No conflicts.
Unified · Split
| @@ -100,6 +100,8 @@ stable kernels. · 99 unmodified lines | |||
| 100 | +----------------+-----------------+-----------------+-----------------------------+ | 100 | +----------------+-----------------+-----------------+-----------------------------+ |
| 101 | | ARM | Cortex-A510 | #2051678 | ARM64_ERRATUM_2051678 | | 101 | | ARM | Cortex-A510 | #2051678 | ARM64_ERRATUM_2051678 | |
| 102 | +----------------+-----------------+-----------------+-----------------------------+ | 102 | +----------------+-----------------+-----------------+-----------------------------+ |
| 103 | | ARM | Cortex-A510 | #2077057 | ARM64_ERRATUM_2077057 | | ||
| 104 | +----------------+-----------------+-----------------+-----------------------------+ | ||
| 103 | | ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 | | 105 | | ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 | |
| 104 | +----------------+-----------------+-----------------+-----------------------------+ | 106 | +----------------+-----------------+-----------------+-----------------------------+ |
| 105 | | ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 | | 107 | | ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 | |
| @@ -242,7 +242,7 @@ example: · 241 unmodified lines | |||
| 242 | 242 | ||
| 243 | int rectangle_area(struct shape *this) | 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 | return self->length * self->width; | 247 | return self->length * self->width; |
| 248 | }; | 248 | }; |
| @@ -462,6 +462,10 @@ operation table looks like the following:: · 461 unmodified lines | |||
| 462 | struct iov_iter *iter, | 462 | struct iov_iter *iter, |
| 463 | netfs_io_terminated_t term_func, | 463 | netfs_io_terminated_t term_func, |
| 464 | void *term_func_priv); | 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 | With a termination handler function pointer:: | 471 | With a termination handler function pointer:: |
| @@ -536,6 +540,18 @@ The methods defined in the table are: · 68 unmodified lines | |||
| 536 | indicating whether the termination is definitely happening in the caller's | 540 | indicating whether the termination is definitely happening in the caller's |
| 537 | context. | 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 | Note that these methods are passed a pointer to the cache resource structure, | 555 | Note that these methods are passed a pointer to the cache resource structure, |
| 540 | not the read request structure as they could be used in other situations where | 556 | not the read request structure as they could be used in other situations where |
| 541 | there isn't a read request structure as well, such as writing dirty data to the | 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 | Level: Advanced | 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 | idr_init_base() | 303 | idr_init_base() |
| 328 | --------------- | 304 | --------------- |
| 329 | 305 | ||
| @@ -115,6 +115,7 @@ Code Seq# Include File Comments · 114 unmodified lines | |||
| 115 | 'B' 00-1F linux/cciss_ioctl.h conflict! | 115 | 'B' 00-1F linux/cciss_ioctl.h conflict! |
| 116 | 'B' 00-0F include/linux/pmu.h conflict! | 116 | 'B' 00-0F include/linux/pmu.h conflict! |
| 117 | 'B' C0-FF advanced bbus <mailto:maassen@uni-freiburg.de> | 117 | 'B' C0-FF advanced bbus <mailto:maassen@uni-freiburg.de> |
| 118 | 'B' 00-0F xen/xenbus_dev.h conflict! | ||
| 118 | 'C' all linux/soundcard.h conflict! | 119 | 'C' all linux/soundcard.h conflict! |
| 119 | 'C' 01-2F linux/capi.h conflict! | 120 | 'C' 01-2F linux/capi.h conflict! |
| 120 | 'C' F0-FF drivers/net/wan/cosa.h conflict! | 121 | 'C' F0-FF drivers/net/wan/cosa.h conflict! |
| @@ -134,6 +135,7 @@ Code Seq# Include File Comments · 13 unmodified lines | |||
| 134 | 'F' 80-8F linux/arcfb.h conflict! | 135 | 'F' 80-8F linux/arcfb.h conflict! |
| 135 | 'F' DD video/sstfb.h conflict! | 136 | 'F' DD video/sstfb.h conflict! |
| 136 | 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! | 137 | 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! |
| 138 | 'G' 00-0F xen/gntalloc.h, xen/gntdev.h conflict! | ||
| 137 | 'H' 00-7F linux/hiddev.h conflict! | 139 | 'H' 00-7F linux/hiddev.h conflict! |
| 138 | 'H' 00-0F linux/hidraw.h conflict! | 140 | 'H' 00-0F linux/hidraw.h conflict! |
| 139 | 'H' 01 linux/mei.h conflict! | 141 | 'H' 01 linux/mei.h conflict! |
| @@ -176,6 +178,7 @@ Code Seq# Include File Comments · 36 unmodified lines | |||
| 176 | 'P' 60-6F sound/sscape_ioctl.h conflict! | 178 | 'P' 60-6F sound/sscape_ioctl.h conflict! |
| 177 | 'P' 00-0F drivers/usb/class/usblp.c conflict! | 179 | 'P' 00-0F drivers/usb/class/usblp.c conflict! |
| 178 | 'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! | 180 | 'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! |
| 181 | 'P' 00-0F xen/privcmd.h conflict! | ||
| 179 | 'Q' all linux/soundcard.h | 182 | 'Q' all linux/soundcard.h |
| 180 | 'R' 00-1F linux/random.h conflict! | 183 | 'R' 00-1F linux/random.h conflict! |
| 181 | 'R' 01 linux/rfkill.h conflict! | 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 | F: drivers/ata/pata_arasan_cf.c | 10881 | F: drivers/ata/pata_arasan_cf.c |
| 10882 | F: include/linux/pata_arasan_cf_data.h | 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 | LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS | 10890 | LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS |
| 10885 | M: Linus Walleij <linus.walleij@linaro.org> | 10891 | M: Linus Walleij <linus.walleij@linaro.org> |
| 10886 | L: linux-ide@vger.kernel.org | 10892 | L: linux-ide@vger.kernel.org |
| @@ -12401,7 +12407,7 @@ F: include/uapi/linux/membarrier.h · 1514 unmodified lines | |||
| 12401 | F: kernel/sched/membarrier.c | 12407 | F: kernel/sched/membarrier.c |
| 12402 | 12408 | ||
| 12403 | MEMBLOCK | 12409 | MEMBLOCK |
| 12404 | M: Mike Rapoport <rppt@linux.ibm.com> | 12410 | M: Mike Rapoport <rppt@kernel.org> |
| 12405 | L: linux-mm@kvack.org | 12411 | L: linux-mm@kvack.org |
| 12406 | S: Maintained | 12412 | S: Maintained |
| 12407 | F: Documentation/core-api/boot-time-mm.rst | 12413 | F: Documentation/core-api/boot-time-mm.rst |
| @@ -13299,8 +13305,8 @@ W: http://www.iptables.org/ · 891 unmodified lines | |||
| 13299 | W: http://www.nftables.org/ | 13305 | W: http://www.nftables.org/ |
| 13300 | Q: http://patchwork.ozlabs.org/project/netfilter-devel/list/ | 13306 | Q: http://patchwork.ozlabs.org/project/netfilter-devel/list/ |
| 13301 | C: irc://irc.libera.chat/netfilter | 13307 | C: irc://irc.libera.chat/netfilter |
| 13302 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git | 13308 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git |
| 13303 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git | 13309 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next.git |
| 13304 | F: include/linux/netfilter* | 13310 | F: include/linux/netfilter* |
| 13305 | F: include/linux/netfilter/ | 13311 | F: include/linux/netfilter/ |
| 13306 | F: include/net/netfilter/ | 13312 | F: include/net/netfilter/ |
| @@ -13567,7 +13573,7 @@ F: tools/testing/selftests/nci/ · 260 unmodified lines | |||
| 13567 | 13573 | ||
| 13568 | NFS, SUNRPC, AND LOCKD CLIENTS | 13574 | NFS, SUNRPC, AND LOCKD CLIENTS |
| 13569 | M: Trond Myklebust <trond.myklebust@hammerspace.com> | 13575 | M: Trond Myklebust <trond.myklebust@hammerspace.com> |
| 13570 | M: Anna Schumaker <anna.schumaker@netapp.com> | 13576 | M: Anna Schumaker <anna@kernel.org> |
| 13571 | L: linux-nfs@vger.kernel.org | 13577 | L: linux-nfs@vger.kernel.org |
| 13572 | S: Maintained | 13578 | S: Maintained |
| 13573 | W: http://client.linux-nfs.org | 13579 | W: http://client.linux-nfs.org |
| @@ -16469,6 +16475,14 @@ F: Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml · 2895 unmodified lines | |||
| 16469 | F: drivers/i2c/busses/i2c-rcar.c | 16475 | F: drivers/i2c/busses/i2c-rcar.c |
| 16470 | F: drivers/i2c/busses/i2c-sh_mobile.c | 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 | RENESAS R-CAR THERMAL DRIVERS | 16486 | RENESAS R-CAR THERMAL DRIVERS |
| 16473 | M: Niklas Söderlund <niklas.soderlund@ragnatech.se> | 16487 | M: Niklas Söderlund <niklas.soderlund@ragnatech.se> |
| 16474 | L: linux-renesas-soc@vger.kernel.org | 16488 | L: linux-renesas-soc@vger.kernel.org |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 5 | 2 | VERSION = 5 |
| 3 | PATCHLEVEL = 17 | 3 | PATCHLEVEL = 17 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc2 | 5 | EXTRAVERSION = -rc3 |
| 6 | NAME = Gobble Gobble | 6 | NAME = Gobble Gobble |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -13,12 +13,12 @@ · 12 unmodified lines | |||
| 13 | static int crypto_blake2s_update_arm(struct shash_desc *desc, | 13 | static int crypto_blake2s_update_arm(struct shash_desc *desc, |
| 14 | const u8 *in, unsigned int inlen) | 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 | static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out) | 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 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ | 24 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ |
| @@ -680,6 +680,22 @@ config ARM64_ERRATUM_2051678 · 679 unmodified lines | |||
| 680 | 680 | ||
| 681 | If unsure, say Y. | 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 | config ARM64_ERRATUM_2119858 | 699 | config ARM64_ERRATUM_2119858 |
| 684 | bool "Cortex-A710/X2: 2119858: workaround TRBE overwriting trace data in FILL mode" | 700 | bool "Cortex-A710/X2: 2119858: workaround TRBE overwriting trace data in FILL mode" |
| 685 | default y | 701 | default y |
| @@ -600,6 +600,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { · 599 unmodified lines | |||
| 600 | CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus), | 600 | CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus), |
| 601 | }, | 601 | }, |
| 602 | #endif | 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 | #ifdef CONFIG_ARM64_ERRATUM_2064142 | 611 | #ifdef CONFIG_ARM64_ERRATUM_2064142 |
| 604 | { | 612 | { |
| 605 | .desc = "ARM erratum 2064142", | 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 | xfer_to_guest_mode_work_pending(); | 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 | * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code | 819 | * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code |
| 802 | * @vcpu: The VCPU pointer | 820 | * @vcpu: The VCPU pointer |
| @@ -881,9 +899,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 78 unmodified lines | |||
| 881 | * Enter the guest | 899 | * Enter the guest |
| 882 | */ | 900 | */ |
| 883 | trace_kvm_entry(*vcpu_pc(vcpu)); | 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 | vcpu->mode = OUTSIDE_GUEST_MODE; | 906 | vcpu->mode = OUTSIDE_GUEST_MODE; |
| 889 | vcpu->stat.exits++; | 907 | vcpu->stat.exits++; |
| @@ -918,26 +936,23 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 28 unmodified lines | |||
| 918 | kvm_arch_vcpu_ctxsync_fp(vcpu); | 936 | kvm_arch_vcpu_ctxsync_fp(vcpu); |
| 919 | 937 | ||
| 920 | /* | 938 | /* |
| 921 | * We may have taken a host interrupt in HYP mode (ie | 939 | * We must ensure that any pending interrupts are taken before |
| 922 | * while executing the guest). This interrupt is still | 940 | * we exit guest timing so that timer ticks are accounted as |
| 923 | * pending, as we haven't serviced it yet! | 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 | 944 | * Per ARM DDI 0487G.b section D1.13.4, an ISB (or other |
| 926 | * disabled. Enabling the interrupts now will have | 945 | * context synchronization event) is necessary to ensure that |
| 927 | * the effect of taking the interrupt again, in SVC | 946 | * pending interrupts are taken. |
| 928 | * mode this time. | ||
| 929 | */ | 947 | */ |
| 930 | local_irq_enable(); | 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 | trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); | 956 | trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); |
| 942 | 957 | ||
| 943 | /* Exit types that need handling before we can be preempted */ | 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 | struct kvm_run *run = vcpu->run; | 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 | exception_index = ARM_EXCEPTION_CODE(exception_index); | 239 | exception_index = ARM_EXCEPTION_CODE(exception_index); |
| 232 | 240 | ||
| 233 | switch (exception_index) { | 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 | return false; | 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 | * Return true when we were able to fixup the guest exit and should return to | 424 | * Return true when we were able to fixup the guest exit and should return to |
| 407 | * the guest, false when we should restore the host state and return to the | 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 | * Save PSTATE early so that we can evaluate the vcpu mode | 431 | * Save PSTATE early so that we can evaluate the vcpu mode |
| 414 | * early on. | 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 | * Check whether we want to repaint the state one way or | 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 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) | 442 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| 425 | vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); | 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 | u8 esr_ec = kvm_vcpu_trap_get_class(vcpu); | 447 | u8 esr_ec = kvm_vcpu_trap_get_class(vcpu); |
| 429 | 448 | ||
| 430 | /* | 449 | /* |
| @@ -55,9 +55,10 @@ WORKAROUND_1418040 · 54 unmodified lines | |||
| 55 | WORKAROUND_1463225 | 55 | WORKAROUND_1463225 |
| 56 | WORKAROUND_1508412 | 56 | WORKAROUND_1508412 |
| 57 | WORKAROUND_1542419 | 57 | WORKAROUND_1542419 |
| 58 | WORKAROUND_2064142 | ||
| 59 | WORKAROUND_2038923 | ||
| 60 | WORKAROUND_1902691 | 58 | WORKAROUND_1902691 |
| 59 | WORKAROUND_2038923 | ||
| 60 | WORKAROUND_2064142 | ||
| 61 | WORKAROUND_2077057 | ||
| 61 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE | 62 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE |
| 62 | WORKAROUND_TSB_FLUSH_FAILURE | 63 | WORKAROUND_TSB_FLUSH_FAILURE |
| 63 | WORKAROUND_TRBE_WRITE_OUT_OF_RANGE | 64 | WORKAROUND_TRBE_WRITE_OUT_OF_RANGE |
| @@ -83,6 +83,8 @@ · 82 unmodified lines | |||
| 83 | label = "HDMI OUT"; | 83 | label = "HDMI OUT"; |
| 84 | type = "a"; | 84 | type = "a"; |
| 85 | 85 | ||
| 86 | ddc-en-gpios = <&gpa 25 GPIO_ACTIVE_HIGH>; | ||
| 87 | |||
| 86 | port { | 88 | port { |
| 87 | hdmi_con: endpoint { | 89 | hdmi_con: endpoint { |
| 88 | remote-endpoint = <&dw_hdmi_out>; | 90 | remote-endpoint = <&dw_hdmi_out>; |
| @@ -114,17 +116,6 @@ · 25 unmodified lines | |||
| 114 | gpio = <&gpf 14 GPIO_ACTIVE_LOW>; | 116 | gpio = <&gpf 14 GPIO_ACTIVE_LOW>; |
| 115 | enable-active-high; | 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 | &ext { | 121 | &ext { |
| @@ -576,8 +567,6 @@ · 445 unmodified lines | |||
| 576 | pinctrl-names = "default"; | 567 | pinctrl-names = "default"; |
| 577 | pinctrl-0 = <&pins_hdmi_ddc>; | 568 | pinctrl-0 = <&pins_hdmi_ddc>; |
| 578 | 569 | ||
| 579 | hdmi-5v-supply = <&hdmi_power>; | ||
| 580 | |||
| 581 | ports { | 570 | ports { |
| 582 | #address-cells = <1>; | 571 | #address-cells = <1>; |
| 583 | #size-cells = <0>; | 572 | #size-cells = <0>; |
| @@ -414,6 +414,24 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, · 413 unmodified lines | |||
| 414 | return -ENOIOCTLCMD; | 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 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) | 435 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) |
| 418 | { | 436 | { |
| 419 | int r = -EINTR; | 437 | int r = -EINTR; |
| @@ -434,7 +452,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 14 unmodified lines | |||
| 434 | lose_fpu(1); | 452 | lose_fpu(1); |
| 435 | 453 | ||
| 436 | local_irq_disable(); | 454 | local_irq_disable(); |
| 437 | guest_enter_irqoff(); | 455 | guest_timing_enter_irqoff(); |
| 438 | trace_kvm_enter(vcpu); | 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 | smp_store_mb(vcpu->mode, IN_GUEST_MODE); | 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 | trace_kvm_out(vcpu); | 481 | trace_kvm_out(vcpu); |
| 451 | guest_exit_irqoff(); | 482 | guest_timing_exit_irqoff(); |
| 452 | local_irq_enable(); | 483 | local_irq_enable(); |
| 453 | 484 | ||
| 454 | out: | 485 | out: |
| @@ -1168,7 +1199,7 @@ static void kvm_mips_set_c0_status(void) · 713 unmodified lines | |||
| 1168 | /* | 1199 | /* |
| 1169 | * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV) | 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 | struct kvm_run *run = vcpu->run; | 1204 | struct kvm_run *run = vcpu->run; |
| 1174 | u32 cause = vcpu->arch.host_cp0_cause; | 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 | return ret; | 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 | /* Enable FPU for guest and restore context */ | 1402 | /* Enable FPU for guest and restore context */ |
| 1361 | void kvm_own_fpu(struct kvm_vcpu *vcpu) | 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 | int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) | 90 | int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) |
| 91 | { | 91 | { |
| 92 | struct kvm_cpu_context *cntx; | 92 | struct kvm_cpu_context *cntx; |
| 93 | struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr; | ||
| 93 | 94 | ||
| 94 | /* Mark this VCPU never ran */ | 95 | /* Mark this VCPU never ran */ |
| 95 | vcpu->arch.ran_atleast_once = false; | 96 | vcpu->arch.ran_atleast_once = false; |
| @@ -106,6 +107,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · 10 unmodified lines | |||
| 106 | cntx->hstatus |= HSTATUS_SPVP; | 107 | cntx->hstatus |= HSTATUS_SPVP; |
| 107 | cntx->hstatus |= HSTATUS_SPV; | 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 | /* Setup VCPU timer */ | 113 | /* Setup VCPU timer */ |
| 110 | kvm_riscv_vcpu_timer_init(vcpu); | 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 | csr_write(CSR_HVIP, csr->hvip); | 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 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) | 720 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) |
| 703 | { | 721 | { |
| 704 | int ret; | 722 | int ret; |
| @@ -790,9 +808,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 85 unmodified lines | |||
| 790 | continue; | 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 | vcpu->mode = OUTSIDE_GUEST_MODE; | 815 | vcpu->mode = OUTSIDE_GUEST_MODE; |
| 798 | vcpu->stat.exits++; | 816 | vcpu->stat.exits++; |
| @@ -812,25 +830,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 13 unmodified lines | |||
| 812 | kvm_riscv_vcpu_sync_interrupts(vcpu); | 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. | 833 | * We must ensure that any pending interrupts are taken before |
| 816 | * while executing the guest). This interrupt is still | 834 | * we exit guest timing so that timer ticks are accounted as |
| 817 | * pending, as we haven't serviced it yet! | 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 | 838 | * There's no barrier which ensures that pending interrupts are |
| 820 | * so enabling the interrupts now will have the effect | 839 | * recognised, so we just hope that the CPU takes any pending |
| 821 | * of taking the interrupt again, in HS-mode this time. | 840 | * interrupts between the enable and disable. |
| 822 | */ | 841 | */ |
| 823 | local_irq_enable(); | 842 | local_irq_enable(); |
| 843 | local_irq_disable(); | ||
| 824 | 844 | ||
| 825 | /* | 845 | guest_timing_exit_irqoff(); |
| 826 | * We do local_irq_enable() before calling guest_exit() so | 846 | |
| 827 | * that if a timer interrupt hits while running the guest | 847 | local_irq_enable(); |
| 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(); | ||
| 834 | 848 | ||
| 835 | preempt_enable(); | 849 | preempt_enable(); |
| 836 | 850 | ||
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
| 10 | #include <linux/err.h> | 10 | #include <linux/err.h> |
| 11 | #include <linux/kvm_host.h> | 11 | #include <linux/kvm_host.h> |
| 12 | #include <linux/version.h> | ||
| 12 | #include <asm/csr.h> | 13 | #include <asm/csr.h> |
| 13 | #include <asm/sbi.h> | 14 | #include <asm/sbi.h> |
| 14 | #include <asm/kvm_vcpu_timer.h> | 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 | *out_val = KVM_SBI_IMPID; | 33 | *out_val = KVM_SBI_IMPID; |
| 33 | break; | 34 | break; |
| 34 | case SBI_EXT_BASE_GET_IMP_VERSION: | 35 | case SBI_EXT_BASE_GET_IMP_VERSION: |
| 35 | *out_val = 0; | 36 | *out_val = LINUX_VERSION_CODE; |
| 36 | break; | 37 | break; |
| 37 | case SBI_EXT_BASE_PROBE_EXT: | 38 | case SBI_EXT_BASE_PROBE_EXT: |
| 38 | if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START && | 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 | return -EINVAL; | 4667 | return -EINVAL; |
| 4668 | if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block)) | 4668 | if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block)) |
| 4669 | return -E2BIG; | 4669 | return -E2BIG; |
| 4670 | if (!kvm_s390_pv_cpu_is_protected(vcpu)) | ||
| 4671 | return -EINVAL; | ||
| 4670 | 4672 | ||
| 4671 | switch (mop->op) { | 4673 | switch (mop->op) { |
| 4672 | case KVM_S390_MEMOP_SIDA_READ: | 4674 | case KVM_S390_MEMOP_SIDA_READ: |
| @@ -18,12 +18,12 @@ · 17 unmodified lines | |||
| 18 | static int crypto_blake2s_update_x86(struct shash_desc *desc, | 18 | static int crypto_blake2s_update_x86(struct shash_desc *desc, |
| 19 | const u8 *in, unsigned int inlen) | 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 | static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out) | 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 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ | 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 | .lbr_read = intel_pmu_lbr_read_64, | 4703 | .lbr_read = intel_pmu_lbr_read_64, |
| 4704 | .lbr_save = intel_pmu_lbr_save, | 4704 | .lbr_save = intel_pmu_lbr_save, |
| 4705 | .lbr_restore = intel_pmu_lbr_restore, | 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 | static __init void intel_clovertown_quirk(void) | 4721 | static __init void intel_clovertown_quirk(void) |
| @@ -897,8 +897,9 @@ static void pt_handle_status(struct pt *pt) · 896 unmodified lines | |||
| 897 | * means we are already losing data; need to let the decoder | 897 | * means we are already losing data; need to let the decoder |
| 898 | * know. | 898 | * know. |
| 899 | */ | 899 | */ |
| 900 | if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || | 900 | if (!buf->single && |
| 901 | buf->output_off == pt_buffer_region_size(buf)) { | 901 | (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || |
| 902 | buf->output_off == pt_buffer_region_size(buf))) { | ||
| 902 | perf_aux_output_flag(&pt->handle, | 903 | perf_aux_output_flag(&pt->handle, |
| 903 | PERF_AUX_FLAG_TRUNCATED); | 904 | PERF_AUX_FLAG_TRUNCATED); |
| 904 | advance++; | 905 | advance++; |
| @@ -82,7 +82,7 @@ KVM_X86_OP_NULL(guest_apic_has_interrupt) · 81 unmodified lines | |||
| 82 | KVM_X86_OP(load_eoi_exitmap) | 82 | KVM_X86_OP(load_eoi_exitmap) |
| 83 | KVM_X86_OP(set_virtual_apic_mode) | 83 | KVM_X86_OP(set_virtual_apic_mode) |
| 84 | KVM_X86_OP_NULL(set_apic_access_page_addr) | 84 | KVM_X86_OP_NULL(set_apic_access_page_addr) |
| 85 | KVM_X86_OP(deliver_posted_interrupt) | 85 | KVM_X86_OP(deliver_interrupt) |
| 86 | KVM_X86_OP_NULL(sync_pir_to_irr) | 86 | KVM_X86_OP_NULL(sync_pir_to_irr) |
| 87 | KVM_X86_OP(set_tss_addr) | 87 | KVM_X86_OP(set_tss_addr) |
| 88 | KVM_X86_OP(set_identity_map_addr) | 88 | KVM_X86_OP(set_identity_map_addr) |
| @@ -1410,7 +1410,8 @@ struct kvm_x86_ops { · 1409 unmodified lines | |||
| 1410 | void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); | 1410 | void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); |
| 1411 | void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); | 1411 | void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); |
| 1412 | void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu); | 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 | int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); | 1415 | int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); |
| 1415 | int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); | 1416 | int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); |
| 1416 | int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr); | 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 | return hypervisor_cpuid_base("XenVMMXenVMM", 2); | 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 | struct pci_dev; | 46 | struct pci_dev; |
| 61 | 47 | ||
| 62 | #ifdef CONFIG_XEN_PV_DOM0 | 48 | #ifdef CONFIG_XEN_PV_DOM0 |
| @@ -554,12 +554,13 @@ void kvm_set_cpu_caps(void) · 553 unmodified lines | |||
| 554 | ); | 554 | ); |
| 555 | 555 | ||
| 556 | kvm_cpu_cap_mask(CPUID_7_0_EBX, | 556 | kvm_cpu_cap_mask(CPUID_7_0_EBX, |
| 557 | F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | | 557 | F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | |
| 558 | F(BMI2) | F(ERMS) | F(INVPCID) | F(RTM) | 0 /*MPX*/ | F(RDSEED) | | 558 | F(FDP_EXCPTN_ONLY) | F(SMEP) | F(BMI2) | F(ERMS) | F(INVPCID) | |
| 559 | F(ADX) | F(SMAP) | F(AVX512IFMA) | F(AVX512F) | F(AVX512PF) | | 559 | F(RTM) | F(ZERO_FCS_FDS) | 0 /*MPX*/ | F(AVX512F) | |
| 560 | F(AVX512ER) | F(AVX512CD) | F(CLFLUSHOPT) | F(CLWB) | F(AVX512DQ) | | 560 | F(AVX512DQ) | F(RDSEED) | F(ADX) | F(SMAP) | F(AVX512IFMA) | |
| 561 | F(SHA_NI) | F(AVX512BW) | F(AVX512VL) | 0 /*INTEL_PT*/ | 561 | F(CLFLUSHOPT) | F(CLWB) | 0 /*INTEL_PT*/ | F(AVX512PF) | |
| 562 | ); | 562 | F(AVX512ER) | F(AVX512CD) | F(SHA_NI) | F(AVX512BW) | |
| 563 | F(AVX512VL)); | ||
| 563 | 564 | ||
| 564 | kvm_cpu_cap_mask(CPUID_7_ECX, | 565 | kvm_cpu_cap_mask(CPUID_7_ECX, |
| 565 | F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | | 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 | apic->regs + APIC_TMR); | 1096 | apic->regs + APIC_TMR); |
| 1097 | } | 1097 | } |
| 1098 | 1098 | ||
| 1099 | if (static_call(kvm_x86_deliver_posted_interrupt)(vcpu, vector)) { | 1099 | static_call(kvm_x86_deliver_interrupt)(apic, delivery_mode, |
| 1100 | kvm_lapic_set_irr(vector, apic); | 1100 | trig_mode, vector); |
| 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 | } | ||
| 1107 | break; | 1101 | break; |
| 1108 | 1102 | ||
| 1109 | case APIC_DM_REMRD: | 1103 | case APIC_DM_REMRD: |
| @@ -3291,6 +3291,21 @@ static void svm_set_irq(struct kvm_vcpu *vcpu) · 3290 unmodified lines | |||
| 3291 | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR; | 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 | static void svm_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) | 3309 | static void svm_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) |
| 3295 | { | 3310 | { |
| 3296 | struct vcpu_svm *svm = to_svm(vcpu); | 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 | struct vcpu_svm *svm = to_svm(vcpu); | 3630 | struct vcpu_svm *svm = to_svm(vcpu); |
| 3616 | unsigned long vmcb_pa = svm->current_vmcb->pa; | 3631 | unsigned long vmcb_pa = svm->current_vmcb->pa; |
| 3617 | 3632 | ||
| 3618 | kvm_guest_enter_irqoff(); | 3633 | guest_state_enter_irqoff(); |
| 3619 | 3634 | ||
| 3620 | if (sev_es_guest(vcpu->kvm)) { | 3635 | if (sev_es_guest(vcpu->kvm)) { |
| 3621 | __svm_sev_es_vcpu_run(vmcb_pa); | 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 | vmload(__sme_page_pa(sd->save_area)); | 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 | static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) | 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 | .pmu_ops = &amd_pmu_ops, | 4560 | .pmu_ops = &amd_pmu_ops, |
| 4546 | .nested_ops = &svm_nested_ops, | 4561 | .nested_ops = &svm_nested_ops, |
| 4547 | 4562 | ||
| 4548 | .deliver_posted_interrupt = svm_deliver_avic_intr, | 4563 | .deliver_interrupt = svm_deliver_interrupt, |
| 4549 | .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt, | 4564 | .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt, |
| 4550 | .update_pi_irte = svm_update_pi_irte, | 4565 | .update_pi_irte = svm_update_pi_irte, |
| 4551 | .setup_mce = svm_setup_mce, | 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 | return 0; | 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 | * Set up the vmcs's constant host-state fields, i.e., host-state fields that | 4060 | * Set up the vmcs's constant host-state fields, i.e., host-state fields that |
| 4046 | * will not change in the lifetime of the guest. | 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 | static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu, | 6769 | static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu, |
| 6755 | struct vcpu_vmx *vmx) | 6770 | struct vcpu_vmx *vmx) |
| 6756 | { | 6771 | { |
| 6757 | kvm_guest_enter_irqoff(); | 6772 | guest_state_enter_irqoff(); |
| 6758 | 6773 | ||
| 6759 | /* L1D Flush includes CPU buffer clear to mitigate MDS */ | 6774 | /* L1D Flush includes CPU buffer clear to mitigate MDS */ |
| 6760 | if (static_branch_unlikely(&vmx_l1d_should_flush)) | 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 | vcpu->arch.cr2 = native_read_cr2(); | 6786 | vcpu->arch.cr2 = native_read_cr2(); |
| 6772 | 6787 | ||
| 6773 | kvm_guest_exit_irqoff(); | 6788 | guest_state_exit_irqoff(); |
| 6774 | } | 6789 | } |
| 6775 | 6790 | ||
| 6776 | static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) | 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 | .hwapic_isr_update = vmx_hwapic_isr_update, | 7783 | .hwapic_isr_update = vmx_hwapic_isr_update, |
| 7769 | .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt, | 7784 | .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt, |
| 7770 | .sync_pir_to_irr = vmx_sync_pir_to_irr, | 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 | .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt, | 7787 | .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt, |
| 7773 | 7788 | ||
| 7774 | .set_tss_addr = vmx_set_tss_addr, | 7789 | .set_tss_addr = vmx_set_tss_addr, |
| @@ -90,6 +90,8 @@ · 89 unmodified lines | |||
| 90 | u64 __read_mostly kvm_mce_cap_supported = MCG_CTL_P | MCG_SER_P; | 90 | u64 __read_mostly kvm_mce_cap_supported = MCG_CTL_P | MCG_SER_P; |
| 91 | EXPORT_SYMBOL_GPL(kvm_mce_cap_supported); | 91 | EXPORT_SYMBOL_GPL(kvm_mce_cap_supported); |
| 92 | 92 | ||
| 93 | #define ERR_PTR_USR(e) ((void __user *)ERR_PTR(e)) | ||
| 94 | |||
| 93 | #define emul_to_vcpu(ctxt) \ | 95 | #define emul_to_vcpu(ctxt) \ |
| 94 | ((struct kvm_vcpu *)(ctxt)->vcpu) | 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 | void __user *uaddr = (void __user*)(unsigned long)attr->addr; | 4342 | void __user *uaddr = (void __user*)(unsigned long)attr->addr; |
| 4341 | 4343 | ||
| 4342 | if ((u64)(unsigned long)uaddr != attr->addr) | 4344 | if ((u64)(unsigned long)uaddr != attr->addr) |
| 4343 | return ERR_PTR(-EFAULT); | 4345 | return ERR_PTR_USR(-EFAULT); |
| 4344 | return uaddr; | 4346 | return uaddr; |
| 4345 | } | 4347 | } |
| 4346 | 4348 | ||
| @@ -10041,6 +10043,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 5694 unmodified lines | |||
| 10041 | set_debugreg(0, 7); | 10043 | set_debugreg(0, 7); |
| 10042 | } | 10044 | } |
| 10043 | 10045 | ||
| 10046 | guest_timing_enter_irqoff(); | ||
| 10047 | |||
| 10044 | for (;;) { | 10048 | for (;;) { |
| 10045 | /* | 10049 | /* |
| 10046 | * Assert that vCPU vs. VM APICv state is consistent. An APICv | 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 | * of accounting via context tracking, but the loss of accuracy is | 10129 | * of accounting via context tracking, but the loss of accuracy is |
| 10126 | * acceptable for all known use cases. | 10130 | * acceptable for all known use cases. |
| 10127 | */ | 10131 | */ |
| 10128 | vtime_account_guest_exit(); | 10132 | guest_timing_exit_irqoff(); |
| 10129 | 10133 | ||
| 10130 | if (lapic_in_kernel(vcpu)) { | 10134 | if (lapic_in_kernel(vcpu)) { |
| 10131 | s64 delta = vcpu->arch.apic->lapic_timer.advance_expire_delta; | 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 | kvm_free_pit(kvm); | 11643 | kvm_free_pit(kvm); |
| 11640 | } | 11644 | } |
| 11641 | 11645 | ||
| 11642 | #define ERR_PTR_USR(e) ((void __user *)ERR_PTR(e)) | ||
| 11643 | |||
| 11644 | /** | 11646 | /** |
| 11645 | * __x86_set_memory_region: Setup KVM internal memory slot | 11647 | * __x86_set_memory_region: Setup KVM internal memory slot |
| 11646 | * | 11648 | * |
| @@ -10,51 +10,6 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | void kvm_spurious_fault(void); | 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 | #define KVM_NESTED_VMENTER_CONSISTENCY_CHECK(consistency_check) \ | 13 | #define KVM_NESTED_VMENTER_CONSISTENCY_CHECK(consistency_check) \ |
| 59 | ({ \ | 14 | ({ \ |
| 60 | bool failed = (consistency_check); \ | 15 | bool failed = (consistency_check); \ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <xen/events.h> | 9 | #include <xen/events.h> |
| 10 | #include <xen/interface/memory.h> | 10 | #include <xen/interface/memory.h> |
| 11 | 11 | ||
| 12 | #include <asm/apic.h> | ||
| 12 | #include <asm/cpu.h> | 13 | #include <asm/cpu.h> |
| 13 | #include <asm/smp.h> | 14 | #include <asm/smp.h> |
| 14 | #include <asm/io_apic.h> | 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 | early_param("xen_no_vector_callback", xen_parse_no_vector_callback); | 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 x2apic_supported(); |
| 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; | ||
| 254 | } | 249 | } |
| 255 | 250 | ||
| 256 | static __init void xen_hvm_guest_late_init(void) | 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 | .detect = xen_platform_hvm, | 307 | .detect = xen_platform_hvm, |
| 313 | .type = X86_HYPER_XEN_HVM, | 308 | .type = X86_HYPER_XEN_HVM, |
| 314 | .init.init_platform = xen_hvm_guest_init, | 309 | .init.init_platform = xen_hvm_guest_init, |
| 315 | .init.x2apic_available = xen_x2apic_para_available, | 310 | .init.x2apic_available = xen_x2apic_available, |
| 316 | .init.init_mem_mapping = xen_hvm_init_mem_mapping, | 311 | .init.init_mem_mapping = xen_hvm_init_mem_mapping, |
| 317 | .init.guest_late_init = xen_hvm_guest_late_init, | 312 | .init.guest_late_init = xen_hvm_guest_late_init, |
| 318 | .runtime.pin_vcpu = xen_pin_vcpu, | 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 | xen_acpi_sleep_register(); | 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 | xen_boot_params_init_edd(); | 1344 | xen_boot_params_init_edd(); |
| 1349 | 1345 | ||
| 1350 | #ifdef CONFIG_ACPI | 1346 | #ifdef CONFIG_ACPI |
| @@ -148,28 +148,12 @@ int xen_smp_intr_init_pv(unsigned int cpu) · 147 unmodified lines | |||
| 148 | return rc; | 148 | return rc; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static void __init xen_fill_possible_map(void) | 151 | static void __init _get_smp_config(unsigned int early) |
| 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) | ||
| 168 | { | 152 | { |
| 169 | int i, rc; | 153 | int i, rc; |
| 170 | unsigned int subtract = 0; | 154 | unsigned int subtract = 0; |
| 171 | 155 | ||
| 172 | if (!xen_initial_domain()) | 156 | if (early) |
| 173 | return; | 157 | return; |
| 174 | 158 | ||
| 175 | num_processors = 0; | 159 | num_processors = 0; |
| @@ -210,7 +194,6 @@ static void __init xen_pv_smp_prepare_boot_cpu(void) · 34 unmodified lines | |||
| 210 | * sure the old memory can be recycled. */ | 194 | * sure the old memory can be recycled. */ |
| 211 | make_lowmem_page_readwrite(xen_initial_gdt); | 195 | make_lowmem_page_readwrite(xen_initial_gdt); |
| 212 | 196 | ||
| 213 | xen_filter_cpu_maps(); | ||
| 214 | xen_setup_vcpu_info_placement(); | 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 | void __init xen_smp_init(void) | 459 | void __init xen_smp_init(void) |
| 477 | { | 460 | { |
| 478 | smp_ops = xen_smp_ops; | 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 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | 373 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); |
| 374 | unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); | 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 | bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); | 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 | struct block_device *bdev = iocb->ki_filp->private_data; | 567 | struct block_device *bdev = iocb->ki_filp->private_data; |
| 568 | loff_t size = bdev_nr_bytes(bdev); | 568 | loff_t size = bdev_nr_bytes(bdev); |
| 569 | size_t count = iov_iter_count(to); | ||
| 570 | loff_t pos = iocb->ki_pos; | 569 | loff_t pos = iocb->ki_pos; |
| 571 | size_t shorted = 0; | 570 | size_t shorted = 0; |
| 572 | ssize_t ret = 0; | 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 | if (pos >= size) | 575 | if (pos >= size) |
| 576 | return 0; | 576 | return 0; |
| 577 | size -= pos; | 577 | size -= pos; |
| 578 | if (count > size) { | 578 | shorted = iov_iter_count(to) - size; |
| 579 | shorted = count - size; | 579 | iov_iter_truncate(to, size); |
| 580 | iov_iter_truncate(to, size); | ||
| 581 | } | ||
| 582 | } | 580 | } |
| 583 | 581 | ||
| 582 | count = iov_iter_count(to); | ||
| 583 | if (!count) | ||
| 584 | goto reexpand; /* skip atime */ | ||
| 585 | |||
| 584 | if (iocb->ki_flags & IOCB_DIRECT) { | 586 | if (iocb->ki_flags & IOCB_DIRECT) { |
| 585 | struct address_space *mapping = iocb->ki_filp->f_mapping; | 587 | struct address_space *mapping = iocb->ki_filp->f_mapping; |
| 586 | 588 | ||
| 587 | if (iocb->ki_flags & IOCB_NOWAIT) { | 589 | if (iocb->ki_flags & IOCB_NOWAIT) { |
| 588 | if (filemap_range_needs_writeback(mapping, iocb->ki_pos, | 590 | if (filemap_range_needs_writeback(mapping, pos, |
| 589 | iocb->ki_pos + count - 1)) | 591 | pos + count - 1)) { |
| 590 | return -EAGAIN; | 592 | ret = -EAGAIN; |
| 593 | goto reexpand; | ||
| 594 | } | ||
| 591 | } else { | 595 | } else { |
| 592 | ret = filemap_write_and_wait_range(mapping, | 596 | ret = filemap_write_and_wait_range(mapping, pos, |
| 593 | iocb->ki_pos, | 597 | pos + count - 1); |
| 594 | iocb->ki_pos + count - 1); | ||
| 595 | if (ret < 0) | 598 | if (ret < 0) |
| 596 | return ret; | 599 | goto reexpand; |
| 597 | } | 600 | } |
| 598 | 601 | ||
| 599 | file_accessed(iocb->ki_filp); | 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 | iocb->ki_pos += ret; | 606 | iocb->ki_pos += ret; |
| 604 | count -= ret; | 607 | count -= ret; |
| 605 | } | 608 | } |
| 609 | iov_iter_revert(to, count - iov_iter_count(to)); | ||
| 606 | if (ret < 0 || !count) | 610 | if (ret < 0 || !count) |
| 607 | return ret; | 611 | goto reexpand; |
| 608 | } | 612 | } |
| 609 | 613 | ||
| 610 | ret = filemap_read(iocb, to, ret); | 614 | ret = filemap_read(iocb, to, ret); |
| 611 | 615 | ||
| 616 | reexpand: | ||
| 612 | if (unlikely(shorted)) | 617 | if (unlikely(shorted)) |
| 613 | iov_iter_reexpand(to, iov_iter_count(to) + shorted); | 618 | iov_iter_reexpand(to, iov_iter_count(to) + shorted); |
| 614 | return ret; | 619 | return ret; |
| @@ -1324,3 +1324,4 @@ module_exit(crypto_algapi_exit); · 1323 unmodified lines | |||
| 1324 | 1324 | ||
| 1325 | MODULE_LICENSE("GPL"); | 1325 | MODULE_LICENSE("GPL"); |
| 1326 | MODULE_DESCRIPTION("Cryptographic algorithms API"); | 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 | MODULE_DESCRIPTION("Cryptographic core API"); | 644 | MODULE_DESCRIPTION("Cryptographic core API"); |
| 645 | MODULE_LICENSE("GPL"); | 645 | MODULE_LICENSE("GPL"); |
| 646 | MODULE_SOFTDEP("pre: cryptomgr"); | ||
| @@ -15,12 +15,12 @@ · 14 unmodified lines | |||
| 15 | static int crypto_blake2s_update_generic(struct shash_desc *desc, | 15 | static int crypto_blake2s_update_generic(struct shash_desc *desc, |
| 16 | const u8 *in, unsigned int inlen) | 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 | static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out) | 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 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ | 26 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ |
| @@ -11,6 +11,7 @@ menuconfig ACPI · 10 unmodified lines | |||
| 11 | depends on ARCH_SUPPORTS_ACPI | 11 | depends on ARCH_SUPPORTS_ACPI |
| 12 | select PNP | 12 | select PNP |
| 13 | select NLS | 13 | select NLS |
| 14 | select CRC32 | ||
| 14 | default y if X86 | 15 | default y if X86 |
| 15 | help | 16 | help |
| 16 | Advanced Configuration and Power Interface (ACPI) support for | 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 | struct ata_port *ap = dev->link->ap; | 2008 | struct ata_port *ap = dev->link->ap; |
| 2009 | 2009 | ||
| 2010 | if (dev->horkage & ATA_HORKAGE_NO_LOG_DIR) | ||
| 2011 | return false; | ||
| 2012 | |||
| 2010 | if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) | 2013 | if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) |
| 2011 | return false; | 2014 | return false; |
| 2012 | return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false; | 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 | struct ata_cpr_log *cpr_log = NULL; | 2448 | struct ata_cpr_log *cpr_log = NULL; |
| 2446 | u8 *desc, *buf = NULL; | 2449 | u8 *desc, *buf = NULL; |
| 2447 | 2450 | ||
| 2448 | if (!ata_identify_page_supported(dev, | 2451 | if (ata_id_major_version(dev->id) < 11 || |
| 2449 | ATA_LOG_CONCURRENT_POSITIONING_RANGES)) | 2452 | !ata_log_supported(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES)) |
| 2450 | goto out; | 2453 | goto out; |
| 2451 | 2454 | ||
| 2452 | /* | 2455 | /* |
| 2453 | * Read IDENTIFY DEVICE data log, page 0x47 | 2456 | * Read the concurrent positioning ranges log (0x47). We can have at |
| 2454 | * (concurrent positioning ranges). We can have at most 255 32B range | 2457 | * most 255 32B range descriptors plus a 64B header. |
| 2455 | * descriptors plus a 64B header. | ||
| 2456 | */ | 2458 | */ |
| 2457 | buf_len = (64 + 255 * 32 + 511) & ~511; | 2459 | buf_len = (64 + 255 * 32 + 511) & ~511; |
| 2458 | buf = kzalloc(buf_len, GFP_KERNEL); | 2460 | buf = kzalloc(buf_len, GFP_KERNEL); |
| 2459 | if (!buf) | 2461 | if (!buf) |
| 2460 | goto out; | 2462 | goto out; |
| 2461 | 2463 | ||
| 2462 | err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, | 2464 | err_mask = ata_read_log_page(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES, |
| 2463 | ATA_LOG_CONCURRENT_POSITIONING_RANGES, | 2465 | 0, buf, buf_len >> 9); |
| 2464 | buf, buf_len >> 9); | ||
| 2465 | if (err_mask) | 2466 | if (err_mask) |
| 2466 | goto out; | 2467 | goto out; |
| 2467 | 2468 | ||
| @@ -4073,6 +4074,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { · 1605 unmodified lines | |||
| 4073 | { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, | 4074 | { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, |
| 4074 | { "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, | 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 | /* End Marker */ | 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 | return arch_init; | 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 | int i; | 767 | int i; |
| 768 | bool arch_init = true; | 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 | rv = random_get_entropy(); | 774 | rv = random_get_entropy(); |
| 775 | arch_init = false; | 775 | arch_init = false; |
| 776 | } | 776 | } |
| 777 | crng->state[i] ^= rv; | 777 | primary_crng.state[i] ^= rv; |
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | return arch_init; | 780 | return arch_init; |
| @@ -788,22 +788,20 @@ static void crng_initialize_secondary(struct crng_state *crng) · 7 unmodified lines | |||
| 788 | crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; | 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); | 793 | _extract_entropy(&primary_crng.state[4], sizeof(u32) * 12); |
| 794 | if (crng_init_try_arch_early(crng) && trust_cpu && crng_init < 2) { | 794 | if (crng_init_try_arch_early() && trust_cpu && crng_init < 2) { |
| 795 | invalidate_batched_entropy(); | 795 | invalidate_batched_entropy(); |
| 796 | numa_crng_init(); | 796 | numa_crng_init(); |
| 797 | crng_init = 2; | 797 | crng_init = 2; |
| 798 | pr_notice("crng init done (trusting CPU's manufacturer)\n"); | 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 | if (!system_wq) { | 805 | if (!system_wq) { |
| 808 | /* We can't call numa_crng_init until we have workqueues, | 806 | /* We can't call numa_crng_init until we have workqueues, |
| 809 | * so mark this for processing later. */ | 807 | * so mark this for processing later. */ |
| @@ -814,6 +812,7 @@ static void crng_finalize_init(struct crng_state *crng) · 4 unmodified lines | |||
| 814 | invalidate_batched_entropy(); | 812 | invalidate_batched_entropy(); |
| 815 | numa_crng_init(); | 813 | numa_crng_init(); |
| 816 | crng_init = 2; | 814 | crng_init = 2; |
| 815 | crng_need_final_init = false; | ||
| 817 | process_random_ready_list(); | 816 | process_random_ready_list(); |
| 818 | wake_up_interruptible(&crng_init_wait); | 817 | wake_up_interruptible(&crng_init_wait); |
| 819 | kill_fasync(&fasync, SIGIO, POLL_IN); | 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 | memzero_explicit(&buf, sizeof(buf)); | 979 | memzero_explicit(&buf, sizeof(buf)); |
| 981 | WRITE_ONCE(crng->init_time, jiffies); | 980 | WRITE_ONCE(crng->init_time, jiffies); |
| 982 | spin_unlock_irqrestore(&crng->lock, flags); | 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 | static void _extract_crng(struct crng_state *crng, u8 out[CHACHA_BLOCK_SIZE]) | 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 | init_std_data(); | 1698 | init_std_data(); |
| 1699 | if (crng_need_final_init) | 1699 | if (crng_need_final_init) |
| 1700 | crng_finalize_init(&primary_crng); | 1700 | crng_finalize_init(); |
| 1701 | crng_initialize_primary(&primary_crng); | 1701 | crng_initialize_primary(); |
| 1702 | crng_global_init_time = jiffies; | 1702 | crng_global_init_time = jiffies; |
| 1703 | if (ratelimit_disable) { | 1703 | if (ratelimit_disable) { |
| 1704 | urandom_warning.interval = 0; | 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 | if (!capable(CAP_SYS_ADMIN)) | 1857 | if (!capable(CAP_SYS_ADMIN)) |
| 1858 | return -EPERM; | 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 | return 0; | 1863 | return 0; |
| 1861 | case RNDRESEEDCRNG: | 1864 | case RNDRESEEDCRNG: |
| 1862 | if (!capable(CAP_SYS_ADMIN)) | 1865 | if (!capable(CAP_SYS_ADMIN)) |
| @@ -2205,13 +2208,15 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, · 342 unmodified lines | |||
| 2205 | return; | 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 | * We'll be woken up again once below random_write_wakeup_thresh, | 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 | !system_wq || kthread_should_stop() || | 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 | mix_pool_bytes(buffer, count); | 2220 | mix_pool_bytes(buffer, count); |
| 2216 | credit_entropy_bits(entropy); | 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 | char engs_info[2 * OTX2_CPT_NAME_LENGTH]; | 1753 | char engs_info[2 * OTX2_CPT_NAME_LENGTH]; |
| 1754 | struct otx2_cpt_eng_grp_info *grp; | 1754 | struct otx2_cpt_eng_grp_info *grp; |
| 1755 | struct otx2_cpt_engs_rsvd *engs; | 1755 | struct otx2_cpt_engs_rsvd *engs; |
| 1756 | u32 mask[4]; | ||
| 1757 | int i, j; | 1756 | int i, j; |
| 1758 | 1757 | ||
| 1759 | pr_debug("Engine groups global info"); | 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 | for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) { | 1784 | for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) { |
| 1786 | engs = &grp->engs[j]; | 1785 | engs = &grp->engs[j]; |
| 1787 | if (engs->type) { | 1786 | if (engs->type) { |
| 1787 | u32 mask[5] = { }; | ||
| 1788 | |||
| 1788 | get_engs_info(grp, engs_info, | 1789 | get_engs_info(grp, engs_info, |
| 1789 | 2 * OTX2_CPT_NAME_LENGTH, j); | 1790 | 2 * OTX2_CPT_NAME_LENGTH, j); |
| 1790 | pr_debug("Slot%d: %s", j, engs_info); | 1791 | pr_debug("Slot%d: %s", j, engs_info); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/xarray.h> | 14 | #include <linux/xarray.h> |
| 15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/nospec.h> | ||
| 17 | #include <linux/uaccess.h> | 18 | #include <linux/uaccess.h> |
| 18 | #include <linux/syscalls.h> | 19 | #include <linux/syscalls.h> |
| 19 | #include <linux/dma-heap.h> | 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 | if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) | 136 | if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) |
| 136 | return -EINVAL; | 137 | return -EINVAL; |
| 137 | 138 | ||
| 139 | nr = array_index_nospec(nr, ARRAY_SIZE(dma_heap_ioctl_cmds)); | ||
| 138 | /* Get the kernel ioctl cmd that matches */ | 140 | /* Get the kernel ioctl cmd that matches */ |
| 139 | kcmd = dma_heap_ioctl_cmds[nr]; | 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 | if (irq < 0) { | 350 | if (irq < 0) { |
| 351 | edac_printk(KERN_ERR, EDAC_MC, | 351 | edac_printk(KERN_ERR, EDAC_MC, |
| 352 | "No irq %d in DT\n", irq); | 352 | "No irq %d in DT\n", irq); |
| 353 | return -ENODEV; | 353 | return irq; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | /* Arria10 has a 2nd IRQ */ | 356 | /* Arria10 has a 2nd IRQ */ |
| @@ -1919,7 +1919,7 @@ static int xgene_edac_probe(struct platform_device *pdev) · 1918 unmodified lines | |||
| 1919 | irq = platform_get_irq_optional(pdev, i); | 1919 | irq = platform_get_irq_optional(pdev, i); |
| 1920 | if (irq < 0) { | 1920 | if (irq < 0) { |
| 1921 | dev_err(&pdev->dev, "No IRQ resource\n"); | 1921 | dev_err(&pdev->dev, "No IRQ resource\n"); |
| 1922 | rc = -EINVAL; | 1922 | rc = irq; |
| 1923 | goto out_err; | 1923 | goto out_err; |
| 1924 | } | 1924 | } |
| 1925 | rc = devm_request_irq(&pdev->dev, irq, | 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 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); | 1408 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); |
| 1409 | 1409 | ||
| 1410 | void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); | 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 | void amdgpu_acpi_detect(void); | 1411 | void amdgpu_acpi_detect(void); |
| 1413 | #else | 1412 | #else |
| 1414 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } | 1413 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } |
| 1415 | static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } | 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 | static inline void amdgpu_acpi_detect(void) { } | 1415 | static inline void amdgpu_acpi_detect(void) { } |
| 1418 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } | 1416 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } |
| 1419 | static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, | 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 | enum amdgpu_ss ss_state) { return 0; } | 1420 | enum amdgpu_ss ss_state) { return 0; } |
| 1423 | #endif | 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 | int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, | 1431 | int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, |
| 1426 | uint64_t addr, struct amdgpu_bo **bo, | 1432 | uint64_t addr, struct amdgpu_bo **bo, |
| 1427 | struct amdgpu_bo_va_mapping **mapping); | 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 | * amdgpu_acpi_is_s0ix_active | 1049 | * amdgpu_acpi_is_s0ix_active |
| 1036 | * | 1050 | * |
| @@ -1040,11 +1054,24 @@ void amdgpu_acpi_detect(void) · 3 unmodified lines | |||
| 1040 | */ | 1054 | */ |
| 1041 | bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) | 1055 | bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) |
| 1042 | { | 1056 | { |
| 1043 | #if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) | 1057 | if (!(adev->flags & AMD_IS_APU) || |
| 1044 | if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { | 1058 | (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) |
| 1045 | if (adev->flags & AMD_IS_APU) | 1059 | return false; |
| 1046 | return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; | 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 | return false; | 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 | static int amdgpu_pmops_prepare(struct device *dev) | 2246 | static int amdgpu_pmops_prepare(struct device *dev) |
| 2247 | { | 2247 | { |
| 2248 | struct drm_device *drm_dev = dev_get_drvdata(dev); | 2248 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
| 2249 | struct amdgpu_device *adev = drm_to_adev(drm_dev); | ||
| 2249 | 2250 | ||
| 2250 | /* Return a positive number here so | 2251 | /* Return a positive number here so |
| 2251 | * DPM_FLAG_SMART_SUSPEND works properly | 2252 | * DPM_FLAG_SMART_SUSPEND works properly |
| 2252 | */ | 2253 | */ |
| 2253 | if (amdgpu_device_supports_boco(drm_dev)) | 2254 | if (amdgpu_device_supports_boco(drm_dev)) |
| 2254 | return pm_runtime_suspended(dev) && | 2255 | return pm_runtime_suspended(dev); |
| 2255 | pm_suspend_via_firmware(); | 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 | return 0; | 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 | unsigned i; | 1904 | unsigned i; |
| 1905 | int r; | 1905 | int r; |
| 1906 | 1906 | ||
| 1907 | if (direct_submit && !ring->sched.ready) { | 1907 | if (!direct_submit && !ring->sched.ready) { |
| 1908 | DRM_ERROR("Trying to move memory with ring turned off.\n"); | 1908 | DRM_ERROR("Trying to move memory with ring turned off.\n"); |
| 1909 | return -EINVAL; | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | adev->mmhub.funcs->get_clockgating(adev, flags); | 1146 | adev->mmhub.funcs->get_clockgating(adev, flags); |
| 1144 | 1147 | ||
| 1145 | if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0)) | 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 | .wm_inst = WM_A, | 570 | .wm_inst = WM_A, |
| 571 | .wm_type = WM_TYPE_PSTATE_CHG, | 571 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 572 | .pstate_latency_us = 11.65333, | 572 | .pstate_latency_us = 11.65333, |
| 573 | .sr_exit_time_us = 7.95, | 573 | .sr_exit_time_us = 13.5, |
| 574 | .sr_enter_plus_exit_time_us = 9, | 574 | .sr_enter_plus_exit_time_us = 16.5, |
| 575 | .valid = true, | 575 | .valid = true, |
| 576 | }, | 576 | }, |
| 577 | { | 577 | { |
| 578 | .wm_inst = WM_B, | 578 | .wm_inst = WM_B, |
| 579 | .wm_type = WM_TYPE_PSTATE_CHG, | 579 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 580 | .pstate_latency_us = 11.65333, | 580 | .pstate_latency_us = 11.65333, |
| 581 | .sr_exit_time_us = 9.82, | 581 | .sr_exit_time_us = 13.5, |
| 582 | .sr_enter_plus_exit_time_us = 11.196, | 582 | .sr_enter_plus_exit_time_us = 16.5, |
| 583 | .valid = true, | 583 | .valid = true, |
| 584 | }, | 584 | }, |
| 585 | { | 585 | { |
| 586 | .wm_inst = WM_C, | 586 | .wm_inst = WM_C, |
| 587 | .wm_type = WM_TYPE_PSTATE_CHG, | 587 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 588 | .pstate_latency_us = 11.65333, | 588 | .pstate_latency_us = 11.65333, |
| 589 | .sr_exit_time_us = 9.89, | 589 | .sr_exit_time_us = 13.5, |
| 590 | .sr_enter_plus_exit_time_us = 11.24, | 590 | .sr_enter_plus_exit_time_us = 16.5, |
| 591 | .valid = true, | 591 | .valid = true, |
| 592 | }, | 592 | }, |
| 593 | { | 593 | { |
| 594 | .wm_inst = WM_D, | 594 | .wm_inst = WM_D, |
| 595 | .wm_type = WM_TYPE_PSTATE_CHG, | 595 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 596 | .pstate_latency_us = 11.65333, | 596 | .pstate_latency_us = 11.65333, |
| 597 | .sr_exit_time_us = 9.748, | 597 | .sr_exit_time_us = 13.5, |
| 598 | .sr_enter_plus_exit_time_us = 11.102, | 598 | .sr_enter_plus_exit_time_us = 16.5, |
| 599 | .valid = true, | 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 | .entries = { | 333 | .entries = { |
| 334 | { | 334 | { |
| 335 | .wm_inst = WM_A, | 335 | .wm_inst = WM_A, |
| 336 | .wm_type = WM_TYPE_PSTATE_CHG, | 336 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 337 | .pstate_latency_us = 11.72, | 337 | .pstate_latency_us = 11.72, |
| 338 | .sr_exit_time_us = 6.09, | 338 | .sr_exit_time_us = 9, |
| 339 | .sr_enter_plus_exit_time_us = 7.14, | 339 | .sr_enter_plus_exit_time_us = 11, |
| 340 | .valid = true, | 340 | .valid = true, |
| 341 | }, | 341 | }, |
| 342 | { | 342 | { |
| 343 | .wm_inst = WM_B, | 343 | .wm_inst = WM_B, |
| 344 | .wm_type = WM_TYPE_PSTATE_CHG, | 344 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 345 | .pstate_latency_us = 11.72, | 345 | .pstate_latency_us = 11.72, |
| 346 | .sr_exit_time_us = 10.12, | 346 | .sr_exit_time_us = 9, |
| 347 | .sr_enter_plus_exit_time_us = 11.48, | 347 | .sr_enter_plus_exit_time_us = 11, |
| 348 | .valid = true, | 348 | .valid = true, |
| 349 | }, | 349 | }, |
| 350 | { | 350 | { |
| 351 | .wm_inst = WM_C, | 351 | .wm_inst = WM_C, |
| 352 | .wm_type = WM_TYPE_PSTATE_CHG, | 352 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 353 | .pstate_latency_us = 11.72, | 353 | .pstate_latency_us = 11.72, |
| 354 | .sr_exit_time_us = 10.12, | 354 | .sr_exit_time_us = 9, |
| 355 | .sr_enter_plus_exit_time_us = 11.48, | 355 | .sr_enter_plus_exit_time_us = 11, |
| 356 | .valid = true, | 356 | .valid = true, |
| 357 | }, | 357 | }, |
| 358 | { | 358 | { |
| 359 | .wm_inst = WM_D, | 359 | .wm_inst = WM_D, |
| 360 | .wm_type = WM_TYPE_PSTATE_CHG, | 360 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 361 | .pstate_latency_us = 11.72, | 361 | .pstate_latency_us = 11.72, |
| 362 | .sr_exit_time_us = 10.12, | 362 | .sr_exit_time_us = 9, |
| 363 | .sr_enter_plus_exit_time_us = 11.48, | 363 | .sr_enter_plus_exit_time_us = 11, |
| 364 | .valid = true, | 364 | .valid = true, |
| 365 | }, | 365 | }, |
| 366 | } | 366 | } |
| @@ -687,7 +687,7 @@ void dcn31_clk_mgr_construct( · 320 unmodified lines | |||
| 687 | if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { | 687 | if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { |
| 688 | dcn31_bw_params.wm_table = lpddr5_wm_table; | 688 | dcn31_bw_params.wm_table = lpddr5_wm_table; |
| 689 | } else { | 689 | } else { |
| 690 | dcn31_bw_params.wm_table = ddr4_wm_table; | 690 | dcn31_bw_params.wm_table = ddr5_wm_table; |
| 691 | } | 691 | } |
| 692 | /* Saved clocks configured at boot for debug purposes */ | 692 | /* Saved clocks configured at boot for debug purposes */ |
| 693 | dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); | 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 | dp_hw_fw_revision.ieee_fw_rev, | 5597 | dp_hw_fw_revision.ieee_fw_rev, |
| 5598 | sizeof(dp_hw_fw_revision.ieee_fw_rev)); | 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 | memset(&link->dpcd_caps.dsc_caps, '\0', | 5620 | memset(&link->dpcd_caps.dsc_caps, '\0', |
| 5601 | sizeof(link->dpcd_caps.dsc_caps)); | 5621 | sizeof(link->dpcd_caps.dsc_caps)); |
| 5602 | memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); | 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 | pipe_ctx->stream_res.stream_enc, | 1608 | pipe_ctx->stream_res.stream_enc, |
| 1609 | pipe_ctx->stream_res.tg->inst); | 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 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) | 1611 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) |
| 1617 | dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); | 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 | void enc1_stream_encoder_dp_blank( | 905 | void enc1_stream_encoder_dp_blank( |
| 919 | struct dc_link *link, | 906 | struct dc_link *link, |
| 920 | struct stream_encoder *enc) | 907 | struct stream_encoder *enc) |
| @@ -1600,8 +1587,6 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { · 679 unmodified lines | |||
| 1600 | enc1_stream_encoder_send_immediate_sdp_message, | 1587 | enc1_stream_encoder_send_immediate_sdp_message, |
| 1601 | .stop_dp_info_packets = | 1588 | .stop_dp_info_packets = |
| 1602 | enc1_stream_encoder_stop_dp_info_packets, | 1589 | enc1_stream_encoder_stop_dp_info_packets, |
| 1603 | .reset_fifo = | ||
| 1604 | enc1_stream_encoder_reset_fifo, | ||
| 1605 | .dp_blank = | 1590 | .dp_blank = |
| 1606 | enc1_stream_encoder_dp_blank, | 1591 | enc1_stream_encoder_dp_blank, |
| 1607 | .dp_unblank = | 1592 | .dp_unblank = |
| @@ -626,9 +626,6 @@ void enc1_stream_encoder_send_immediate_sdp_message( · 625 unmodified lines | |||
| 626 | void enc1_stream_encoder_stop_dp_info_packets( | 626 | void enc1_stream_encoder_stop_dp_info_packets( |
| 627 | struct stream_encoder *enc); | 627 | struct stream_encoder *enc); |
| 628 | 628 | ||
| 629 | void enc1_stream_encoder_reset_fifo( | ||
| 630 | struct stream_encoder *enc); | ||
| 631 | |||
| 632 | void enc1_stream_encoder_dp_blank( | 629 | void enc1_stream_encoder_dp_blank( |
| 633 | struct dc_link *link, | 630 | struct dc_link *link, |
| 634 | struct stream_encoder *enc); | 631 | struct stream_encoder *enc); |
| @@ -593,8 +593,6 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { · 592 unmodified lines | |||
| 593 | enc1_stream_encoder_send_immediate_sdp_message, | 593 | enc1_stream_encoder_send_immediate_sdp_message, |
| 594 | .stop_dp_info_packets = | 594 | .stop_dp_info_packets = |
| 595 | enc1_stream_encoder_stop_dp_info_packets, | 595 | enc1_stream_encoder_stop_dp_info_packets, |
| 596 | .reset_fifo = | ||
| 597 | enc1_stream_encoder_reset_fifo, | ||
| 598 | .dp_blank = | 596 | .dp_blank = |
| 599 | enc1_stream_encoder_dp_blank, | 597 | enc1_stream_encoder_dp_blank, |
| 600 | .dp_unblank = | 598 | .dp_unblank = |
| @@ -789,8 +789,6 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { · 788 unmodified lines | |||
| 789 | enc3_stream_encoder_update_dp_info_packets, | 789 | enc3_stream_encoder_update_dp_info_packets, |
| 790 | .stop_dp_info_packets = | 790 | .stop_dp_info_packets = |
| 791 | enc1_stream_encoder_stop_dp_info_packets, | 791 | enc1_stream_encoder_stop_dp_info_packets, |
| 792 | .reset_fifo = | ||
| 793 | enc1_stream_encoder_reset_fifo, | ||
| 794 | .dp_blank = | 792 | .dp_blank = |
| 795 | enc1_stream_encoder_dp_blank, | 793 | enc1_stream_encoder_dp_blank, |
| 796 | .dp_unblank = | 794 | .dp_unblank = |
| @@ -164,10 +164,6 @@ struct stream_encoder_funcs { · 163 unmodified lines | |||
| 164 | void (*stop_dp_info_packets)( | 164 | void (*stop_dp_info_packets)( |
| 165 | struct stream_encoder *enc); | 165 | struct stream_encoder *enc); |
| 166 | 166 | ||
| 167 | void (*reset_fifo)( | ||
| 168 | struct stream_encoder *enc | ||
| 169 | ); | ||
| 170 | |||
| 171 | void (*dp_blank)( | 167 | void (*dp_blank)( |
| 172 | struct dc_link *link, | 168 | struct dc_link *link, |
| 173 | struct stream_encoder *enc); | 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 | static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) | 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; | 3699 | uint16_t *mgpu_fan_boost_limit_rpm; |
| 3700 | PPTable_t *smc_pptable = table_context->driver_pptable; | ||
| 3701 | 3700 | ||
| 3701 | GET_PPTABLE_MEMBER(MGpuFanBoostLimitRpm, &mgpu_fan_boost_limit_rpm); | ||
| 3702 | /* | 3702 | /* |
| 3703 | * Skip the MGpuFanBoost setting for those ASICs | 3703 | * Skip the MGpuFanBoost setting for those ASICs |
| 3704 | * which do not support it | 3704 | * which do not support it |
| 3705 | */ | 3705 | */ |
| 3706 | if (!smc_pptable->MGpuFanBoostLimitRpm) | 3706 | if (*mgpu_fan_boost_limit_rpm == 0) |
| 3707 | return 0; | 3707 | return 0; |
| 3708 | 3708 | ||
| 3709 | return smu_cmn_send_smc_msg_with_param(smu, | 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 | const struct intel_crtc_state *pipe_config = | 959 | const struct intel_crtc_state *pipe_config = |
| 960 | overlay->crtc->config; | 960 | overlay->crtc->config; |
| 961 | 961 | ||
| 962 | if (rec->dst_height == 0 || rec->dst_width == 0) | ||
| 963 | return -EINVAL; | ||
| 964 | |||
| 962 | if (rec->dst_x < pipe_config->pipe_src_w && | 965 | if (rec->dst_x < pipe_config->pipe_src_w && |
| 963 | rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && | 966 | rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && |
| 964 | rec->dst_y < pipe_config->pipe_src_h && | 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 | static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) | 345 | static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) |
| 346 | { | 346 | { |
| 347 | struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); | 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 | struct intel_uncore *uncore = &i915->uncore; | 349 | struct intel_uncore *uncore = &i915->uncore; |
| 349 | u32 val; | 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 | if (val == 0xffffffff) { | 353 | if (val == 0xffffffff) { |
| 353 | drm_dbg_kms(&i915->drm, | 354 | drm_dbg_kms(&i915->drm, |
| 354 | "Port %s: PHY in TCCOLD, assuming not complete\n", | 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 | timeout) < 0) { | 2505 | timeout) < 0) { |
| 2506 | i915_request_put(rq); | 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 | intel_context_exit(ce); | 2514 | intel_context_exit(ce); |
| 2510 | intel_context_timeline_unlock(tl); | 2515 | mutex_unlock(&ce->timeline->mutex); |
| 2511 | 2516 | ||
| 2512 | if (nonblock) | 2517 | if (nonblock) |
| 2513 | return -EWOULDBLOCK; | 2518 | return -EWOULDBLOCK; |
| @@ -206,6 +206,11 @@ struct intel_guc { · 205 unmodified lines | |||
| 206 | * context usage for overflows. | 206 | * context usage for overflows. |
| 207 | */ | 207 | */ |
| 208 | struct delayed_work work; | 208 | struct delayed_work work; |
| 209 | |||
| 210 | /** | ||
| 211 | * @shift: Right shift value for the gpm timestamp | ||
| 212 | */ | ||
| 213 | u32 shift; | ||
| 209 | } timestamp; | 214 | } timestamp; |
| 210 | 215 | ||
| 211 | #ifdef CONFIG_DRM_I915_SELFTEST | 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 | if (new_start == lower_32_bits(*prev_start)) | 1113 | if (new_start == lower_32_bits(*prev_start)) |
| 1114 | return; | 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 | if (new_start < gt_stamp_last && | 1129 | if (new_start < gt_stamp_last && |
| 1117 | (new_start - gt_stamp_last) <= POLL_TIME_CLKS) | 1130 | (new_start - gt_stamp_last) <= POLL_TIME_CLKS) |
| 1118 | gt_stamp_hi++; | 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 | *prev_start = ((u64)gt_stamp_hi << 32) | new_start; | 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 | struct guc_engine_usage_record *rec = intel_guc_engine_usage(engine); | 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 | struct intel_engine_guc_stats *stats = &engine->stats.guc; | 1171 | struct intel_engine_guc_stats *stats = &engine->stats.guc; |
| 1131 | struct intel_guc *guc = &engine->gt->uc.guc; | 1172 | struct intel_guc *guc = &engine->gt->uc.guc; |
| 1132 | u32 last_switch = rec->last_switch_in_stamp; | 1173 | u32 last_switch, ctx_id, total; |
| 1133 | u32 ctx_id = rec->current_context_index; | ||
| 1134 | u32 total = rec->total_runtime; | ||
| 1135 | 1174 | ||
| 1136 | lockdep_assert_held(&guc->timestamp.lock); | 1175 | lockdep_assert_held(&guc->timestamp.lock); |
| 1137 | 1176 | ||
| 1177 | __get_engine_usage_record(engine, &last_switch, &ctx_id, &total); | ||
| 1178 | |||
| 1138 | stats->running = ctx_id != ~0U && last_switch; | 1179 | stats->running = ctx_id != ~0U && last_switch; |
| 1139 | if (stats->running) | 1180 | if (stats->running) |
| 1140 | __extend_last_switch(guc, &stats->start_gt_clk, last_switch); | 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, | 1193 | static u32 gpm_timestamp_shift(struct intel_gt *gt) |
| 1153 | struct intel_engine_cs *engine, | 1194 | { |
| 1154 | ktime_t *now) | 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 | lockdep_assert_held(&guc->timestamp.lock); | 1227 | lockdep_assert_held(&guc->timestamp.lock); |
| 1159 | 1228 | ||
| 1160 | gt_stamp_hi = upper_32_bits(guc->timestamp.gt_stamp); | 1229 | gt_stamp_hi = upper_32_bits(guc->timestamp.gt_stamp); |
| 1161 | gt_stamp_now = intel_uncore_read(engine->uncore, | 1230 | gpm_ts = gpm_timestamp(gt) >> guc->timestamp.shift; |
| 1162 | RING_TIMESTAMP(engine->mmio_base)); | 1231 | gt_stamp_lo = lower_32_bits(gpm_ts); |
| 1163 | *now = ktime_get(); | 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 | gt_stamp_hi++; | 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 | if (!in_reset && intel_gt_pm_get_if_awake(gt)) { | 1277 | if (!in_reset && intel_gt_pm_get_if_awake(gt)) { |
| 1209 | stats_saved = *stats; | 1278 | stats_saved = *stats; |
| 1210 | gt_stamp_saved = guc->timestamp.gt_stamp; | 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 | guc_update_engine_gt_clks(engine); | 1284 | guc_update_engine_gt_clks(engine); |
| 1212 | guc_update_pm_timestamp(guc, engine, now); | 1285 | guc_update_pm_timestamp(guc, now); |
| 1213 | intel_gt_pm_put_async(gt); | 1286 | intel_gt_pm_put_async(gt); |
| 1214 | if (i915_reset_count(gpu_error) != reset_count) { | 1287 | if (i915_reset_count(gpu_error) != reset_count) { |
| 1215 | *stats = stats_saved; | 1288 | *stats = stats_saved; |
| @@ -1241,8 +1314,8 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) · 25 unmodified lines | |||
| 1241 | 1314 | ||
| 1242 | spin_lock_irqsave(&guc->timestamp.lock, flags); | 1315 | spin_lock_irqsave(&guc->timestamp.lock, flags); |
| 1243 | 1316 | ||
| 1317 | guc_update_pm_timestamp(guc, &unused); | ||
| 1244 | for_each_engine(engine, gt, id) { | 1318 | for_each_engine(engine, gt, id) { |
| 1245 | guc_update_pm_timestamp(guc, engine, &unused); | ||
| 1246 | guc_update_engine_gt_clks(engine); | 1319 | guc_update_engine_gt_clks(engine); |
| 1247 | engine->stats.guc.prev_total = 0; | 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 | ktime_t unused; | 1332 | ktime_t unused; |
| 1260 | 1333 | ||
| 1261 | spin_lock_irqsave(&guc->timestamp.lock, flags); | 1334 | spin_lock_irqsave(&guc->timestamp.lock, flags); |
| 1262 | for_each_engine(engine, gt, id) { | 1335 | |
| 1263 | guc_update_pm_timestamp(guc, engine, &unused); | 1336 | guc_update_pm_timestamp(guc, &unused); |
| 1337 | for_each_engine(engine, gt, id) | ||
| 1264 | guc_update_engine_gt_clks(engine); | 1338 | guc_update_engine_gt_clks(engine); |
| 1265 | } | 1339 | |
| 1266 | spin_unlock_irqrestore(&guc->timestamp.lock, flags); | 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 | void intel_guc_busyness_unpark(struct intel_gt *gt) | 1409 | void intel_guc_busyness_unpark(struct intel_gt *gt) |
| 1336 | { | 1410 | { |
| 1337 | struct intel_guc *guc = >->uc.guc; | 1411 | struct intel_guc *guc = >->uc.guc; |
| 1412 | unsigned long flags; | ||
| 1413 | ktime_t unused; | ||
| 1338 | 1414 | ||
| 1339 | if (!guc_submission_initialized(guc)) | 1415 | if (!guc_submission_initialized(guc)) |
| 1340 | return; | 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 | mod_delayed_work(system_highpri_wq, &guc->timestamp.work, | 1421 | mod_delayed_work(system_highpri_wq, &guc->timestamp.work, |
| 1343 | guc->timestamp.ping_delay); | 1422 | guc->timestamp.ping_delay); |
| 1344 | } | 1423 | } |
| @@ -1783,6 +1862,7 @@ int intel_guc_submission_init(struct intel_guc *guc) · 438 unmodified lines | |||
| 1783 | spin_lock_init(&guc->timestamp.lock); | 1862 | spin_lock_init(&guc->timestamp.lock); |
| 1784 | INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping); | 1863 | INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping); |
| 1785 | guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ; | 1864 | guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ; |
| 1865 | guc->timestamp.shift = gpm_timestamp_shift(gt); | ||
| 1786 | 1866 | ||
| 1787 | return 0; | 1867 | return 0; |
| 1788 | } | 1868 | } |
| @@ -1522,7 +1522,7 @@ capture_engine(struct intel_engine_cs *engine, · 1521 unmodified lines | |||
| 1522 | struct i915_request *rq = NULL; | 1522 | struct i915_request *rq = NULL; |
| 1523 | unsigned long flags; | 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 | if (!ee) | 1526 | if (!ee) |
| 1527 | return NULL; | 1527 | return NULL; |
| 1528 | 1528 | ||
| @@ -2684,7 +2684,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 2683 unmodified lines | |||
| 2684 | #define RING_WAIT (1 << 11) /* gen3+, PRBx_CTL */ | 2684 | #define RING_WAIT (1 << 11) /* gen3+, PRBx_CTL */ |
| 2685 | #define RING_WAIT_SEMAPHORE (1 << 10) /* gen6+ */ | 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 | /* There are 16 64-bit CS General Purpose Registers per-engine on Gen8+ */ | 2690 | /* There are 16 64-bit CS General Purpose Registers per-engine on Gen8+ */ |
| 2690 | #define GEN8_RING_CS_GPR(base, n) _MMIO((base) + 0x600 + (n) * 8) | 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 | case LAYER_1: | 158 | case LAYER_1: |
| 159 | kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE; | 159 | kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE; |
| 160 | break; | 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 | kmb->plane_status[plane_id].disable = true; | 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 | bridge_state = | 361 | bridge_state = |
| 362 | drm_atomic_get_new_bridge_state(state, | 362 | drm_atomic_get_new_bridge_state(state, |
| 363 | mxsfb->bridge); | 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 | if (bus_format == MEDIA_BUS_FMT_FIXED) { | 369 | if (bus_format == MEDIA_BUS_FMT_FIXED) { |
| 366 | dev_warn_once(drm->dev, | 370 | dev_warn_once(drm->dev, |
| 367 | "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n" | 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 | *addr += bios->imaged_addr; | 38 | *addr += bios->imaged_addr; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | if (unlikely(*addr + size >= bios->size)) { | 41 | if (unlikely(*addr + size > bios->size)) { |
| 42 | nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr); | 42 | nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr); |
| 43 | return false; | 43 | return false; |
| 44 | } | 44 | } |
| @@ -3322,7 +3322,7 @@ static int cm_lap_handler(struct cm_work *work) · 3321 unmodified lines | |||
| 3322 | ret = cm_init_av_by_path(param->alternate_path, NULL, &alt_av); | 3322 | ret = cm_init_av_by_path(param->alternate_path, NULL, &alt_av); |
| 3323 | if (ret) { | 3323 | if (ret) { |
| 3324 | rdma_destroy_ah_attr(&ah_attr); | 3324 | rdma_destroy_ah_attr(&ah_attr); |
| 3325 | return -EINVAL; | 3325 | goto deref; |
| 3326 | } | 3326 | } |
| 3327 | 3327 | ||
| 3328 | spin_lock_irq(&cm_id_priv->lock); | 3328 | spin_lock_irq(&cm_id_priv->lock); |
| @@ -67,8 +67,8 @@ static const char * const cma_events[] = { · 66 unmodified lines | |||
| 67 | [RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit", | 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, | 70 | static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, |
| 71 | union ib_gid *mgid); | 71 | enum ib_gid_type gid_type); |
| 72 | 72 | ||
| 73 | const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event) | 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 | if (dev_addr->bound_dev_if) | 1846 | if (dev_addr->bound_dev_if) |
| 1847 | ndev = dev_get_by_index(dev_addr->net, | 1847 | ndev = dev_get_by_index(dev_addr->net, |
| 1848 | dev_addr->bound_dev_if); | 1848 | dev_addr->bound_dev_if); |
| 1849 | if (ndev) { | 1849 | if (ndev && !send_only) { |
| 1850 | enum ib_gid_type gid_type; | ||
| 1850 | union ib_gid mgid; | 1851 | union ib_gid mgid; |
| 1851 | 1852 | ||
| 1852 | cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, | 1853 | gid_type = id_priv->cma_dev->default_gid_type |
| 1853 | &mgid); | 1854 | [id_priv->id.port_num - |
| 1854 | 1855 | rdma_start_port( | |
| 1855 | if (!send_only) | 1856 | id_priv->cma_dev->device)]; |
| 1856 | cma_igmp_send(ndev, &mgid, false); | 1857 | cma_iboe_set_mgid((struct sockaddr *)&mc->addr, &mgid, |
| 1857 | 1858 | gid_type); | |
| 1858 | dev_put(ndev); | 1859 | cma_igmp_send(ndev, &mgid, false); |
| 1859 | } | 1860 | } |
| 1861 | dev_put(ndev); | ||
| 1860 | 1862 | ||
| 1861 | cancel_work_sync(&mc->iboe_join.work); | 1863 | cancel_work_sync(&mc->iboe_join.work); |
| 1862 | } | 1864 | } |
| @@ -95,6 +95,7 @@ struct ucma_context { · 94 unmodified lines | |||
| 95 | u64 uid; | 95 | u64 uid; |
| 96 | 96 | ||
| 97 | struct list_head list; | 97 | struct list_head list; |
| 98 | struct list_head mc_list; | ||
| 98 | struct work_struct close_work; | 99 | struct work_struct close_work; |
| 99 | }; | 100 | }; |
| 100 | 101 | ||
| @@ -105,6 +106,7 @@ struct ucma_multicast { · 4 unmodified lines | |||
| 105 | 106 | ||
| 106 | u64 uid; | 107 | u64 uid; |
| 107 | u8 join_state; | 108 | u8 join_state; |
| 109 | struct list_head list; | ||
| 108 | struct sockaddr_storage addr; | 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 | INIT_WORK(&ctx->close_work, ucma_close_id); | 201 | INIT_WORK(&ctx->close_work, ucma_close_id); |
| 200 | init_completion(&ctx->comp); | 202 | init_completion(&ctx->comp); |
| 203 | INIT_LIST_HEAD(&ctx->mc_list); | ||
| 201 | /* So list_del() will work if we don't do ucma_finish_ctx() */ | 204 | /* So list_del() will work if we don't do ucma_finish_ctx() */ |
| 202 | INIT_LIST_HEAD(&ctx->list); | 205 | INIT_LIST_HEAD(&ctx->list); |
| 203 | ctx->file = file; | 206 | ctx->file = file; |
| @@ -484,19 +487,19 @@ err1: · 280 unmodified lines | |||
| 484 | 487 | ||
| 485 | static void ucma_cleanup_multicast(struct ucma_context *ctx) | 488 | static void ucma_cleanup_multicast(struct ucma_context *ctx) |
| 486 | { | 489 | { |
| 487 | struct ucma_multicast *mc; | 490 | struct ucma_multicast *mc, *tmp; |
| 488 | unsigned long index; | ||
| 489 | 491 | ||
| 490 | xa_for_each(&multicast_table, index, mc) { | 492 | xa_lock(&multicast_table); |
| 491 | if (mc->ctx != ctx) | 493 | list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) { |
| 492 | continue; | 494 | list_del(&mc->list); |
| 493 | /* | 495 | /* |
| 494 | * At this point mc->ctx->ref is 0 so the mc cannot leave the | 496 | * At this point mc->ctx->ref is 0 so the mc cannot leave the |
| 495 | * lock on the reader and this is enough serialization | 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 | kfree(mc); | 500 | kfree(mc); |
| 499 | } | 501 | } |
| 502 | xa_unlock(&multicast_table); | ||
| 500 | } | 503 | } |
| 501 | 504 | ||
| 502 | static void ucma_cleanup_mc_events(struct ucma_multicast *mc) | 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 | mc->uid = cmd->uid; | 1472 | mc->uid = cmd->uid; |
| 1470 | memcpy(&mc->addr, addr, cmd->addr_size); | 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 | GFP_KERNEL)) { | 1477 | GFP_KERNEL)) { |
| 1474 | ret = -ENOMEM; | 1478 | ret = -ENOMEM; |
| 1475 | goto err_free_mc; | 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 | mutex_lock(&ctx->mutex); | 1485 | mutex_lock(&ctx->mutex); |
| 1479 | ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr, | 1486 | ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr, |
| 1480 | join_state, mc); | 1487 | join_state, mc); |
| @@ -1500,8 +1507,11 @@ err_leave_multicast: · 19 unmodified lines | |||
| 1500 | mutex_unlock(&ctx->mutex); | 1507 | mutex_unlock(&ctx->mutex); |
| 1501 | ucma_cleanup_mc_events(mc); | 1508 | ucma_cleanup_mc_events(mc); |
| 1502 | err_xa_erase: | 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 | err_free_mc: | 1513 | err_free_mc: |
| 1514 | xa_unlock(&multicast_table); | ||
| 1505 | kfree(mc); | 1515 | kfree(mc); |
| 1506 | err_put_ctx: | 1516 | err_put_ctx: |
| 1507 | ucma_put_ctx(ctx); | 1517 | ucma_put_ctx(ctx); |
| @@ -1569,15 +1579,17 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file, · 61 unmodified lines | |||
| 1569 | mc = ERR_PTR(-EINVAL); | 1579 | mc = ERR_PTR(-EINVAL); |
| 1570 | else if (!refcount_inc_not_zero(&mc->ctx->ref)) | 1580 | else if (!refcount_inc_not_zero(&mc->ctx->ref)) |
| 1571 | mc = ERR_PTR(-ENXIO); | 1581 | mc = ERR_PTR(-ENXIO); |
| 1572 | else | ||
| 1573 | __xa_erase(&multicast_table, mc->id); | ||
| 1574 | xa_unlock(&multicast_table); | ||
| 1575 | 1582 | ||
| 1576 | if (IS_ERR(mc)) { | 1583 | if (IS_ERR(mc)) { |
| 1584 | xa_unlock(&multicast_table); | ||
| 1577 | ret = PTR_ERR(mc); | 1585 | ret = PTR_ERR(mc); |
| 1578 | goto out; | 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 | mutex_lock(&mc->ctx->mutex); | 1593 | mutex_lock(&mc->ctx->mutex); |
| 1582 | rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr); | 1594 | rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr); |
| 1583 | mutex_unlock(&mc->ctx->mutex); | 1595 | mutex_unlock(&mc->ctx->mutex); |
| @@ -55,7 +55,7 @@ union hfi1_ipoib_flow { · 54 unmodified lines | |||
| 55 | */ | 55 | */ |
| 56 | struct ipoib_txreq { | 56 | struct ipoib_txreq { |
| 57 | struct sdma_txreq txreq; | 57 | struct sdma_txreq txreq; |
| 58 | struct hfi1_sdma_header sdma_hdr; | 58 | struct hfi1_sdma_header *sdma_hdr; |
| 59 | int sdma_status; | 59 | int sdma_status; |
| 60 | int complete; | 60 | int complete; |
| 61 | struct hfi1_ipoib_dev_priv *priv; | 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 | int ret; | 22 | int ret; |
| 23 | 23 | ||
| 24 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | 24 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 25 | if (!dev->tstats) | ||
| 26 | return -ENOMEM; | ||
| 25 | 27 | ||
| 26 | ret = priv->netdev_ops->ndo_init(dev); | 28 | ret = priv->netdev_ops->ndo_init(dev); |
| 27 | if (ret) | 29 | if (ret) |
| 28 | return ret; | 30 | goto out_ret; |
| 29 | 31 | ||
| 30 | ret = hfi1_netdev_add_data(priv->dd, | 32 | ret = hfi1_netdev_add_data(priv->dd, |
| 31 | qpn_from_mac(priv->netdev->dev_addr), | 33 | qpn_from_mac(priv->netdev->dev_addr), |
| 32 | dev); | 34 | dev); |
| 33 | if (ret < 0) { | 35 | if (ret < 0) { |
| 34 | priv->netdev_ops->ndo_uninit(dev); | 36 | priv->netdev_ops->ndo_uninit(dev); |
| 35 | return ret; | 37 | goto out_ret; |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | return 0; | 40 | return 0; |
| 41 | out_ret: | ||
| 42 | free_percpu(dev->tstats); | ||
| 43 | dev->tstats = NULL; | ||
| 44 | return ret; | ||
| 39 | } | 45 | } |
| 40 | 46 | ||
| 41 | static void hfi1_ipoib_dev_uninit(struct net_device *dev) | 47 | static void hfi1_ipoib_dev_uninit(struct net_device *dev) |
| 42 | { | 48 | { |
| 43 | struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev); | 49 | struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev); |
| 44 | 50 | ||
| 51 | free_percpu(dev->tstats); | ||
| 52 | dev->tstats = NULL; | ||
| 53 | |||
| 45 | hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr)); | 54 | hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr)); |
| 46 | 55 | ||
| 47 | priv->netdev_ops->ndo_uninit(dev); | 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 | hfi1_ipoib_rxq_deinit(priv->netdev); | 175 | hfi1_ipoib_rxq_deinit(priv->netdev); |
| 167 | 176 | ||
| 168 | free_percpu(dev->tstats); | 177 | free_percpu(dev->tstats); |
| 169 | } | 178 | dev->tstats = NULL; |
| 170 | |||
| 171 | static void hfi1_ipoib_free_rdma_netdev(struct net_device *dev) | ||
| 172 | { | ||
| 173 | hfi1_ipoib_netdev_dtor(dev); | ||
| 174 | free_netdev(dev); | ||
| 175 | } | 179 | } |
| 176 | 180 | ||
| 177 | static void hfi1_ipoib_set_id(struct net_device *dev, int id) | 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 | priv->port_num = port_num; | 215 | priv->port_num = port_num; |
| 212 | priv->netdev_ops = netdev->netdev_ops; | 216 | priv->netdev_ops = netdev->netdev_ops; |
| 213 | 217 | ||
| 214 | netdev->netdev_ops = &hfi1_ipoib_netdev_ops; | ||
| 215 | |||
| 216 | ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey); | 218 | ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey); |
| 217 | 219 | ||
| 218 | rc = hfi1_ipoib_txreq_init(priv); | 220 | rc = hfi1_ipoib_txreq_init(priv); |
| 219 | if (rc) { | 221 | if (rc) { |
| 220 | dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc); | 222 | dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc); |
| 221 | hfi1_ipoib_free_rdma_netdev(netdev); | ||
| 222 | return rc; | 223 | return rc; |
| 223 | } | 224 | } |
| 224 | 225 | ||
| 225 | rc = hfi1_ipoib_rxq_init(netdev); | 226 | rc = hfi1_ipoib_rxq_init(netdev); |
| 226 | if (rc) { | 227 | if (rc) { |
| 227 | dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc); | 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 | return rc; | 230 | return rc; |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 233 | netdev->netdev_ops = &hfi1_ipoib_netdev_ops; | ||
| 234 | |||
| 232 | netdev->priv_destructor = hfi1_ipoib_netdev_dtor; | 235 | netdev->priv_destructor = hfi1_ipoib_netdev_dtor; |
| 233 | netdev->needs_free_netdev = true; | 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 | dd_dev_warn(priv->dd, | 122 | dd_dev_warn(priv->dd, |
| 123 | "%s: Status = 0x%x pbc 0x%llx txq = %d sde = %d\n", | 123 | "%s: Status = 0x%x pbc 0x%llx txq = %d sde = %d\n", |
| 124 | __func__, tx->sdma_status, | 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 | tx->txq->sde->this_idx); | 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 | struct hfi1_devdata *dd = txp->dd; | 232 | struct hfi1_devdata *dd = txp->dd; |
| 233 | struct sdma_txreq *txreq = &tx->txreq; | 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 | u16 pkt_bytes = | 235 | u16 pkt_bytes = |
| 236 | sizeof(sdma_hdr->pbc) + (txp->hdr_dwords << 2) + tx->skb->len; | 236 | sizeof(sdma_hdr->pbc) + (txp->hdr_dwords << 2) + tx->skb->len; |
| 237 | int ret; | 237 | int ret; |
| @@ -256,7 +256,7 @@ static void hfi1_ipoib_build_ib_tx_headers(struct ipoib_txreq *tx, · 18 unmodified lines | |||
| 256 | struct ipoib_txparms *txp) | 256 | struct ipoib_txparms *txp) |
| 257 | { | 257 | { |
| 258 | struct hfi1_ipoib_dev_priv *priv = tx->txq->priv; | 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 | struct sk_buff *skb = tx->skb; | 260 | struct sk_buff *skb = tx->skb; |
| 261 | struct hfi1_pportdata *ppd = ppd_from_ibp(txp->ibp); | 261 | struct hfi1_pportdata *ppd = ppd_from_ibp(txp->ibp); |
| 262 | struct rdma_ah_attr *ah_attr = txp->ah_attr; | 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 | if (likely(!ret)) { | 483 | if (likely(!ret)) { |
| 484 | tx_ok: | 484 | tx_ok: |
| 485 | trace_sdma_output_ibhdr(txq->priv->dd, | 485 | trace_sdma_output_ibhdr(txq->priv->dd, |
| 486 | &tx->sdma_hdr.hdr, | 486 | &tx->sdma_hdr->hdr, |
| 487 | ib_is_sc5(txp->flow.sc5)); | 487 | ib_is_sc5(txp->flow.sc5)); |
| 488 | hfi1_ipoib_check_queue_depth(txq); | 488 | hfi1_ipoib_check_queue_depth(txq); |
| 489 | return NETDEV_TX_OK; | 489 | return NETDEV_TX_OK; |
| @@ -547,7 +547,7 @@ static int hfi1_ipoib_send_dma_list(struct net_device *dev, · 57 unmodified lines | |||
| 547 | hfi1_ipoib_check_queue_depth(txq); | 547 | hfi1_ipoib_check_queue_depth(txq); |
| 548 | 548 | ||
| 549 | trace_sdma_output_ibhdr(txq->priv->dd, | 549 | trace_sdma_output_ibhdr(txq->priv->dd, |
| 550 | &tx->sdma_hdr.hdr, | 550 | &tx->sdma_hdr->hdr, |
| 551 | ib_is_sc5(txp->flow.sc5)); | 551 | ib_is_sc5(txp->flow.sc5)); |
| 552 | 552 | ||
| 553 | if (!netdev_xmit_more()) | 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 | struct net_device *dev = priv->netdev; | 684 | struct net_device *dev = priv->netdev; |
| 685 | u32 tx_ring_size, tx_item_size; | 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 | * Ring holds 1 less than tx_ring_size | 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 | for (i = 0; i < dev->num_tx_queues; i++) { | 703 | for (i = 0; i < dev->num_tx_queues; i++) { |
| 703 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; | 704 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 705 | struct ipoib_txreq *tx; | ||
| 704 | 706 | ||
| 707 | tx_ring = &txq->tx_ring; | ||
| 705 | iowait_init(&txq->wait, | 708 | iowait_init(&txq->wait, |
| 706 | 0, | 709 | 0, |
| 707 | hfi1_ipoib_flush_txq, | 710 | hfi1_ipoib_flush_txq, |
| @@ -725,14 +728,19 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) · 17 unmodified lines | |||
| 725 | priv->dd->node); | 728 | priv->dd->node); |
| 726 | 729 | ||
| 727 | txq->tx_ring.items = | 730 | txq->tx_ring.items = |
| 728 | kcalloc_node(tx_ring_size, tx_item_size, | 731 | kvzalloc_node(array_size(tx_ring_size, tx_item_size), |
| 729 | GFP_KERNEL, priv->dd->node); | 732 | GFP_KERNEL, priv->dd->node); |
| 730 | if (!txq->tx_ring.items) | 733 | if (!txq->tx_ring.items) |
| 731 | goto free_txqs; | 734 | goto free_txqs; |
| 732 | 735 | ||
| 733 | txq->tx_ring.max_items = tx_ring_size; | 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 | txq->tx_ring.avail = hfi1_ipoib_ring_hwat(txq); | 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 | netif_tx_napi_add(dev, &txq->napi, | 745 | netif_tx_napi_add(dev, &txq->napi, |
| 738 | hfi1_ipoib_poll_tx_ring, | 746 | hfi1_ipoib_poll_tx_ring, |
| @@ -746,7 +754,10 @@ free_txqs: · 7 unmodified lines | |||
| 746 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; | 754 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 747 | 755 | ||
| 748 | netif_napi_del(&txq->napi); | 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 | kfree(priv->txqs); | 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 | void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv) | 792 | void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv) |
| 782 | { | 793 | { |
| 783 | int i; | 794 | int i, j; |
| 784 | 795 | ||
| 785 | for (i = 0; i < priv->netdev->num_tx_queues; i++) { | 796 | for (i = 0; i < priv->netdev->num_tx_queues; i++) { |
| 786 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; | 797 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 798 | struct hfi1_ipoib_circ_buf *tx_ring = &txq->tx_ring; | ||
| 787 | 799 | ||
| 788 | iowait_cancel_work(&txq->wait); | 800 | iowait_cancel_work(&txq->wait); |
| 789 | iowait_sdma_drain(&txq->wait); | 801 | iowait_sdma_drain(&txq->wait); |
| 790 | hfi1_ipoib_drain_tx_list(txq); | 802 | hfi1_ipoib_drain_tx_list(txq); |
| 791 | netif_napi_del(&txq->napi); | 803 | netif_napi_del(&txq->napi); |
| 792 | hfi1_ipoib_drain_tx_ring(txq); | 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 | kfree(priv->txqs); | 810 | kfree(priv->txqs); |
| @@ -3237,7 +3237,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, · 3236 unmodified lines | |||
| 3237 | case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: | 3237 | case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: |
| 3238 | ew = kmalloc(sizeof *ew, GFP_ATOMIC); | 3238 | ew = kmalloc(sizeof *ew, GFP_ATOMIC); |
| 3239 | if (!ew) | 3239 | if (!ew) |
| 3240 | break; | 3240 | return; |
| 3241 | 3241 | ||
| 3242 | INIT_WORK(&ew->work, handle_port_mgmt_change_event); | 3242 | INIT_WORK(&ew->work, handle_port_mgmt_change_event); |
| 3243 | memcpy(&ew->ib_eqe, eqe, sizeof *eqe); | 3243 | memcpy(&ew->ib_eqe, eqe, sizeof *eqe); |
| @@ -3073,6 +3073,8 @@ do_write: · 3072 unmodified lines | |||
| 3073 | case IB_WR_ATOMIC_FETCH_AND_ADD: | 3073 | case IB_WR_ATOMIC_FETCH_AND_ADD: |
| 3074 | if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) | 3074 | if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) |
| 3075 | goto inv_err; | 3075 | goto inv_err; |
| 3076 | if (unlikely(wqe->atomic_wr.remote_addr & (sizeof(u64) - 1))) | ||
| 3077 | goto inv_err; | ||
| 3076 | if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), | 3078 | if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), |
| 3077 | wqe->atomic_wr.remote_addr, | 3079 | wqe->atomic_wr.remote_addr, |
| 3078 | wqe->atomic_wr.rkey, | 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 | return &qp->orq[qp->orq_get % qp->attrs.orq_size]; | 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 | static inline struct siw_sqe *orq_get_free(struct siw_qp *qp) | 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 | if (READ_ONCE(orq_e->flags) == 0) | 651 | if (READ_ONCE(orq_e->flags) == 0) |
| 657 | return orq_e; | 652 | return orq_e; |
| @@ -1153,11 +1153,12 @@ static int siw_check_tx_fence(struct siw_qp *qp) · 1152 unmodified lines | |||
| 1153 | 1153 | ||
| 1154 | spin_lock_irqsave(&qp->orq_lock, flags); | 1154 | spin_lock_irqsave(&qp->orq_lock, flags); |
| 1155 | 1155 | ||
| 1156 | rreq = orq_get_current(qp); | ||
| 1157 | |||
| 1158 | /* free current orq entry */ | 1156 | /* free current orq entry */ |
| 1157 | rreq = orq_get_current(qp); | ||
| 1159 | WRITE_ONCE(rreq->flags, 0); | 1158 | WRITE_ONCE(rreq->flags, 0); |
| 1160 | 1159 | ||
| 1160 | qp->orq_get++; | ||
| 1161 | |||
| 1161 | if (qp->tx_ctx.orq_fence) { | 1162 | if (qp->tx_ctx.orq_fence) { |
| 1162 | if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) { | 1163 | if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) { |
| 1163 | pr_warn("siw: [QP %u]: fence resume: bad status %d\n", | 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 | rv = -EPROTO; | 1166 | rv = -EPROTO; |
| 1166 | goto out; | 1167 | goto out; |
| 1167 | } | 1168 | } |
| 1168 | /* resume SQ processing */ | 1169 | /* resume SQ processing, if possible */ |
| 1169 | if (tx_waiting->sqe.opcode == SIW_OP_READ || | 1170 | if (tx_waiting->sqe.opcode == SIW_OP_READ || |
| 1170 | tx_waiting->sqe.opcode == SIW_OP_READ_LOCAL_INV) { | 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 | if (unlikely(!rreq)) { | 1175 | if (unlikely(!rreq)) { |
| 1173 | pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp)); | 1176 | pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp)); |
| 1174 | rv = -EPROTO; | 1177 | rv = -EPROTO; |
| @@ -1181,15 +1184,14 @@ static int siw_check_tx_fence(struct siw_qp *qp) · 6 unmodified lines | |||
| 1181 | resume_tx = 1; | 1184 | resume_tx = 1; |
| 1182 | 1185 | ||
| 1183 | } else if (siw_orq_empty(qp)) { | 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 | qp->tx_ctx.orq_fence = 0; | 1191 | qp->tx_ctx.orq_fence = 0; |
| 1185 | resume_tx = 1; | 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 | out: | 1195 | out: |
| 1194 | spin_unlock_irqrestore(&qp->orq_lock, flags); | 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 | if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) { | 314 | if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) { |
| 315 | siw_dbg(base_dev, "too many QP's\n"); | 315 | siw_dbg(base_dev, "too many QP's\n"); |
| 316 | return -ENOMEM; | 316 | rv = -ENOMEM; |
| 317 | goto err_atomic; | ||
| 317 | } | 318 | } |
| 318 | if (attrs->qp_type != IB_QPT_RC) { | 319 | if (attrs->qp_type != IB_QPT_RC) { |
| 319 | siw_dbg(base_dev, "only RC QP's supported\n"); | 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 | * extensions) | 615 | * extensions) |
| 616 | */ | 616 | */ |
| 617 | wm->touch_dev = platform_device_alloc("wm97xx-touch", -1); | 617 | wm->touch_dev = platform_device_alloc("wm97xx-touch", -1); |
| 618 | if (!wm->touch_dev) { | 618 | if (!wm->touch_dev) |
| 619 | ret = -ENOMEM; | 619 | return -ENOMEM; |
| 620 | goto touch_err; | 620 | |
| 621 | } | ||
| 622 | platform_set_drvdata(wm->touch_dev, wm); | 621 | platform_set_drvdata(wm->touch_dev, wm); |
| 623 | wm->touch_dev->dev.parent = wm->dev; | 622 | wm->touch_dev->dev.parent = wm->dev; |
| 624 | wm->touch_dev->dev.platform_data = pdata; | 623 | wm->touch_dev->dev.platform_data = pdata; |
| @@ -629,9 +628,6 @@ static int wm97xx_register_touch(struct wm97xx *wm) · 4 unmodified lines | |||
| 629 | return 0; | 628 | return 0; |
| 630 | touch_reg_err: | 629 | touch_reg_err: |
| 631 | platform_device_put(wm->touch_dev); | 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 | return ret; | 632 | return ret; |
| 637 | } | 633 | } |
| @@ -639,8 +635,6 @@ touch_err: · 1 unmodified line | |||
| 639 | static void wm97xx_unregister_touch(struct wm97xx *wm) | 635 | static void wm97xx_unregister_touch(struct wm97xx *wm) |
| 640 | { | 636 | { |
| 641 | platform_device_unregister(wm->touch_dev); | 637 | platform_device_unregister(wm->touch_dev); |
| 642 | input_unregister_device(wm->input_dev); | ||
| 643 | wm->input_dev = NULL; | ||
| 644 | } | 638 | } |
| 645 | 639 | ||
| 646 | static int _wm97xx_probe(struct wm97xx *wm) | 640 | static int _wm97xx_probe(struct wm97xx *wm) |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
| 22 | #include <linux/kmemleak.h> | 22 | #include <linux/kmemleak.h> |
| 23 | #include <linux/cc_platform.h> | 23 | #include <linux/cc_platform.h> |
| 24 | #include <linux/iopoll.h> | ||
| 24 | #include <asm/pci-direct.h> | 25 | #include <asm/pci-direct.h> |
| 25 | #include <asm/iommu.h> | 26 | #include <asm/iommu.h> |
| 26 | #include <asm/apic.h> | 27 | #include <asm/apic.h> |
| @@ -834,6 +835,7 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) · 807 unmodified lines | |||
| 834 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | 835 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); |
| 835 | if (status & (MMIO_STATUS_GALOG_RUN_MASK)) | 836 | if (status & (MMIO_STATUS_GALOG_RUN_MASK)) |
| 836 | break; | 837 | break; |
| 838 | udelay(10); | ||
| 837 | } | 839 | } |
| 838 | 840 | ||
| 839 | if (WARN_ON(i >= LOOP_TIMEOUT)) | 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 | fn, &intel_ir_domain_ops, | 569 | fn, &intel_ir_domain_ops, |
| 570 | iommu); | 570 | iommu); |
| 571 | if (!iommu->ir_domain) { | 571 | if (!iommu->ir_domain) { |
| 572 | irq_domain_free_fwnode(fn); | ||
| 573 | pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); | 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 | iommu->ir_msi_domain = | 575 | iommu->ir_msi_domain = |
| 577 | arch_create_remap_msi_irq_domain(iommu->ir_domain, | 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 | if (dmar_enable_qi(iommu)) { | 595 | if (dmar_enable_qi(iommu)) { |
| 597 | pr_err("Failed to enable queued invalidation\n"); | 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 | return 0; | 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 | out_free_bitmap: | 629 | out_free_bitmap: |
| 623 | bitmap_free(bitmap); | 630 | bitmap_free(bitmap); |
| 624 | out_free_pages: | 631 | out_free_pages: |
| @@ -349,6 +349,7 @@ EXPORT_SYMBOL_GPL(ioasid_alloc); · 348 unmodified lines | |||
| 349 | 349 | ||
| 350 | /** | 350 | /** |
| 351 | * ioasid_get - obtain a reference to the IOASID | 351 | * ioasid_get - obtain a reference to the IOASID |
| 352 | * @ioasid: the ID to get | ||
| 352 | */ | 353 | */ |
| 353 | void ioasid_get(ioasid_t ioasid) | 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 | static void dev_iommu_free(struct device *dev) | 208 | static void dev_iommu_free(struct device *dev) |
| 209 | { | 209 | { |
| 210 | iommu_fwspec_free(dev); | 210 | struct dev_iommu *param = dev->iommu; |
| 211 | kfree(dev->iommu); | 211 | |
| 212 | dev->iommu = NULL; | 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 | static int __iommu_probe_device(struct device *dev, struct list_head *group_list) | 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 | return ret; | 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 | static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, | 988 | static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, |
| 995 | int (*fn)(struct device *, void *)) | 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 | return ret; | 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 | int iommu_group_for_each_dev(struct iommu_group *group, void *data, | 1013 | int iommu_group_for_each_dev(struct iommu_group *group, void *data, |
| 1010 | int (*fn)(struct device *, void *)) | 1014 | int (*fn)(struct device *, void *)) |
| 1011 | { | 1015 | { |
| @@ -3032,6 +3036,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid); · 2020 unmodified lines | |||
| 3032 | * iommu_sva_bind_device() - Bind a process address space to a device | 3036 | * iommu_sva_bind_device() - Bind a process address space to a device |
| 3033 | * @dev: the device | 3037 | * @dev: the device |
| 3034 | * @mm: the mm to bind, caller must hold a reference to it | 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 | * Create a bond between device and address space, allowing the device to access | 3041 | * Create a bond between device and address space, allowing the device to access |
| 3037 | * the mm using the returned PASID. If a bond already exists between @device and | 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 | * @dev: iommu device | 1089 | * @dev: iommu device |
| 1090 | * | 1090 | * |
| 1091 | * This function performs the necessary checks to determine if the IOMMU | 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 | nowait = nowait && blk_queue_nowait(bdev_get_queue(rdev->bdev)); | 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 | if (!bioset_initialized(&mddev->bio_set)) { | 5872 | if (!bioset_initialized(&mddev->bio_set)) { |
| 5877 | err = bioset_init(&mddev->bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); | 5873 | err = bioset_init(&mddev->bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); |
| 5878 | if (err) | 5874 | if (err) |
| @@ -6010,6 +6006,10 @@ int md_run(struct mddev *mddev) · 131 unmodified lines | |||
| 6010 | else | 6006 | else |
| 6011 | blk_queue_flag_clear(QUEUE_FLAG_NONROT, mddev->queue); | 6007 | blk_queue_flag_clear(QUEUE_FLAG_NONROT, mddev->queue); |
| 6012 | blk_queue_flag_set(QUEUE_FLAG_IO_STAT, mddev->queue); | 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 | if (pers->sync_request) { | 6014 | if (pers->sync_request) { |
| 6015 | if (mddev->kobj.sd && | 6015 | if (mddev->kobj.sd && |
| @@ -67,7 +67,7 @@ static const unsigned int sd_au_size[] = { · 66 unmodified lines | |||
| 67 | __res & __mask; \ | 67 | __res & __mask; \ |
| 68 | }) | 68 | }) |
| 69 | 69 | ||
| 70 | #define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 | 70 | #define SD_POWEROFF_NOTIFY_TIMEOUT_MS 1000 |
| 71 | #define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 | 71 | #define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 |
| 72 | 72 | ||
| 73 | struct sd_busy_data { | 73 | struct sd_busy_data { |
| @@ -1664,6 +1664,12 @@ static int sd_poweroff_notify(struct mmc_card *card) · 1590 unmodified lines | |||
| 1664 | goto out; | 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 | cb_data.card = card; | 1673 | cb_data.card = card; |
| 1668 | cb_data.reg_buf = reg_buf; | 1674 | cb_data.reg_buf = reg_buf; |
| 1669 | err = __mmc_poll_for_busy(card->host, SD_POWEROFF_NOTIFY_TIMEOUT_MS, | 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 | if (!IS_ERR_OR_NULL(host->dma_chan_rx)) | 705 | if (!IS_ERR_OR_NULL(host->dma_chan_rx)) |
| 706 | dma_release_channel(host->dma_chan_rx); | 706 | dma_release_channel(host->dma_chan_rx); |
| 707 | mmc_remove_host(mmc); | 707 | mmc_remove_host(mmc); |
| 708 | mmc_free_host(mmc); | ||
| 709 | 708 | ||
| 710 | writel(0, host->base + REG_INTERRUPT_MASK); | 709 | writel(0, host->base + REG_INTERRUPT_MASK); |
| 711 | writel(0, host->base + REG_POWER_CONTROL); | 710 | writel(0, host->base + REG_POWER_CONTROL); |
| 712 | writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, | 711 | writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, |
| 713 | host->base + REG_CLOCK_CONTROL); | 712 | host->base + REG_CLOCK_CONTROL); |
| 713 | mmc_free_host(mmc); | ||
| 714 | 714 | ||
| 715 | return 0; | 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 | static int esdhc_of_enable_dma(struct sdhci_host *host) | 525 | static int esdhc_of_enable_dma(struct sdhci_host *host) |
| 526 | { | 526 | { |
| 527 | int ret; | ||
| 527 | u32 value; | 528 | u32 value; |
| 528 | struct device *dev = mmc_dev(host->mmc); | 529 | struct device *dev = mmc_dev(host->mmc); |
| 529 | 530 | ||
| 530 | if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || | 531 | if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || |
| 531 | of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) | 532 | of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { |
| 532 | dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); | 533 | ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); |
| 534 | if (ret) | ||
| 535 | return ret; | ||
| 536 | } | ||
| 533 | 537 | ||
| 534 | value = sdhci_readl(host, ESDHC_DMA_SYSCTL); | 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 | struct dma_slave_config cfg = { 0, }; | 405 | struct dma_slave_config cfg = { 0, }; |
| 406 | 406 | ||
| 407 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | 407 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); |
| 408 | if (!res) | ||
| 409 | return -EINVAL; | ||
| 410 | |||
| 408 | cfg.direction = direction; | 411 | cfg.direction = direction; |
| 409 | 412 | ||
| 410 | if (direction == DMA_DEV_TO_MEM) { | 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 | if (port->aggregator && | 1021 | if (port->aggregator && |
| 1022 | port->aggregator->is_active && | 1022 | port->aggregator->is_active && |
| 1023 | !__port_is_enabled(port)) { | 1023 | !__port_is_enabled(port)) { |
| 1024 | |||
| 1025 | __enable_port(port); | 1024 | __enable_port(port); |
| 1025 | *update_slave_arr = true; | ||
| 1026 | } | 1026 | } |
| 1027 | } | 1027 | } |
| 1028 | break; | 1028 | break; |
| @@ -1779,6 +1779,7 @@ static void ad_agg_selection_logic(struct aggregator *agg, · 750 unmodified lines | |||
| 1779 | port = port->next_port_in_aggregator) { | 1779 | port = port->next_port_in_aggregator) { |
| 1780 | __enable_port(port); | 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 | get_device(&priv->master_mii_bus->dev); | 621 | get_device(&priv->master_mii_bus->dev); |
| 622 | priv->master_mii_dn = dn; | 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 | if (!priv->slave_mii_bus) { | 625 | if (!priv->slave_mii_bus) { |
| 626 | of_node_put(dn); | 626 | of_node_put(dn); |
| 627 | return -ENOMEM; | 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 | err = mdiobus_register(priv->slave_mii_bus); | 683 | err = mdiobus_register(priv->slave_mii_bus); |
| 684 | if (err && dn) | 684 | if (err && dn) { |
| 685 | mdiobus_free(priv->slave_mii_bus); | ||
| 685 | of_node_put(dn); | 686 | of_node_put(dn); |
| 687 | } | ||
| 686 | 688 | ||
| 687 | return err; | 689 | return err; |
| 688 | } | 690 | } |
| @@ -690,6 +692,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) · 1 unmodified line | |||
| 690 | static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) | 692 | static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) |
| 691 | { | 693 | { |
| 692 | mdiobus_unregister(priv->slave_mii_bus); | 694 | mdiobus_unregister(priv->slave_mii_bus); |
| 695 | mdiobus_free(priv->slave_mii_bus); | ||
| 693 | of_node_put(priv->master_mii_dn); | 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 | static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) | 498 | static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) |
| 499 | { | 499 | { |
| 500 | struct dsa_switch *ds = priv->ds; | 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 | if (!ds->slave_mii_bus) | 504 | if (!ds->slave_mii_bus) |
| 504 | return -ENOMEM; | 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 | ds->slave_mii_bus->parent = priv->dev; | 513 | ds->slave_mii_bus->parent = priv->dev; |
| 513 | ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; | 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 | static int gswip_pce_table_entry_read(struct gswip_priv *priv, | 523 | static int gswip_pce_table_entry_read(struct gswip_priv *priv, |
| @@ -2145,8 +2150,10 @@ disable_switch: · 1626 unmodified lines | |||
| 2145 | gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); | 2150 | gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); |
| 2146 | dsa_unregister_switch(priv->ds); | 2151 | dsa_unregister_switch(priv->ds); |
| 2147 | mdio_bus: | 2152 | mdio_bus: |
| 2148 | if (mdio_np) | 2153 | if (mdio_np) { |
| 2149 | mdiobus_unregister(priv->ds->slave_mii_bus); | 2154 | mdiobus_unregister(priv->ds->slave_mii_bus); |
| 2155 | mdiobus_free(priv->ds->slave_mii_bus); | ||
| 2156 | } | ||
| 2150 | put_mdio_node: | 2157 | put_mdio_node: |
| 2151 | of_node_put(mdio_np); | 2158 | of_node_put(mdio_np); |
| 2152 | for (i = 0; i < priv->num_gphy_fw; i++) | 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 | if (priv->ds->slave_mii_bus) { | 2177 | if (priv->ds->slave_mii_bus) { |
| 2171 | mdiobus_unregister(priv->ds->slave_mii_bus); | 2178 | mdiobus_unregister(priv->ds->slave_mii_bus); |
| 2179 | mdiobus_free(priv->ds->slave_mii_bus); | ||
| 2172 | of_node_put(priv->ds->slave_mii_bus->dev.of_node); | 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 | if (priv->irq) | 2074 | if (priv->irq) |
| 2075 | mt7530_setup_mdio_irq(priv); | 2075 | mt7530_setup_mdio_irq(priv); |
| 2076 | 2076 | ||
| 2077 | ret = mdiobus_register(bus); | 2077 | ret = devm_mdiobus_register(dev, bus); |
| 2078 | if (ret) { | 2078 | if (ret) { |
| 2079 | dev_err(dev, "failed to register MDIO bus: %d\n", ret); | 2079 | dev_err(dev, "failed to register MDIO bus: %d\n", ret); |
| 2080 | if (priv->irq) | 2080 | if (priv->irq) |
| @@ -3566,7 +3566,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 3565 unmodified lines | |||
| 3566 | return err; | 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 | if (!bus) | 3570 | if (!bus) |
| 3571 | return -ENOMEM; | 3571 | return -ENOMEM; |
| 3572 | 3572 | ||
| @@ -3591,14 +3591,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 18 unmodified lines | |||
| 3591 | if (!external) { | 3591 | if (!external) { |
| 3592 | err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); | 3592 | err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); |
| 3593 | if (err) | 3593 | if (err) |
| 3594 | return err; | 3594 | goto out; |
| 3595 | } | 3595 | } |
| 3596 | 3596 | ||
| 3597 | err = of_mdiobus_register(bus, np); | 3597 | err = of_mdiobus_register(bus, np); |
| 3598 | if (err) { | 3598 | if (err) { |
| 3599 | dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); | 3599 | dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); |
| 3600 | mv88e6xxx_g2_irq_mdio_free(chip, bus); | 3600 | mv88e6xxx_g2_irq_mdio_free(chip, bus); |
| 3601 | return err; | 3601 | goto out; |
| 3602 | } | 3602 | } |
| 3603 | 3603 | ||
| 3604 | if (external) | 3604 | if (external) |
| @@ -3607,21 +3607,26 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 2 unmodified lines | |||
| 3607 | list_add(&mdio_bus->list, &chip->mdios); | 3607 | list_add(&mdio_bus->list, &chip->mdios); |
| 3608 | 3608 | ||
| 3609 | return 0; | 3609 | return 0; |
| 3610 | |||
| 3611 | out: | ||
| 3612 | mdiobus_free(bus); | ||
| 3613 | return err; | ||
| 3610 | } | 3614 | } |
| 3611 | 3615 | ||
| 3612 | static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) | 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 | struct mii_bus *bus; | 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 | bus = mdio_bus->bus; | 3623 | bus = mdio_bus->bus; |
| 3620 | 3624 | ||
| 3621 | if (!mdio_bus->external) | 3625 | if (!mdio_bus->external) |
| 3622 | mv88e6xxx_g2_irq_mdio_free(chip, bus); | 3626 | mv88e6xxx_g2_irq_mdio_free(chip, bus); |
| 3623 | 3627 | ||
| 3624 | mdiobus_unregister(bus); | 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 | return PTR_ERR(hw); | 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 | if (!bus) | 1065 | if (!bus) |
| 1066 | return -ENOMEM; | 1066 | return -ENOMEM; |
| 1067 | 1067 | ||
| @@ -1081,6 +1081,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) · 13 unmodified lines | |||
| 1081 | rc = mdiobus_register(bus); | 1081 | rc = mdiobus_register(bus); |
| 1082 | if (rc < 0) { | 1082 | if (rc < 0) { |
| 1083 | dev_err(dev, "failed to register MDIO bus\n"); | 1083 | dev_err(dev, "failed to register MDIO bus\n"); |
| 1084 | mdiobus_free(bus); | ||
| 1084 | return rc; | 1085 | return rc; |
| 1085 | } | 1086 | } |
| 1086 | 1087 | ||
| @@ -1132,6 +1133,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot) · 45 unmodified lines | |||
| 1132 | lynx_pcs_destroy(phylink_pcs); | 1133 | lynx_pcs_destroy(phylink_pcs); |
| 1133 | } | 1134 | } |
| 1134 | mdiobus_unregister(felix->imdio); | 1135 | mdiobus_unregister(felix->imdio); |
| 1136 | mdiobus_free(felix->imdio); | ||
| 1135 | } | 1137 | } |
| 1136 | 1138 | ||
| 1137 | static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, | 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 | /* Needed in order to initialize the bus mutex lock */ | 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 | if (rc < 0) { | 1033 | if (rc < 0) { |
| 1034 | dev_err(dev, "failed to register MDIO bus\n"); | 1034 | dev_err(dev, "failed to register MDIO bus\n"); |
| 1035 | return rc; | 1035 | return rc; |
| @@ -1083,7 +1083,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) · 47 unmodified lines | |||
| 1083 | mdio_device_free(mdio_device); | 1083 | mdio_device_free(mdio_device); |
| 1084 | lynx_pcs_destroy(phylink_pcs); | 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 | static const struct felix_info seville_info_vsc9953 = { | 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 | if (!mnp) | 378 | if (!mnp) |
| 379 | return -ENODEV; | 379 | return -ENODEV; |
| 380 | 380 | ||
| 381 | ret = of_mdiobus_register(mbus, mnp); | 381 | ret = devm_of_mdiobus_register(dev, mbus, mnp); |
| 382 | of_node_put(mnp); | 382 | of_node_put(mnp); |
| 383 | if (ret) | 383 | if (ret) |
| 384 | return ret; | 384 | return ret; |
| @@ -1066,7 +1066,6 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev) · 681 unmodified lines | |||
| 1066 | } | 1066 | } |
| 1067 | 1067 | ||
| 1068 | irq_domain_remove(priv->irqdomain); | 1068 | irq_domain_remove(priv->irqdomain); |
| 1069 | mdiobus_unregister(priv->mbus); | ||
| 1070 | dsa_unregister_switch(&priv->ds); | 1069 | dsa_unregister_switch(&priv->ds); |
| 1071 | 1070 | ||
| 1072 | reset_control_assert(priv->sw_reset); | 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 | pci_free_irq_vectors(pdata->pcidev); | 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 | xgbe_free_pdata(pdata); | 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 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT | 4766 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT |
| 4767 | if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) { | 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 | bp->hw_dma_cap |= HW_DMA_CAP_64B; | 4769 | bp->hw_dma_cap |= HW_DMA_CAP_64B; |
| 4770 | } | 4770 | } |
| 4771 | #endif | 4771 | #endif |
| @@ -4733,12 +4733,12 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) · 4732 unmodified lines | |||
| 4733 | #ifdef CONFIG_DEBUG_FS | 4733 | #ifdef CONFIG_DEBUG_FS |
| 4734 | dpaa2_dbg_remove(priv); | 4734 | dpaa2_dbg_remove(priv); |
| 4735 | #endif | 4735 | #endif |
| 4736 | |||
| 4737 | unregister_netdev(net_dev); | ||
| 4736 | rtnl_lock(); | 4738 | rtnl_lock(); |
| 4737 | dpaa2_eth_disconnect_mac(priv); | 4739 | dpaa2_eth_disconnect_mac(priv); |
| 4738 | rtnl_unlock(); | 4740 | rtnl_unlock(); |
| 4739 | 4741 | ||
| 4740 | unregister_netdev(net_dev); | ||
| 4741 | |||
| 4742 | dpaa2_eth_dl_port_del(priv); | 4742 | dpaa2_eth_dl_port_del(priv); |
| 4743 | dpaa2_eth_dl_traps_unregister(priv); | 4743 | dpaa2_eth_dl_traps_unregister(priv); |
| 4744 | dpaa2_eth_dl_free(priv); | 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 | *packet_size_bytes = skb->len + (skb->protocol ? ETH_HLEN : 0); | 610 | *packet_size_bytes = skb->len + (skb->protocol ? ETH_HLEN : 0); |
| 611 | *work_done = work_cnt; | 611 | *work_done = work_cnt; |
| 612 | skb_record_rx_queue(skb, rx->q_num); | ||
| 612 | if (skb_is_nonlinear(skb)) | 613 | if (skb_is_nonlinear(skb)) |
| 613 | napi_gro_frags(napi); | 614 | napi_gro_frags(napi); |
| 614 | else | 615 | else |
| @@ -110,6 +110,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, · 109 unmodified lines | |||
| 110 | struct ibmvnic_sub_crq_queue *tx_scrq); | 110 | struct ibmvnic_sub_crq_queue *tx_scrq); |
| 111 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, | 111 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, |
| 112 | struct ibmvnic_long_term_buff *ltb); | 112 | struct ibmvnic_long_term_buff *ltb); |
| 113 | static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); | ||
| 113 | 114 | ||
| 114 | struct ibmvnic_stat { | 115 | struct ibmvnic_stat { |
| 115 | char name[ETH_GSTRING_LEN]; | 116 | char name[ETH_GSTRING_LEN]; |
| @@ -1424,7 +1425,7 @@ static int __ibmvnic_open(struct net_device *netdev) · 1308 unmodified lines | |||
| 1424 | rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); | 1425 | rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); |
| 1425 | if (rc) { | 1426 | if (rc) { |
| 1426 | ibmvnic_napi_disable(adapter); | 1427 | ibmvnic_napi_disable(adapter); |
| 1427 | release_resources(adapter); | 1428 | ibmvnic_disable_irqs(adapter); |
| 1428 | return rc; | 1429 | return rc; |
| 1429 | } | 1430 | } |
| 1430 | 1431 | ||
| @@ -1474,9 +1475,6 @@ static int ibmvnic_open(struct net_device *netdev) · 43 unmodified lines | |||
| 1474 | rc = init_resources(adapter); | 1475 | rc = init_resources(adapter); |
| 1475 | if (rc) { | 1476 | if (rc) { |
| 1476 | netdev_err(netdev, "failed to initialize resources\n"); | 1477 | netdev_err(netdev, "failed to initialize resources\n"); |
| 1477 | release_resources(adapter); | ||
| 1478 | release_rx_pools(adapter); | ||
| 1479 | release_tx_pools(adapter); | ||
| 1480 | goto out; | 1478 | goto out; |
| 1481 | } | 1479 | } |
| 1482 | } | 1480 | } |
| @@ -1493,6 +1491,13 @@ out: · 10 unmodified lines | |||
| 1493 | adapter->state = VNIC_OPEN; | 1491 | adapter->state = VNIC_OPEN; |
| 1494 | rc = 0; | 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 | return rc; | 1501 | return rc; |
| 1497 | } | 1502 | } |
| 1498 | 1503 | ||
| @@ -487,6 +487,7 @@ enum ice_pf_flags { · 486 unmodified lines | |||
| 487 | ICE_FLAG_MDD_AUTO_RESET_VF, | 487 | ICE_FLAG_MDD_AUTO_RESET_VF, |
| 488 | ICE_FLAG_VF_VLAN_PRUNING, | 488 | ICE_FLAG_VF_VLAN_PRUNING, |
| 489 | ICE_FLAG_LINK_LENIENT_MODE_ENA, | 489 | ICE_FLAG_LINK_LENIENT_MODE_ENA, |
| 490 | ICE_FLAG_PLUG_AUX_DEV, | ||
| 490 | ICE_PF_FLAGS_NBITS /* must be last */ | 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 | if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) { | 892 | if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) { |
| 892 | set_bit(ICE_FLAG_RDMA_ENA, pf->flags); | 893 | set_bit(ICE_FLAG_RDMA_ENA, pf->flags); |
| 893 | set_bit(ICE_FLAG_AUX_ENA, pf->flags); | 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 | !ice_fw_supports_report_dflt_cfg(hw)) { | 3381 | !ice_fw_supports_report_dflt_cfg(hw)) { |
| 3382 | struct ice_link_default_override_tlv tlv; | 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 | goto out; | 3386 | goto out; |
| 3386 | 3387 | ||
| 3387 | if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && | 3388 | if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && |
| @@ -204,17 +204,39 @@ ice_lag_unlink(struct ice_lag *lag, · 203 unmodified lines | |||
| 204 | lag->upper_netdev = NULL; | 204 | lag->upper_netdev = NULL; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | if (lag->peer_netdev) { | 207 | lag->peer_netdev = NULL; |
| 208 | dev_put(lag->peer_netdev); | ||
| 209 | lag->peer_netdev = NULL; | ||
| 210 | } | ||
| 211 | |||
| 212 | ice_set_sriov_cap(pf); | 208 | ice_set_sriov_cap(pf); |
| 213 | ice_set_rdma_cap(pf); | 209 | ice_set_rdma_cap(pf); |
| 214 | lag->bonded = false; | 210 | lag->bonded = false; |
| 215 | lag->role = ICE_LAG_NONE; | 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 | * ice_lag_changeupper_event - handle LAG changeupper event | 241 | * ice_lag_changeupper_event - handle LAG changeupper event |
| 220 | * @lag: LAG info struct | 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 | ice_lag_info_event(lag, ptr); | 329 | ice_lag_info_event(lag, ptr); |
| 308 | break; | 330 | break; |
| 309 | case NETDEV_UNREGISTER: | 331 | case NETDEV_UNREGISTER: |
| 310 | ice_lag_unlink(lag, ptr); | 332 | ice_lag_unregister(lag, netdev); |
| 311 | break; | 333 | break; |
| 312 | default: | 334 | default: |
| 313 | break; | 335 | break; |
| @@ -570,6 +570,7 @@ struct ice_tx_ctx_desc { · 569 unmodified lines | |||
| 570 | (0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S) | 570 | (0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S) |
| 571 | 571 | ||
| 572 | #define ICE_TXD_CTX_QW1_MSS_S 50 | 572 | #define ICE_TXD_CTX_QW1_MSS_S 50 |
| 573 | #define ICE_TXD_CTX_MIN_MSS 64 | ||
| 573 | 574 | ||
| 574 | #define ICE_TXD_CTX_QW1_VSI_S 50 | 575 | #define ICE_TXD_CTX_QW1_VSI_S 50 |
| 575 | #define ICE_TXD_CTX_QW1_VSI_M (0x3FFULL << ICE_TXD_CTX_QW1_VSI_S) | 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 | return; | 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 | ice_clean_adminq_subtask(pf); | 2262 | ice_clean_adminq_subtask(pf); |
| 2260 | ice_check_media_subtask(pf); | 2263 | ice_check_media_subtask(pf); |
| 2261 | ice_check_for_hang_subtask(pf); | 2264 | ice_check_for_hang_subtask(pf); |
| @@ -8724,6 +8727,7 @@ ice_features_check(struct sk_buff *skb, · 6462 unmodified lines | |||
| 8724 | struct net_device __always_unused *netdev, | 8727 | struct net_device __always_unused *netdev, |
| 8725 | netdev_features_t features) | 8728 | netdev_features_t features) |
| 8726 | { | 8729 | { |
| 8730 | bool gso = skb_is_gso(skb); | ||
| 8727 | size_t len; | 8731 | size_t len; |
| 8728 | 8732 | ||
| 8729 | /* No point in doing any of this if neither checksum nor GSO are | 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 | /* We cannot support GSO if the MSS is going to be less than | 8740 | /* We cannot support GSO if the MSS is going to be less than |
| 8737 | * 64 bytes. If it is then we need to drop support for GSO. | 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 | features &= ~NETIF_F_GSO_MASK; | 8744 | features &= ~NETIF_F_GSO_MASK; |
| 8741 | 8745 | ||
| 8742 | len = skb_network_header(skb) - skb->data; | 8746 | len = skb_network_offset(skb); |
| 8743 | if (len > ICE_TXD_MACLEN_MAX || len & 0x1) | 8747 | if (len > ICE_TXD_MACLEN_MAX || len & 0x1) |
| 8744 | goto out_rm_features; | 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 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) | 8751 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) |
| 8748 | goto out_rm_features; | 8752 | goto out_rm_features; |
| 8749 | 8753 | ||
| 8750 | if (skb->encapsulation) { | 8754 | if (skb->encapsulation) { |
| 8751 | len = skb_inner_network_header(skb) - skb_transport_header(skb); | 8755 | /* this must work for VXLAN frames AND IPIP/SIT frames, and in |
| 8752 | if (len > ICE_TXD_L4LEN_MAX || len & 0x1) | 8756 | * the case of IPIP frames, the transport header pointer is |
| 8753 | goto out_rm_features; | 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) - | 8768 | len = skb_inner_network_header_len(skb); |
| 8756 | skb_inner_network_header(skb); | ||
| 8757 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) | 8769 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) |
| 8758 | goto out_rm_features; | 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 | if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) | 1984 | if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) |
| 1985 | return; | 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) { | 1991 | /* 82599 can't rely on RXDCTL.RLPML to restrict the size of the frame */ |
| 1990 | if (max_frame <= IXGBEVF_MAX_FRAME_BUILD_SKB) | 1992 | if (adapter->hw.mac.type == ixgbe_mac_82599_vf && !ring_uses_large_buffer(rx_ring)) |
| 1991 | return; | 1993 | return; |
| 1992 | 1994 | ||
| 1993 | set_ring_uses_large_buffer(rx_ring); | 1995 | set_ring_build_skb_enabled(rx_ring); |
| 1994 | } | ||
| 1995 | } | 1996 | } |
| 1996 | 1997 | ||
| 1997 | /** | 1998 | /** |
| @@ -17,7 +17,7 @@ if NET_VENDOR_LITEX · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | config LITEX_LITEETH | 18 | config LITEX_LITEETH |
| 19 | tristate "LiteX Ethernet support" | 19 | tristate "LiteX Ethernet support" |
| 20 | depends on OF | 20 | depends on OF && HAS_IOMEM |
| 21 | help | 21 | help |
| 22 | If you wish to compile a kernel for hardware with a LiteX LiteEth | 22 | If you wish to compile a kernel for hardware with a LiteX LiteEth |
| 23 | device then you should answer Y to this. | 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 | stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt]; | 1103 | stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt]; |
| 1104 | stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt]; | 1104 | stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt]; |
| 1105 | stats->rx_dropped = portstats[spx5_stats_ana_ac_port_stat_lsb_cnt]; | 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 | stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop | 1107 | stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop |
| 1108 | + idx]; | 1108 | + idx]; |
| 1109 | stats->tx_dropped = portstats[spx5_stats_tx_local_drop]; | 1109 | stats->tx_dropped = portstats[spx5_stats_tx_local_drop]; |
| @@ -1432,6 +1432,8 @@ static void · 1431 unmodified lines | |||
| 1432 | ocelot_populate_ipv4_ptp_event_trap_key(struct ocelot_vcap_filter *trap) | 1432 | ocelot_populate_ipv4_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 1433 | { | 1433 | { |
| 1434 | trap->key_type = OCELOT_VCAP_KEY_IPV4; | 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 | trap->key.ipv4.dport.value = PTP_EV_PORT; | 1437 | trap->key.ipv4.dport.value = PTP_EV_PORT; |
| 1436 | trap->key.ipv4.dport.mask = 0xffff; | 1438 | trap->key.ipv4.dport.mask = 0xffff; |
| 1437 | } | 1439 | } |
| @@ -1440,6 +1442,8 @@ static void · 2 unmodified lines | |||
| 1440 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) | 1442 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 1441 | { | 1443 | { |
| 1442 | trap->key_type = OCELOT_VCAP_KEY_IPV6; | 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 | trap->key.ipv6.dport.value = PTP_EV_PORT; | 1447 | trap->key.ipv6.dport.value = PTP_EV_PORT; |
| 1444 | trap->key.ipv6.dport.mask = 0xffff; | 1448 | trap->key.ipv6.dport.mask = 0xffff; |
| 1445 | } | 1449 | } |
| @@ -1448,6 +1452,8 @@ static void · 2 unmodified lines | |||
| 1448 | ocelot_populate_ipv4_ptp_general_trap_key(struct ocelot_vcap_filter *trap) | 1452 | ocelot_populate_ipv4_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 1449 | { | 1453 | { |
| 1450 | trap->key_type = OCELOT_VCAP_KEY_IPV4; | 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 | trap->key.ipv4.dport.value = PTP_GEN_PORT; | 1457 | trap->key.ipv4.dport.value = PTP_GEN_PORT; |
| 1452 | trap->key.ipv4.dport.mask = 0xffff; | 1458 | trap->key.ipv4.dport.mask = 0xffff; |
| 1453 | } | 1459 | } |
| @@ -1456,6 +1462,8 @@ static void · 2 unmodified lines | |||
| 1456 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) | 1462 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 1457 | { | 1463 | { |
| 1458 | trap->key_type = OCELOT_VCAP_KEY_IPV6; | 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 | trap->key.ipv6.dport.value = PTP_GEN_PORT; | 1467 | trap->key.ipv6.dport.value = PTP_GEN_PORT; |
| 1460 | trap->key.ipv6.dport.mask = 0xffff; | 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 | EXPORT_SYMBOL(ocelot_get_strings); | 1746 | EXPORT_SYMBOL(ocelot_get_strings); |
| 1739 | 1747 | ||
| 1748 | /* Caller must hold &ocelot->stats_lock */ | ||
| 1740 | static void ocelot_update_stats(struct ocelot *ocelot) | 1749 | static void ocelot_update_stats(struct ocelot *ocelot) |
| 1741 | { | 1750 | { |
| 1742 | int i, j; | 1751 | int i, j; |
| 1743 | 1752 | ||
| 1744 | mutex_lock(&ocelot->stats_lock); | ||
| 1745 | |||
| 1746 | for (i = 0; i < ocelot->num_phys_ports; i++) { | 1753 | for (i = 0; i < ocelot->num_phys_ports; i++) { |
| 1747 | /* Configure the port to read the stats from */ | 1754 | /* Configure the port to read the stats from */ |
| 1748 | ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(i), SYS_STAT_CFG); | 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 | ~(u64)U32_MAX) + val; | 1768 | ~(u64)U32_MAX) + val; |
| 1762 | } | 1769 | } |
| 1763 | } | 1770 | } |
| 1764 | |||
| 1765 | mutex_unlock(&ocelot->stats_lock); | ||
| 1766 | } | 1771 | } |
| 1767 | 1772 | ||
| 1768 | static void ocelot_check_stats_work(struct work_struct *work) | 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 | struct ocelot *ocelot = container_of(del_work, struct ocelot, | 1776 | struct ocelot *ocelot = container_of(del_work, struct ocelot, |
| 1772 | stats_work); | 1777 | stats_work); |
| 1773 | 1778 | ||
| 1779 | mutex_lock(&ocelot->stats_lock); | ||
| 1774 | ocelot_update_stats(ocelot); | 1780 | ocelot_update_stats(ocelot); |
| 1781 | mutex_unlock(&ocelot->stats_lock); | ||
| 1775 | 1782 | ||
| 1776 | queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, | 1783 | queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, |
| 1777 | OCELOT_STATS_CHECK_DELAY); | 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 | int i; | 1789 | int i; |
| 1783 | 1790 | ||
| 1791 | mutex_lock(&ocelot->stats_lock); | ||
| 1792 | |||
| 1784 | /* check and update now */ | 1793 | /* check and update now */ |
| 1785 | ocelot_update_stats(ocelot); | 1794 | ocelot_update_stats(ocelot); |
| 1786 | 1795 | ||
| 1787 | /* Copy all counters */ | 1796 | /* Copy all counters */ |
| 1788 | for (i = 0; i < ocelot->num_stats; i++) | 1797 | for (i = 0; i < ocelot->num_stats; i++) |
| 1789 | *data++ = ocelot->stats[port * ocelot->num_stats + i]; | 1798 | *data++ = ocelot->stats[port * ocelot->num_stats + i]; |
| 1799 | |||
| 1800 | mutex_unlock(&ocelot->stats_lock); | ||
| 1790 | } | 1801 | } |
| 1791 | EXPORT_SYMBOL(ocelot_get_ethtool_stats); | 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 | struct nfp_flower_repr_priv *repr_priv; | 1011 | struct nfp_flower_repr_priv *repr_priv; |
| 1012 | struct nfp_tun_offloaded_mac *entry; | 1012 | struct nfp_tun_offloaded_mac *entry; |
| 1013 | struct nfp_repr *repr; | 1013 | struct nfp_repr *repr; |
| 1014 | u16 nfp_mac_idx; | ||
| 1014 | int ida_idx; | 1015 | int ida_idx; |
| 1015 | 1016 | ||
| 1016 | entry = nfp_tunnel_lookup_offloaded_macs(app, mac); | 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 | entry->bridge_count--; | 1030 | entry->bridge_count--; |
| 1030 | 1031 | ||
| 1031 | if (!entry->bridge_count && entry->ref_count) { | 1032 | if (!entry->bridge_count && entry->ref_count) { |
| 1032 | u16 nfp_mac_idx; | ||
| 1033 | |||
| 1034 | nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; | 1033 | nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; |
| 1035 | if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, | 1034 | if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, |
| 1036 | false)) { | 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 | /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ | 1046 | /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ |
| 1048 | if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { | 1047 | if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { |
| 1049 | u16 nfp_mac_idx; | ||
| 1050 | int port, err; | 1048 | int port, err; |
| 1051 | 1049 | ||
| 1052 | repr_priv = list_first_entry(&entry->repr_list, | 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 | WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, | 1072 | WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, |
| 1075 | &entry->ht_node, | 1073 | &entry->ht_node, |
| 1076 | offloaded_macs_params)); | 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 | /* If MAC has global ID then extract and free the ida entry. */ | 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 | ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); | 1083 | ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); |
| 1080 | ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); | 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 | { .compatible = "aspeed,ast2600-mdio", }, | 148 | { .compatible = "aspeed,ast2600-mdio", }, |
| 149 | { }, | 149 | { }, |
| 150 | }; | 150 | }; |
| 151 | MODULE_DEVICE_TABLE(of, aspeed_mdio_of_match); | ||
| 151 | 152 | ||
| 152 | static struct platform_driver aspeed_mdio_driver = { | 153 | static struct platform_driver aspeed_mdio_driver = { |
| 153 | .driver = { | 154 | .driver = { |
| @@ -553,9 +553,9 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev) · 552 unmodified lines | |||
| 553 | else | 553 | else |
| 554 | mscr = 0; | 554 | mscr = 0; |
| 555 | 555 | ||
| 556 | return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE, | 556 | return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE, |
| 557 | MII_88E1121_PHY_MSCR_REG, | 557 | MII_88E1121_PHY_MSCR_REG, |
| 558 | MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); | 558 | MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); |
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | static int m88e1121_config_aneg(struct phy_device *phydev) | 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 | return err; | 569 | return err; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | changed = err; | ||
| 573 | |||
| 572 | err = marvell_set_polarity(phydev, phydev->mdix_ctrl); | 574 | err = marvell_set_polarity(phydev, phydev->mdix_ctrl); |
| 573 | if (err < 0) | 575 | if (err < 0) |
| 574 | return err; | 576 | return err; |
| 575 | 577 | ||
| 576 | changed = err; | 578 | changed |= err; |
| 577 | 579 | ||
| 578 | err = genphy_config_aneg(phydev); | 580 | err = genphy_config_aneg(phydev); |
| 579 | if (err < 0) | 581 | if (err < 0) |
| @@ -1213,16 +1215,15 @@ static int m88e1118_config_aneg(struct phy_device *phydev) · 633 unmodified lines | |||
| 1213 | { | 1215 | { |
| 1214 | int err; | 1216 | int err; |
| 1215 | 1217 | ||
| 1216 | err = genphy_soft_reset(phydev); | 1218 | err = marvell_set_polarity(phydev, phydev->mdix_ctrl); |
| 1217 | if (err < 0) | 1219 | if (err < 0) |
| 1218 | return err; | 1220 | return err; |
| 1219 | 1221 | ||
| 1220 | err = marvell_set_polarity(phydev, phydev->mdix_ctrl); | 1222 | err = genphy_config_aneg(phydev); |
| 1221 | if (err < 0) | 1223 | if (err < 0) |
| 1222 | return err; | 1224 | return err; |
| 1223 | 1225 | ||
| 1224 | err = genphy_config_aneg(phydev); | 1226 | return genphy_soft_reset(phydev); |
| 1225 | return 0; | ||
| 1226 | } | 1227 | } |
| 1227 | 1228 | ||
| 1228 | static int m88e1118_config_init(struct phy_device *phydev) | 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 | {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ | 1400 | {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ |
| 1401 | {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ | 1401 | {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ |
| 1402 | {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ | 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 | {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ | 1405 | {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ |
| 1404 | {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ | 1406 | {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ |
| 1405 | {QMI_QUIRK_SET_DTR(0x22de, 0x9051, 2)}, /* Hucom Wireless HM-211S/K */ | 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 | /* Write ptr_ring before reading rx_notify_masked */ | 266 | /* Write ptr_ring before reading rx_notify_masked */ |
| 267 | smp_mb(); | 267 | smp_mb(); |
| 268 | if (!rq->rx_notify_masked) { | 268 | if (!READ_ONCE(rq->rx_notify_masked) && |
| 269 | rq->rx_notify_masked = true; | 269 | napi_schedule_prep(&rq->xdp_napi)) { |
| 270 | napi_schedule(&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 | /* Write rx_notify_masked before reading ptr_ring */ | 913 | /* Write rx_notify_masked before reading ptr_ring */ |
| 913 | smp_store_mb(rq->rx_notify_masked, false); | 914 | smp_store_mb(rq->rx_notify_masked, false); |
| 914 | if (unlikely(!__ptr_ring_empty(&rq->xdp_ring))) { | 915 | if (unlikely(!__ptr_ring_empty(&rq->xdp_ring))) { |
| 915 | rq->rx_notify_masked = true; | 916 | if (napi_schedule_prep(&rq->xdp_napi)) { |
| 916 | napi_schedule(&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 | container_of(work, struct nvme_ctrl, async_event_work); | 4253 | container_of(work, struct nvme_ctrl, async_event_work); |
| 4254 | 4254 | ||
| 4255 | nvme_aen_uevent(ctrl); | 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 | static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl) | 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 | struct nvmf_ctrl_options *opts) | 170 | struct nvmf_ctrl_options *opts) |
| 171 | { | 171 | { |
| 172 | if (ctrl->state == NVME_CTRL_DELETING || | 172 | if (ctrl->state == NVME_CTRL_DELETING || |
| 173 | ctrl->state == NVME_CTRL_DELETING_NOIO || | ||
| 173 | ctrl->state == NVME_CTRL_DEAD || | 174 | ctrl->state == NVME_CTRL_DEAD || |
| 174 | strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || | 175 | strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || |
| 175 | strcmp(opts->host->nqn, ctrl->opts->host->nqn) || | 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 | struct nvme_rdma_ctrl, err_work); | 1200 | struct nvme_rdma_ctrl, err_work); |
| 1201 | 1201 | ||
| 1202 | nvme_stop_keep_alive(&ctrl->ctrl); | 1202 | nvme_stop_keep_alive(&ctrl->ctrl); |
| 1203 | flush_work(&ctrl->ctrl.async_event_work); | ||
| 1203 | nvme_rdma_teardown_io_queues(ctrl, false); | 1204 | nvme_rdma_teardown_io_queues(ctrl, false); |
| 1204 | nvme_start_queues(&ctrl->ctrl); | 1205 | nvme_start_queues(&ctrl->ctrl); |
| 1205 | nvme_rdma_teardown_admin_queue(ctrl, false); | 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 | struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl; | 2096 | struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl; |
| 2097 | 2097 | ||
| 2098 | nvme_stop_keep_alive(ctrl); | 2098 | nvme_stop_keep_alive(ctrl); |
| 2099 | flush_work(&ctrl->async_event_work); | ||
| 2099 | nvme_tcp_teardown_io_queues(ctrl, false); | 2100 | nvme_tcp_teardown_io_queues(ctrl, false); |
| 2100 | /* unquiesce to fail fast pending requests */ | 2101 | /* unquiesce to fail fast pending requests */ |
| 2101 | nvme_start_queues(ctrl); | 2102 | nvme_start_queues(ctrl); |
| @@ -356,8 +356,8 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 355 unmodified lines | |||
| 356 | const struct j721e_pcie_data *data; | 356 | const struct j721e_pcie_data *data; |
| 357 | struct cdns_pcie *cdns_pcie; | 357 | struct cdns_pcie *cdns_pcie; |
| 358 | struct j721e_pcie *pcie; | 358 | struct j721e_pcie *pcie; |
| 359 | struct cdns_pcie_rc *rc; | 359 | struct cdns_pcie_rc *rc = NULL; |
| 360 | struct cdns_pcie_ep *ep; | 360 | struct cdns_pcie_ep *ep = NULL; |
| 361 | struct gpio_desc *gpiod; | 361 | struct gpio_desc *gpiod; |
| 362 | void __iomem *base; | 362 | void __iomem *base; |
| 363 | struct clk *clk; | 363 | struct clk *clk; |
| @@ -376,6 +376,46 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 376 | if (!pcie) | 376 | if (!pcie) |
| 377 | return -ENOMEM; | 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 | pcie->mode = mode; | 419 | pcie->mode = mode; |
| 380 | pcie->linkdown_irq_regfield = data->linkdown_irq_regfield; | 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 | switch (mode) { | 467 | switch (mode) { |
| 428 | case PCI_MODE_RC: | 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 | gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); | 469 | gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); |
| 452 | if (IS_ERR(gpiod)) { | 470 | if (IS_ERR(gpiod)) { |
| 453 | ret = PTR_ERR(gpiod); | 471 | ret = PTR_ERR(gpiod); |
| @@ -497,23 +515,6 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 43 unmodified lines | |||
| 497 | 515 | ||
| 498 | break; | 516 | break; |
| 499 | case PCI_MODE_EP: | 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 | ret = cdns_pcie_init_phy(dev, cdns_pcie); | 518 | ret = cdns_pcie_init_phy(dev, cdns_pcie); |
| 518 | if (ret) { | 519 | if (ret) { |
| 519 | dev_err(dev, "Failed to init phy\n"); | 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 | goto err_pcie_setup; | 526 | goto err_pcie_setup; |
| 526 | 527 | ||
| 527 | break; | 528 | break; |
| 528 | default: | ||
| 529 | dev_err(dev, "INVALID device type %d\n", mode); | ||
| 530 | } | 529 | } |
| 531 | 530 | ||
| 532 | return 0; | 531 | return 0; |
| @@ -756,22 +756,28 @@ static int __exit kirin_pcie_remove(struct platform_device *pdev) · 755 unmodified lines | |||
| 756 | return 0; | 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 | static const struct of_device_id kirin_pcie_match[] = { | 771 | static const struct of_device_id kirin_pcie_match[] = { |
| 760 | { | 772 | { .compatible = "hisilicon,kirin960-pcie", .data = &kirin_960_data }, |
| 761 | .compatible = "hisilicon,kirin960-pcie", | 773 | { .compatible = "hisilicon,kirin970-pcie", .data = &kirin_970_data }, |
| 762 | .data = (void *)PCIE_KIRIN_INTERNAL_PHY | ||
| 763 | }, | ||
| 764 | { | ||
| 765 | .compatible = "hisilicon,kirin970-pcie", | ||
| 766 | .data = (void *)PCIE_KIRIN_EXTERNAL_PHY | ||
| 767 | }, | ||
| 768 | {}, | 774 | {}, |
| 769 | }; | 775 | }; |
| 770 | 776 | ||
| 771 | static int kirin_pcie_probe(struct platform_device *pdev) | 777 | static int kirin_pcie_probe(struct platform_device *pdev) |
| 772 | { | 778 | { |
| 773 | enum pcie_kirin_phy_type phy_type; | ||
| 774 | struct device *dev = &pdev->dev; | 779 | struct device *dev = &pdev->dev; |
| 780 | const struct kirin_pcie_data *data; | ||
| 775 | struct kirin_pcie *kirin_pcie; | 781 | struct kirin_pcie *kirin_pcie; |
| 776 | struct dw_pcie *pci; | 782 | struct dw_pcie *pci; |
| 777 | int ret; | 783 | int ret; |
| @@ -781,13 +787,12 @@ static int kirin_pcie_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 781 | return -EINVAL; | 787 | return -EINVAL; |
| 782 | } | 788 | } |
| 783 | 789 | ||
| 784 | phy_type = (long)of_device_get_match_data(dev); | 790 | data = of_device_get_match_data(dev); |
| 785 | if (!phy_type) { | 791 | if (!data) { |
| 786 | dev_err(dev, "OF data missing\n"); | 792 | dev_err(dev, "OF data missing\n"); |
| 787 | return -EINVAL; | 793 | return -EINVAL; |
| 788 | } | 794 | } |
| 789 | 795 | ||
| 790 | |||
| 791 | kirin_pcie = devm_kzalloc(dev, sizeof(struct kirin_pcie), GFP_KERNEL); | 796 | kirin_pcie = devm_kzalloc(dev, sizeof(struct kirin_pcie), GFP_KERNEL); |
| 792 | if (!kirin_pcie) | 797 | if (!kirin_pcie) |
| 793 | return -ENOMEM; | 798 | return -ENOMEM; |
| @@ -800,7 +805,7 @@ static int kirin_pcie_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 800 | pci->ops = &kirin_dw_pcie_ops; | 805 | pci->ops = &kirin_dw_pcie_ops; |
| 801 | pci->pp.ops = &kirin_pcie_host_ops; | 806 | pci->pp.ops = &kirin_pcie_host_ops; |
| 802 | kirin_pcie->pci = pci; | 807 | kirin_pcie->pci = pci; |
| 803 | kirin_pcie->type = phy_type; | 808 | kirin_pcie->type = data->phy_type; |
| 804 | 809 | ||
| 805 | ret = kirin_pcie_get_resource(kirin_pcie, pdev); | 810 | ret = kirin_pcie_get_resource(kirin_pcie, pdev); |
| 806 | if (ret) | 811 | if (ret) |
| @@ -1111,7 +1111,8 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) · 1110 unmodified lines | |||
| 1111 | if (!desc) | 1111 | if (!desc) |
| 1112 | return cpu_possible_mask; | 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 | return NULL; | 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 | static void bnx2fc_recv_frame(struct sk_buff *skb) | 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 | struct fc_lport *lport; | 513 | struct fc_lport *lport; |
| 513 | struct fcoe_rcv_info *fr; | 514 | struct fcoe_rcv_info *fr; |
| 514 | struct fc_stats *stats; | 515 | struct fc_stats *stats; |
| @@ -542,6 +543,11 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) · 27 unmodified lines | |||
| 542 | skb_pull(skb, sizeof(struct fcoe_hdr)); | 543 | skb_pull(skb, sizeof(struct fcoe_hdr)); |
| 543 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); | 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 | fp = (struct fc_frame *)skb; | 551 | fp = (struct fc_frame *)skb; |
| 546 | fc_frame_init(fp); | 552 | fc_frame_init(fp); |
| 547 | fr_dev(fp) = lport; | 553 | fr_dev(fp) = lport; |
| @@ -624,16 +630,15 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) · 76 unmodified lines | |||
| 624 | return; | 630 | return; |
| 625 | } | 631 | } |
| 626 | 632 | ||
| 627 | stats = per_cpu_ptr(lport->stats, smp_processor_id()); | 633 | fr_crc = le32_to_cpu(fr_crc(fp)); |
| 628 | stats->RxFrames++; | ||
| 629 | stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | ||
| 630 | 634 | ||
| 631 | if (le32_to_cpu(fr_crc(fp)) != | 635 | if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) { |
| 632 | ~crc32(~0, skb->data, fr_len)) { | 636 | stats = per_cpu_ptr(lport->stats, get_cpu()); |
| 633 | if (stats->InvalidCRCCount < 5) | 637 | crc_err = (stats->InvalidCRCCount++); |
| 638 | put_cpu(); | ||
| 639 | if (crc_err < 5) | ||
| 634 | printk(KERN_WARNING PFX "dropping frame with " | 640 | printk(KERN_WARNING PFX "dropping frame with " |
| 635 | "CRC error\n"); | 641 | "CRC error\n"); |
| 636 | stats->InvalidCRCCount++; | ||
| 637 | kfree_skb(skb); | 642 | kfree_skb(skb); |
| 638 | return; | 643 | return; |
| 639 | } | 644 | } |
| @@ -400,8 +400,7 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, · 399 unmodified lines | |||
| 400 | struct hisi_sas_slot *slot, | 400 | struct hisi_sas_slot *slot, |
| 401 | struct hisi_sas_dq *dq, | 401 | struct hisi_sas_dq *dq, |
| 402 | struct hisi_sas_device *sas_dev, | 402 | struct hisi_sas_device *sas_dev, |
| 403 | struct hisi_sas_internal_abort *abort, | 403 | struct hisi_sas_internal_abort *abort) |
| 404 | struct hisi_sas_tmf_task *tmf) | ||
| 405 | { | 404 | { |
| 406 | struct hisi_sas_cmd_hdr *cmd_hdr_base; | 405 | struct hisi_sas_cmd_hdr *cmd_hdr_base; |
| 407 | int dlvry_queue_slot, dlvry_queue; | 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 | cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue]; | 426 | cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue]; |
| 428 | slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot]; | 427 | slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot]; |
| 429 | 428 | ||
| 430 | slot->tmf = tmf; | ||
| 431 | slot->is_internal = tmf; | ||
| 432 | task->lldd_task = slot; | 429 | task->lldd_task = slot; |
| 433 | 430 | ||
| 434 | memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); | 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 | slot->is_internal = tmf; | 584 | slot->is_internal = tmf; |
| 588 | 585 | ||
| 589 | /* protect task_prep and start_delivery sequence */ | 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 | return 0; | 589 | return 0; |
| 593 | 590 | ||
| @@ -1380,12 +1377,13 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) · 786 unmodified lines | |||
| 1380 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); | 1377 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
| 1381 | struct device *dev = hisi_hba->dev; | 1378 | struct device *dev = hisi_hba->dev; |
| 1382 | int s = sizeof(struct host_to_dev_fis); | 1379 | int s = sizeof(struct host_to_dev_fis); |
| 1380 | struct hisi_sas_tmf_task tmf = {}; | ||
| 1383 | 1381 | ||
| 1384 | ata_for_each_link(link, ap, EDGE) { | 1382 | ata_for_each_link(link, ap, EDGE) { |
| 1385 | int pmp = sata_srst_pmp(link); | 1383 | int pmp = sata_srst_pmp(link); |
| 1386 | 1384 | ||
| 1387 | hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis); | 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 | if (rc != TMF_RESP_FUNC_COMPLETE) | 1387 | if (rc != TMF_RESP_FUNC_COMPLETE) |
| 1390 | break; | 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 | hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis); | 1395 | hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis); |
| 1398 | rc = hisi_sas_exec_internal_tmf_task(device, fis, | 1396 | rc = hisi_sas_exec_internal_tmf_task(device, fis, |
| 1399 | s, NULL); | 1397 | s, &tmf); |
| 1400 | if (rc != TMF_RESP_FUNC_COMPLETE) | 1398 | if (rc != TMF_RESP_FUNC_COMPLETE) |
| 1401 | dev_err(dev, "ata disk %016llx de-reset failed\n", | 1399 | dev_err(dev, "ata disk %016llx de-reset failed\n", |
| 1402 | SAS_ADDR(device->sas_addr)); | 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 | slot->port = port; | 2065 | slot->port = port; |
| 2068 | slot->is_internal = true; | 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 | return 0; | 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 | u32 tag = le32_to_cpu(psataPayload->tag); | 2692 | u32 tag = le32_to_cpu(psataPayload->tag); |
| 2693 | u32 port_id = le32_to_cpu(psataPayload->port_id); | 2693 | u32 port_id = le32_to_cpu(psataPayload->port_id); |
| 2694 | u32 dev_id = le32_to_cpu(psataPayload->device_id); | 2694 | u32 dev_id = le32_to_cpu(psataPayload->device_id); |
| 2695 | unsigned long flags; | ||
| 2696 | 2695 | ||
| 2697 | if (event) | 2696 | if (event) |
| 2698 | pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); | 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 | ts->resp = SAS_TASK_COMPLETE; | 2723 | ts->resp = SAS_TASK_COMPLETE; |
| 2725 | ts->stat = SAS_DATA_OVERRUN; | 2724 | ts->stat = SAS_DATA_OVERRUN; |
| 2726 | ts->residual = 0; | 2725 | ts->residual = 0; |
| 2727 | if (pm8001_dev) | ||
| 2728 | atomic_dec(&pm8001_dev->running_req); | ||
| 2729 | break; | 2726 | break; |
| 2730 | case IO_XFER_ERROR_BREAK: | 2727 | case IO_XFER_ERROR_BREAK: |
| 2731 | pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); | 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 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | 2764 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); |
| 2768 | ts->resp = SAS_TASK_COMPLETE; | 2765 | ts->resp = SAS_TASK_COMPLETE; |
| 2769 | ts->stat = SAS_QUEUE_FULL; | 2766 | ts->stat = SAS_QUEUE_FULL; |
| 2770 | pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); | ||
| 2771 | return; | 2767 | return; |
| 2772 | } | 2768 | } |
| 2773 | break; | 2769 | break; |
| @@ -2853,20 +2849,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) · 79 unmodified lines | |||
| 2853 | ts->stat = SAS_OPEN_TO; | 2849 | ts->stat = SAS_OPEN_TO; |
| 2854 | break; | 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 | /*See the comments for mpi_ssp_completion */ | 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 | res = -TMF_RESP_FUNC_FAILED; | 769 | res = -TMF_RESP_FUNC_FAILED; |
| 770 | /* Even TMF timed out, return direct. */ | 770 | /* Even TMF timed out, return direct. */ |
| 771 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | 771 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { |
| 772 | struct pm8001_ccb_info *ccb = task->lldd_task; | ||
| 773 | |||
| 772 | pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n", | 774 | pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n", |
| 773 | tmf->tmf); | 775 | tmf->tmf); |
| 776 | |||
| 777 | if (ccb) | ||
| 778 | ccb->task = NULL; | ||
| 774 | goto ex_err; | 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 | pm8001_dbg(pm8001_ha, FAIL, | 2185 | pm8001_dbg(pm8001_ha, FAIL, |
| 2186 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", | 2186 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", |
| 2187 | t, status, ts->resp, ts->stat); | 2187 | t, status, ts->resp, ts->stat); |
| 2188 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2188 | if (t->slow_task) | 2189 | if (t->slow_task) |
| 2189 | complete(&t->slow_task->completion); | 2190 | complete(&t->slow_task->completion); |
| 2190 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2191 | } else { | 2191 | } else { |
| 2192 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 2192 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
| 2193 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 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 | pm8001_dbg(pm8001_ha, FAIL, | 2794 | pm8001_dbg(pm8001_ha, FAIL, |
| 2795 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", | 2795 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", |
| 2796 | t, status, ts->resp, ts->stat); | 2796 | t, status, ts->resp, ts->stat); |
| 2797 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2797 | if (t->slow_task) | 2798 | if (t->slow_task) |
| 2798 | complete(&t->slow_task->completion); | 2799 | complete(&t->slow_task->completion); |
| 2799 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2800 | } else { | 2800 | } else { |
| 2801 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 2801 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
| 2802 | spin_unlock_irqrestore(&circularQ->oq_lock, | 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 | u32 tag = le32_to_cpu(psataPayload->tag); | 2821 | u32 tag = le32_to_cpu(psataPayload->tag); |
| 2822 | u32 port_id = le32_to_cpu(psataPayload->port_id); | 2822 | u32 port_id = le32_to_cpu(psataPayload->port_id); |
| 2823 | u32 dev_id = le32_to_cpu(psataPayload->device_id); | 2823 | u32 dev_id = le32_to_cpu(psataPayload->device_id); |
| 2824 | unsigned long flags; | ||
| 2825 | 2824 | ||
| 2826 | if (event) | 2825 | if (event) |
| 2827 | pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); | 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 | ts->resp = SAS_TASK_COMPLETE; | 2853 | ts->resp = SAS_TASK_COMPLETE; |
| 2855 | ts->stat = SAS_DATA_OVERRUN; | 2854 | ts->stat = SAS_DATA_OVERRUN; |
| 2856 | ts->residual = 0; | 2855 | ts->residual = 0; |
| 2857 | if (pm8001_dev) | ||
| 2858 | atomic_dec(&pm8001_dev->running_req); | ||
| 2859 | break; | 2856 | break; |
| 2860 | case IO_XFER_ERROR_BREAK: | 2857 | case IO_XFER_ERROR_BREAK: |
| 2861 | pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); | 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 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | 2901 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); |
| 2905 | ts->resp = SAS_TASK_COMPLETE; | 2902 | ts->resp = SAS_TASK_COMPLETE; |
| 2906 | ts->stat = SAS_QUEUE_FULL; | 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 | return; | 2904 | return; |
| 2913 | } | 2905 | } |
| 2914 | break; | 2906 | break; |
| @@ -3008,24 +3000,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, · 93 unmodified lines | |||
| 3008 | ts->stat = SAS_OPEN_TO; | 3000 | ts->stat = SAS_OPEN_TO; |
| 3009 | break; | 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 | /*See the comments for mpi_ssp_completion */ | 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 | * process_one_iomb - process one outbound Queue memory block | 3906 | * process_one_iomb - process one outbound Queue memory block |
| 3933 | * @pm8001_ha: our hba card information | 3907 | * @pm8001_ha: our hba card information |
| 3908 | * @circularQ: outbound circular queue | ||
| 3934 | * @piomb: IO message buffer | 3909 | * @piomb: IO message buffer |
| 3935 | */ | 3910 | */ |
| 3936 | static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, | 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 | SCSI_TIMEOUT, 3, NULL); | 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 | * scsi_alloc_sdev - allocate and setup a scsi_Device | 260 | * scsi_alloc_sdev - allocate and setup a scsi_Device |
| 219 | * @starget: which target to allocate a &scsi_device for | 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 | * default device queue depth to figure out sbitmap shift | 348 | * default device queue depth to figure out sbitmap shift |
| 307 | * since we use this queue depth most of times. | 349 | * since we use this queue depth most of times. |
| 308 | */ | 350 | */ |
| 309 | if (sbitmap_init_node(&sdev->budget_map, | 351 | if (scsi_realloc_sdev_budget_map(sdev, depth)) { |
| 310 | scsi_device_max_queue_depth(sdev), | ||
| 311 | sbitmap_calculate_shift(depth), | ||
| 312 | GFP_KERNEL, sdev->request_queue->node, | ||
| 313 | false, true)) { | ||
| 314 | put_device(&starget->dev); | 352 | put_device(&starget->dev); |
| 315 | kfree(sdev); | 353 | kfree(sdev); |
| 316 | goto out; | 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 | return SCSI_SCAN_NO_RESPONSE; | 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 | if (sdev->scsi_level >= SCSI_3) | 1067 | if (sdev->scsi_level >= SCSI_3) |
| @@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE · 77 unmodified lines | |||
| 78 | help | 78 | help |
| 79 | Low-level framebuffer-based console driver. | 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 | config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY | 101 | config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY |
| 82 | bool "Map the console to the primary display device" | 102 | bool "Map the console to the primary display device" |
| 83 | depends on FRAMEBUFFER_CONSOLE | 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 | static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, | 61 | static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 47 | int sx, int height, int width) | 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 | void fbcon_set_bitops(struct fbcon_ops *ops) | 394 | void fbcon_set_bitops(struct fbcon_ops *ops) |
| 380 | { | 395 | { |
| 396 | ops->bmove = bit_bmove; | ||
| 381 | ops->clear = bit_clear; | 397 | ops->clear = bit_clear; |
| 382 | ops->putcs = bit_putcs; | 398 | ops->putcs = bit_putcs; |
| 383 | ops->clear_margins = bit_clear_margins; | 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 | int count, int ypos, int xpos); | 173 | int count, int ypos, int xpos); |
| 174 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); | 174 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); |
| 175 | static void fbcon_cursor(struct vc_data *vc, int mode); | 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 | static int fbcon_switch(struct vc_data *vc); | 178 | static int fbcon_switch(struct vc_data *vc); |
| 177 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); | 179 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); |
| 178 | static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); | 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 | * Internal routines | 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 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | 191 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
| 184 | int unit); | 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 | static void fbcon_modechanged(struct fb_info *info); | 195 | static void fbcon_modechanged(struct fb_info *info); |
| 186 | static void fbcon_set_all_vcs(struct fb_info *info); | 196 | static void fbcon_set_all_vcs(struct fb_info *info); |
| 187 | static void fbcon_start(void); | 197 | static void fbcon_start(void); |
| @@ -1015,7 +1025,7 @@ static void fbcon_init(struct vc_data *vc, int init) · 827 unmodified lines | |||
| 1015 | struct vc_data *svc = *default_mode; | 1025 | struct vc_data *svc = *default_mode; |
| 1016 | struct fbcon_display *t, *p = &fb_display[vc->vc_num]; | 1026 | struct fbcon_display *t, *p = &fb_display[vc->vc_num]; |
| 1017 | int logo = 1, new_rows, new_cols, rows, cols; | 1027 | int logo = 1, new_rows, new_cols, rows, cols; |
| 1018 | int ret; | 1028 | int cap, ret; |
| 1019 | 1029 | ||
| 1020 | if (WARN_ON(info_idx == -1)) | 1030 | if (WARN_ON(info_idx == -1)) |
| 1021 | return; | 1031 | return; |
| @@ -1024,6 +1034,7 @@ static void fbcon_init(struct vc_data *vc, int init) · 2 unmodified lines | |||
| 1024 | con2fb_map[vc->vc_num] = info_idx; | 1034 | con2fb_map[vc->vc_num] = info_idx; |
| 1025 | 1035 | ||
| 1026 | info = registered_fb[con2fb_map[vc->vc_num]]; | 1036 | info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1037 | cap = info->flags; | ||
| 1027 | 1038 | ||
| 1028 | if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) | 1039 | if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) |
| 1029 | logo_shown = FBCON_LOGO_DONTSHOW; | 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 | ops->graphics = 0; | 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 | * ++guenther: console.c:vc_allocate() relies on initializing | 1148 | * ++guenther: console.c:vc_allocate() relies on initializing |
| 1130 | * vc_{cols,rows}, but we must not set those if we are only | 1149 | * vc_{cols,rows}, but we must not set those if we are only |
| @@ -1211,13 +1230,14 @@ finished: · 80 unmodified lines | |||
| 1211 | * This system is now divided into two levels because of complications | 1230 | * This system is now divided into two levels because of complications |
| 1212 | * caused by hardware scrolling. Top level functions: | 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 | * handles y values in range [0, scr_height-1] that correspond to real | 1235 | * handles y values in range [0, scr_height-1] that correspond to real |
| 1217 | * screen positions. y_wrap shift means that first line of bitmap may be | 1236 | * screen positions. y_wrap shift means that first line of bitmap may be |
| 1218 | * anywhere on this display. These functions convert lineoffsets to | 1237 | * anywhere on this display. These functions convert lineoffsets to |
| 1219 | * bitmap offsets and deal with the wrap-around case by splitting blits. | 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 | * fbcon_clear_physical_8() -- of original fbcon_XXX fns. | 1241 | * fbcon_clear_physical_8() -- of original fbcon_XXX fns. |
| 1222 | * fbcon_putc_physical_8() -- (font width != 8) may be added later | 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 | static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, | 1631 | static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, |
| 1394 | int line, int count, int offset) | 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 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1689 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1452 | struct fbcon_display *p = &fb_display[vc->vc_num]; | 1690 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1691 | int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; | ||
| 1453 | 1692 | ||
| 1454 | if (fbcon_is_inactive(vc, info)) | 1693 | if (fbcon_is_inactive(vc, info)) |
| 1455 | return true; | 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 | case SM_UP: | 1705 | case SM_UP: |
| 1467 | if (count > vc->vc_rows) /* Maximum realistic size */ | 1706 | if (count > vc->vc_rows) /* Maximum realistic size */ |
| 1468 | count = vc->vc_rows; | 1707 | count = vc->vc_rows; |
| 1469 | fbcon_redraw(vc, p, t, b - t - count, | 1708 | if (logo_shown >= 0) |
| 1470 | count * vc->vc_cols); | 1709 | goto redraw_up; |
| 1471 | fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | 1710 | switch (fb_scrollmode(p)) { |
| 1472 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1711 | case SCROLL_MOVE: |
| 1473 | vc->vc_size_row * | 1712 | fbcon_redraw_blit(vc, info, p, t, b - t - count, |
| 1474 | (b - count)), | 1713 | count); |
| 1475 | vc->vc_video_erase_char, | 1714 | fbcon_clear(vc, b - count, 0, count, vc->vc_cols); |
| 1476 | vc->vc_size_row * count); | 1715 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1477 | return true; | 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 | case SM_DOWN: | 1795 | case SM_DOWN: |
| 1480 | if (count > vc->vc_rows) /* Maximum realistic size */ | 1796 | if (count > vc->vc_rows) /* Maximum realistic size */ |
| 1481 | count = vc->vc_rows; | 1797 | count = vc->vc_rows; |
| 1482 | fbcon_redraw(vc, p, b - 1, b - t - count, | 1798 | if (logo_shown >= 0) |
| 1483 | -count * vc->vc_cols); | 1799 | goto redraw_down; |
| 1484 | fbcon_clear(vc, t, 0, count, vc->vc_cols); | 1800 | switch (fb_scrollmode(p)) { |
| 1485 | scr_memsetw((unsigned short *) (vc->vc_origin + | 1801 | case SCROLL_MOVE: |
| 1486 | vc->vc_size_row * | 1802 | fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, |
| 1487 | t), | 1803 | -count); |
| 1488 | vc->vc_video_erase_char, | 1804 | fbcon_clear(vc, t, 0, count, vc->vc_cols); |
| 1489 | vc->vc_size_row * count); | 1805 | scr_memsetw((unsigned short *) (vc->vc_origin + |
| 1490 | return true; | 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 | return false; | 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 | static void updatescrollmode(struct fbcon_display *p, | 1993 | static void updatescrollmode(struct fbcon_display *p, |
| 1496 | struct fb_info *info, | 1994 | struct fb_info *info, |
| 1497 | struct vc_data *vc) | 1995 | struct vc_data *vc) |
| @@ -1507,6 +2005,9 @@ static void updatescrollmode(struct fbcon_display *p, · 9 unmodified lines | |||
| 1507 | p->vrows -= (yres - (fh * vc->vc_rows)) / fh; | 2005 | p->vrows -= (yres - (fh * vc->vc_rows)) / fh; |
| 1508 | if ((yres % fh) && (vyres % fh < yres % fh)) | 2006 | if ((yres % fh) && (vyres % fh < yres % fh)) |
| 1509 | p->vrows--; | 2007 | p->vrows--; |
| 2008 | |||
| 2009 | /* update scrollmode in case hardware acceleration is used */ | ||
| 2010 | updatescrollmode_accel(p, info, vc); | ||
| 1510 | } | 2011 | } |
| 1511 | 2012 | ||
| 1512 | #define PITCH(w) (((w) + 7) >> 3) | 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 | updatescrollmode(p, info, vc); | 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 | scrollback_max = 0; | 2183 | scrollback_max = 0; |
| 1669 | scrollback_current = 0; | 2184 | scrollback_current = 0; |
| 1670 | 2185 | ||
| @@ -29,6 +29,9 @@ struct fbcon_display { · 28 unmodified lines | |||
| 29 | /* Filled in by the low-level console driver */ | 29 | /* Filled in by the low-level console driver */ |
| 30 | const u_char *fontdata; | 30 | const u_char *fontdata; |
| 31 | int userfont; /* != 0 if fontdata kmalloc()ed */ | 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 | u_short inverse; /* != 0 text black on white as default */ | 35 | u_short inverse; /* != 0 text black on white as default */ |
| 33 | short yscroll; /* Hardware scrolling */ | 36 | short yscroll; /* Hardware scrolling */ |
| 34 | int vrows; /* number of virtual rows */ | 37 | int vrows; /* number of virtual rows */ |
| @@ -51,6 +54,8 @@ struct fbcon_display { · 16 unmodified lines | |||
| 51 | }; | 54 | }; |
| 52 | 55 | ||
| 53 | struct fbcon_ops { | 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 | void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, | 59 | void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, |
| 55 | int sx, int height, int width); | 60 | int sx, int height, int width); |
| 56 | void (*putcs)(struct vc_data *vc, struct fb_info *info, | 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 | #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) | 154 | #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) |
| 150 | #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) | 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 | #ifdef CONFIG_FB_TILEBLITTING | 224 | #ifdef CONFIG_FB_TILEBLITTING |
| 153 | extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); | 225 | extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); |
| 154 | #endif | 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 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 63 | int sx, int height, int width) | 81 | int sx, int height, int width) |
| 64 | { | 82 | { |
| 83 | struct fbcon_ops *ops = info->fbcon_par; | ||
| 65 | struct fb_fillrect region; | 84 | struct fb_fillrect region; |
| 66 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 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 | region.color = attr_bgcol_ec(bgshift,vc,info); | 88 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 70 | region.dx = sy * vc->vc_font.height; | 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 | u32 cnt, pitch, size; | 140 | u32 cnt, pitch, size; |
| 122 | u32 attribute = get_attribute(info, scr_readw(s)); | 141 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 123 | u8 *dst, *buf = NULL; | 142 | u8 *dst, *buf = NULL; |
| 124 | u32 vyres = info->var.yres; | 143 | u32 vyres = GETVYRES(ops->p, info); |
| 125 | 144 | ||
| 126 | if (!ops->fontbuffer) | 145 | if (!ops->fontbuffer) |
| 127 | return; | 146 | return; |
| @@ -210,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 82 unmodified lines | |||
| 210 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; | 229 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 211 | int err = 1, dx, dy; | 230 | int err = 1, dx, dy; |
| 212 | char *src; | 231 | char *src; |
| 213 | u32 vyres = info->var.yres; | 232 | u32 vyres = GETVYRES(ops->p, info); |
| 214 | 233 | ||
| 215 | if (!ops->fontbuffer) | 234 | if (!ops->fontbuffer) |
| 216 | return; | 235 | return; |
| @@ -368,7 +387,7 @@ static int ccw_update_start(struct fb_info *info) · 151 unmodified lines | |||
| 368 | { | 387 | { |
| 369 | struct fbcon_ops *ops = info->fbcon_par; | 388 | struct fbcon_ops *ops = info->fbcon_par; |
| 370 | u32 yoffset; | 389 | u32 yoffset; |
| 371 | u32 vyres = info->var.yres; | 390 | u32 vyres = GETVYRES(ops->p, info); |
| 372 | int err; | 391 | int err; |
| 373 | 392 | ||
| 374 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; | 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 | void fbcon_rotate_ccw(struct fbcon_ops *ops) | 403 | void fbcon_rotate_ccw(struct fbcon_ops *ops) |
| 385 | { | 404 | { |
| 405 | ops->bmove = ccw_bmove; | ||
| 386 | ops->clear = ccw_clear; | 406 | ops->clear = ccw_clear; |
| 387 | ops->putcs = ccw_putcs; | 407 | ops->putcs = ccw_putcs; |
| 388 | ops->clear_margins = ccw_clear_margins; | 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 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 65 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 48 | int sx, int height, int width) | 66 | int sx, int height, int width) |
| 49 | { | 67 | { |
| 68 | struct fbcon_ops *ops = info->fbcon_par; | ||
| 50 | struct fb_fillrect region; | 69 | struct fb_fillrect region; |
| 51 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 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 | region.color = attr_bgcol_ec(bgshift,vc,info); | 73 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 55 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 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 | u32 cnt, pitch, size; | 125 | u32 cnt, pitch, size; |
| 107 | u32 attribute = get_attribute(info, scr_readw(s)); | 126 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 108 | u8 *dst, *buf = NULL; | 127 | u8 *dst, *buf = NULL; |
| 109 | u32 vxres = info->var.xres; | 128 | u32 vxres = GETVXRES(ops->p, info); |
| 110 | 129 | ||
| 111 | if (!ops->fontbuffer) | 130 | if (!ops->fontbuffer) |
| 112 | return; | 131 | return; |
| @@ -193,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 80 unmodified lines | |||
| 193 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; | 212 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 194 | int err = 1, dx, dy; | 213 | int err = 1, dx, dy; |
| 195 | char *src; | 214 | char *src; |
| 196 | u32 vxres = info->var.xres; | 215 | u32 vxres = GETVXRES(ops->p, info); |
| 197 | 216 | ||
| 198 | if (!ops->fontbuffer) | 217 | if (!ops->fontbuffer) |
| 199 | return; | 218 | return; |
| @@ -350,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 150 unmodified lines | |||
| 350 | static int cw_update_start(struct fb_info *info) | 369 | static int cw_update_start(struct fb_info *info) |
| 351 | { | 370 | { |
| 352 | struct fbcon_ops *ops = info->fbcon_par; | 371 | struct fbcon_ops *ops = info->fbcon_par; |
| 353 | u32 vxres = info->var.xres; | 372 | u32 vxres = GETVXRES(ops->p, info); |
| 354 | u32 xoffset; | 373 | u32 xoffset; |
| 355 | int err; | 374 | int err; |
| 356 | 375 | ||
| @@ -366,6 +385,7 @@ static int cw_update_start(struct fb_info *info) · 9 unmodified lines | |||
| 366 | 385 | ||
| 367 | void fbcon_rotate_cw(struct fbcon_ops *ops) | 386 | void fbcon_rotate_cw(struct fbcon_ops *ops) |
| 368 | { | 387 | { |
| 388 | ops->bmove = cw_bmove; | ||
| 369 | ops->clear = cw_clear; | 389 | ops->clear = cw_clear; |
| 370 | ops->putcs = cw_putcs; | 390 | ops->putcs = cw_putcs; |
| 371 | ops->clear_margins = cw_clear_margins; | 391 | ops->clear_margins = cw_clear_margins; |
| @@ -11,6 +11,15 @@ · 10 unmodified lines | |||
| 11 | #ifndef _FBCON_ROTATE_H | 11 | #ifndef _FBCON_ROTATE_H |
| 12 | #define _FBCON_ROTATE_H | 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 | static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) | 23 | static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) |
| 15 | { | 24 | { |
| 16 | u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; | 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 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 48 | int sx, int height, int width) | 67 | int sx, int height, int width) |
| 49 | { | 68 | { |
| 69 | struct fbcon_ops *ops = info->fbcon_par; | ||
| 50 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
| 51 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
| 52 | u32 vyres = info->var.yres; | 72 | u32 vyres = GETVYRES(ops->p, info); |
| 53 | u32 vxres = info->var.xres; | 73 | u32 vxres = GETVXRES(ops->p, info); |
| 54 | 74 | ||
| 55 | region.color = attr_bgcol_ec(bgshift,vc,info); | 75 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 56 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 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 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; | 162 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
| 143 | u32 attribute = get_attribute(info, scr_readw(s)); | 163 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 144 | u8 *dst, *buf = NULL; | 164 | u8 *dst, *buf = NULL; |
| 145 | u32 vyres = info->var.yres; | 165 | u32 vyres = GETVYRES(ops->p, info); |
| 146 | u32 vxres = info->var.xres; | 166 | u32 vxres = GETVXRES(ops->p, info); |
| 147 | 167 | ||
| 148 | if (!ops->fontbuffer) | 168 | if (!ops->fontbuffer) |
| 149 | return; | 169 | return; |
| @@ -239,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 89 unmodified lines | |||
| 239 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; | 259 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 240 | int err = 1, dx, dy; | 260 | int err = 1, dx, dy; |
| 241 | char *src; | 261 | char *src; |
| 242 | u32 vyres = info->var.yres; | 262 | u32 vyres = GETVYRES(ops->p, info); |
| 243 | u32 vxres = info->var.xres; | 263 | u32 vxres = GETVXRES(ops->p, info); |
| 244 | 264 | ||
| 245 | if (!ops->fontbuffer) | 265 | if (!ops->fontbuffer) |
| 246 | return; | 266 | return; |
| @@ -390,8 +410,8 @@ static int ud_update_start(struct fb_info *info) · 143 unmodified lines | |||
| 390 | { | 410 | { |
| 391 | struct fbcon_ops *ops = info->fbcon_par; | 411 | struct fbcon_ops *ops = info->fbcon_par; |
| 392 | int xoffset, yoffset; | 412 | int xoffset, yoffset; |
| 393 | u32 vyres = info->var.yres; | 413 | u32 vyres = GETVYRES(ops->p, info); |
| 394 | u32 vxres = info->var.xres; | 414 | u32 vxres = GETVXRES(ops->p, info); |
| 395 | int err; | 415 | int err; |
| 396 | 416 | ||
| 397 | xoffset = vxres - info->var.xres - ops->var.xoffset; | 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 | void fbcon_rotate_ud(struct fbcon_ops *ops) | 430 | void fbcon_rotate_ud(struct fbcon_ops *ops) |
| 411 | { | 431 | { |
| 432 | ops->bmove = ud_bmove; | ||
| 412 | ops->clear = ud_clear; | 433 | ops->clear = ud_clear; |
| 413 | ops->putcs = ud_putcs; | 434 | ops->putcs = ud_putcs; |
| 414 | ops->clear_margins = ud_clear_margins; | 435 | ops->clear_margins = ud_clear_margins; |
| @@ -16,6 +16,21 @@ · 15 unmodified lines | |||
| 16 | #include <asm/types.h> | 16 | #include <asm/types.h> |
| 17 | #include "fbcon.h" | 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 | static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, | 34 | static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 20 | int sx, int height, int width) | 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 | struct fb_tilemap map; | 133 | struct fb_tilemap map; |
| 119 | struct fbcon_ops *ops = info->fbcon_par; | 134 | struct fbcon_ops *ops = info->fbcon_par; |
| 120 | 135 | ||
| 136 | ops->bmove = tile_bmove; | ||
| 121 | ops->clear = tile_clear; | 137 | ops->clear = tile_clear; |
| 122 | ops->putcs = tile_putcs; | 138 | ops->putcs = tile_putcs; |
| 123 | ops->clear_margins = tile_clear_margins; | 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 | * Copies one area of the screen to another area. | 510 | * Copies one area of the screen to another area. |
| 510 | * Will be deleted in a future version | ||
| 511 | * | 511 | * |
| 512 | * @info: frame buffer structure that represents a single frame buffer | 512 | * @info: frame buffer structure that represents a single frame buffer |
| 513 | * @area: Structure providing the data to copy the framebuffer contents | 513 | * @area: Structure providing the data to copy the framebuffer contents |
| 514 | * from one region to another. | 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 | * screen to another area. | 517 | * screen to another area. |
| 518 | */ | 518 | */ |
| 519 | void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) | 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 | .fb_setcolreg = xxxfb_setcolreg, | 645 | .fb_setcolreg = xxxfb_setcolreg, |
| 646 | .fb_blank = xxxfb_blank, | 646 | .fb_blank = xxxfb_blank, |
| 647 | .fb_pan_display = xxxfb_pan_display, | 647 | .fb_pan_display = xxxfb_pan_display, |
| 648 | .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ | 648 | .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ |
| 649 | .fb_copyarea = xxxfb_copyarea, /* Obsolete */ | 649 | .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ |
| 650 | .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ | 650 | .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ |
| 651 | .fb_cursor = xxxfb_cursor, /* Optional !!! */ | 651 | .fb_cursor = xxxfb_cursor, /* Optional !!! */ |
| 652 | .fb_sync = xxxfb_sync, | 652 | .fb_sync = xxxfb_sync, |
| 653 | .fb_ioctl = xxxfb_ioctl, | 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 | dentry, dentry, from_kuid(&init_user_ns, uid), | 96 | dentry, dentry, from_kuid(&init_user_ns, uid), |
| 97 | any); | 97 | any); |
| 98 | ret = NULL; | 98 | ret = NULL; |
| 99 | |||
| 100 | if (d_inode(dentry)) | ||
| 101 | ret = v9fs_fid_find_inode(d_inode(dentry), uid); | ||
| 102 | |||
| 103 | /* we'll recheck under lock if there's anything to look in */ | 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 | struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; | 101 | struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; |
| 106 | 102 | ||
| 107 | spin_lock(&dentry->d_lock); | 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 | spin_unlock(&dentry->d_lock); | 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 | return ret; | 117 | return ret; |
| @@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig" · 368 unmodified lines | |||
| 369 | 369 | ||
| 370 | config SMBFS_COMMON | 370 | config SMBFS_COMMON |
| 371 | tristate | 371 | tristate |
| 372 | default y if CIFS=y | 372 | default y if CIFS=y || SMB_SERVER=y |
| 373 | default m if CIFS=m | 373 | default m if CIFS=m || SMB_SERVER=m |
| 374 | 374 | ||
| 375 | source "fs/coda/Kconfig" | 375 | source "fs/coda/Kconfig" |
| 376 | source "fs/afs/Kconfig" | 376 | source "fs/afs/Kconfig" |
| @@ -817,20 +817,16 @@ static struct file_system_type bm_fs_type = { · 816 unmodified lines | |||
| 817 | }; | 817 | }; |
| 818 | MODULE_ALIAS_FS("binfmt_misc"); | 818 | MODULE_ALIAS_FS("binfmt_misc"); |
| 819 | 819 | ||
| 820 | static struct ctl_table_header *binfmt_misc_header; | ||
| 821 | |||
| 822 | static int __init init_misc_binfmt(void) | 820 | static int __init init_misc_binfmt(void) |
| 823 | { | 821 | { |
| 824 | int err = register_filesystem(&bm_fs_type); | 822 | int err = register_filesystem(&bm_fs_type); |
| 825 | if (!err) | 823 | if (!err) |
| 826 | insert_binfmt(&misc_format); | 824 | insert_binfmt(&misc_format); |
| 827 | binfmt_misc_header = register_sysctl_mount_point("fs/binfmt_misc"); | 825 | return err; |
| 828 | return 0; | ||
| 829 | } | 826 | } |
| 830 | 827 | ||
| 831 | static void __exit exit_misc_binfmt(void) | 828 | static void __exit exit_misc_binfmt(void) |
| 832 | { | 829 | { |
| 833 | unregister_sysctl_table(binfmt_misc_header); | ||
| 834 | unregister_binfmt(&misc_format); | 830 | unregister_binfmt(&misc_format); |
| 835 | unregister_filesystem(&bm_fs_type); | 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 | if (refcount_dec_and_test(&cache->refs)) { | 125 | if (refcount_dec_and_test(&cache->refs)) { |
| 126 | WARN_ON(cache->pinned > 0); | 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 | * A block_group shouldn't be on the discard_list anymore. | 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 | int ret; | 2553 | int ret; |
| 2545 | bool dirty_bg_running; | 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 | do { | 2569 | do { |
| 2548 | trans = btrfs_join_transaction(root); | 2570 | trans = btrfs_join_transaction(root); |
| 2549 | if (IS_ERR(trans)) | 2571 | if (IS_ERR(trans)) |
| @@ -3974,9 +3996,22 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) · 1424 unmodified lines | |||
| 3974 | * important and indicates a real bug if this happens. | 3996 | * important and indicates a real bug if this happens. |
| 3975 | */ | 3997 | */ |
| 3976 | if (WARN_ON(space_info->bytes_pinned > 0 || | 3998 | if (WARN_ON(space_info->bytes_pinned > 0 || |
| 3977 | space_info->bytes_reserved > 0 || | ||
| 3978 | space_info->bytes_may_use > 0)) | 3999 | space_info->bytes_may_use > 0)) |
| 3979 | btrfs_dump_space_info(info, space_info, 0, 0); | 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 | WARN_ON(space_info->reclaim_size > 0); | 4015 | WARN_ON(space_info->reclaim_size > 0); |
| 3981 | list_del(&space_info->list); | 4016 | list_del(&space_info->list); |
| 3982 | btrfs_sysfs_remove_space_info(space_info); | 4017 | btrfs_sysfs_remove_space_info(space_info); |
| @@ -145,6 +145,9 @@ enum { · 144 unmodified lines | |||
| 145 | BTRFS_FS_STATE_DUMMY_FS_INFO, | 145 | BTRFS_FS_STATE_DUMMY_FS_INFO, |
| 146 | 146 | ||
| 147 | BTRFS_FS_STATE_NO_CSUMS, | 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 | #define BTRFS_BACKREF_REV_MAX 256 | 153 | #define BTRFS_BACKREF_REV_MAX 256 |
| @@ -3593,6 +3596,9 @@ do { \ · 3442 unmodified lines | |||
| 3593 | 3596 | ||
| 3594 | #define BTRFS_FS_ERROR(fs_info) (unlikely(test_bit(BTRFS_FS_STATE_ERROR, \ | 3597 | #define BTRFS_FS_ERROR(fs_info) (unlikely(test_bit(BTRFS_FS_STATE_ERROR, \ |
| 3595 | &(fs_info)->fs_state))) | 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 | __printf(5, 6) | 3603 | __printf(5, 6) |
| 3598 | __cold | 3604 | __cold |
| @@ -805,10 +805,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, · 804 unmodified lines | |||
| 805 | goto fail; | 805 | goto fail; |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | spin_lock(&fs_info->trans_lock); | 808 | trans->pending_snapshot = pending_snapshot; |
| 809 | list_add(&pending_snapshot->list, | ||
| 810 | &trans->transaction->pending_snapshots); | ||
| 811 | spin_unlock(&fs_info->trans_lock); | ||
| 812 | 809 | ||
| 813 | ret = btrfs_commit_transaction(trans); | 810 | ret = btrfs_commit_transaction(trans); |
| 814 | if (ret) | 811 | if (ret) |
| @@ -3354,7 +3351,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) · 2539 unmodified lines | |||
| 3354 | struct block_device *bdev = NULL; | 3351 | struct block_device *bdev = NULL; |
| 3355 | fmode_t mode; | 3352 | fmode_t mode; |
| 3356 | int ret; | 3353 | int ret; |
| 3357 | bool cancel; | 3354 | bool cancel = false; |
| 3358 | 3355 | ||
| 3359 | if (!capable(CAP_SYS_ADMIN)) | 3356 | if (!capable(CAP_SYS_ADMIN)) |
| 3360 | return -EPERM; | 3357 | return -EPERM; |
| @@ -1185,9 +1185,24 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 1184 unmodified lines | |||
| 1185 | struct btrfs_trans_handle *trans = NULL; | 1185 | struct btrfs_trans_handle *trans = NULL; |
| 1186 | int ret = 0; | 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 | mutex_lock(&fs_info->qgroup_ioctl_lock); | 1195 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
| 1189 | if (!fs_info->quota_root) | 1196 | if (!fs_info->quota_root) |
| 1190 | goto out; | 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 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | 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 | if (IS_ERR(trans)) { | 1220 | if (IS_ERR(trans)) { |
| 1206 | ret = PTR_ERR(trans); | 1221 | ret = PTR_ERR(trans); |
| 1207 | trans = NULL; | 1222 | trans = NULL; |
| 1223 | set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); | ||
| 1208 | goto out; | 1224 | goto out; |
| 1209 | } | 1225 | } |
| 1210 | 1226 | ||
| 1211 | if (!fs_info->quota_root) | 1227 | if (!fs_info->quota_root) |
| 1212 | goto out; | 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 | spin_lock(&fs_info->qgroup_lock); | 1230 | spin_lock(&fs_info->qgroup_lock); |
| 1217 | quota_root = fs_info->quota_root; | 1231 | quota_root = fs_info->quota_root; |
| 1218 | fs_info->quota_root = NULL; | 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 | btrfs_warn(fs_info, | 3397 | btrfs_warn(fs_info, |
| 3384 | "qgroup rescan init failed, qgroup is not enabled"); | 3398 | "qgroup rescan init failed, qgroup is not enabled"); |
| 3385 | ret = -EINVAL; | 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 | if (ret) { | 3405 | if (ret) { |
| @@ -2000,6 +2000,27 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info) · 1999 unmodified lines | |||
| 2000 | btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); | 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 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans) | 2024 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans) |
| 2004 | { | 2025 | { |
| 2005 | struct btrfs_fs_info *fs_info = trans->fs_info; | 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 | if (cur_trans->state >= TRANS_STATE_COMMIT_START) { | 2094 | if (cur_trans->state >= TRANS_STATE_COMMIT_START) { |
| 2074 | enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED; | 2095 | enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED; |
| 2075 | 2096 | ||
| 2097 | add_pending_snapshot(trans); | ||
| 2098 | |||
| 2076 | spin_unlock(&fs_info->trans_lock); | 2099 | spin_unlock(&fs_info->trans_lock); |
| 2077 | refcount_inc(&cur_trans->use_count); | 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 | * COMMIT_DOING so make sure to wait for num_writers to == 1 again. | 2186 | * COMMIT_DOING so make sure to wait for num_writers to == 1 again. |
| 2164 | */ | 2187 | */ |
| 2165 | spin_lock(&fs_info->trans_lock); | 2188 | spin_lock(&fs_info->trans_lock); |
| 2189 | add_pending_snapshot(trans); | ||
| 2166 | cur_trans->state = TRANS_STATE_COMMIT_DOING; | 2190 | cur_trans->state = TRANS_STATE_COMMIT_DOING; |
| 2167 | spin_unlock(&fs_info->trans_lock); | 2191 | spin_unlock(&fs_info->trans_lock); |
| 2168 | wait_event(cur_trans->writer_wait, | 2192 | wait_event(cur_trans->writer_wait, |
| @@ -123,6 +123,8 @@ struct btrfs_trans_handle { · 122 unmodified lines | |||
| 123 | struct btrfs_transaction *transaction; | 123 | struct btrfs_transaction *transaction; |
| 124 | struct btrfs_block_rsv *block_rsv; | 124 | struct btrfs_block_rsv *block_rsv; |
| 125 | struct btrfs_block_rsv *orig_rsv; | 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 | refcount_t use_count; | 128 | refcount_t use_count; |
| 127 | unsigned int type; | 129 | unsigned int type; |
| 128 | /* | 130 | /* |
| @@ -965,6 +965,7 @@ static int check_dev_item(struct extent_buffer *leaf, · 964 unmodified lines | |||
| 965 | struct btrfs_key *key, int slot) | 965 | struct btrfs_key *key, int slot) |
| 966 | { | 966 | { |
| 967 | struct btrfs_dev_item *ditem; | 967 | struct btrfs_dev_item *ditem; |
| 968 | const u32 item_size = btrfs_item_size(leaf, slot); | ||
| 968 | 969 | ||
| 969 | if (unlikely(key->objectid != BTRFS_DEV_ITEMS_OBJECTID)) { | 970 | if (unlikely(key->objectid != BTRFS_DEV_ITEMS_OBJECTID)) { |
| 970 | dev_item_err(leaf, slot, | 971 | dev_item_err(leaf, slot, |
| @@ -972,6 +973,13 @@ static int check_dev_item(struct extent_buffer *leaf, · 1 unmodified line | |||
| 972 | key->objectid, BTRFS_DEV_ITEMS_OBJECTID); | 973 | key->objectid, BTRFS_DEV_ITEMS_OBJECTID); |
| 973 | return -EUCLEAN; | 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 | ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); | 983 | ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); |
| 976 | if (unlikely(btrfs_device_id(leaf, ditem) != key->offset)) { | 984 | if (unlikely(btrfs_device_id(leaf, ditem) != key->offset)) { |
| 977 | dev_item_err(leaf, slot, | 985 | dev_item_err(leaf, slot, |
| @@ -1007,6 +1015,7 @@ static int check_inode_item(struct extent_buffer *leaf, · 29 unmodified lines | |||
| 1007 | struct btrfs_inode_item *iitem; | 1015 | struct btrfs_inode_item *iitem; |
| 1008 | u64 super_gen = btrfs_super_generation(fs_info->super_copy); | 1016 | u64 super_gen = btrfs_super_generation(fs_info->super_copy); |
| 1009 | u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); | 1017 | u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); |
| 1018 | const u32 item_size = btrfs_item_size(leaf, slot); | ||
| 1010 | u32 mode; | 1019 | u32 mode; |
| 1011 | int ret; | 1020 | int ret; |
| 1012 | u32 flags; | 1021 | u32 flags; |
| @@ -1016,6 +1025,12 @@ static int check_inode_item(struct extent_buffer *leaf, · 3 unmodified lines | |||
| 1016 | if (unlikely(ret < 0)) | 1025 | if (unlikely(ret < 0)) |
| 1017 | return ret; | 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 | iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); | 1034 | iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); |
| 1020 | 1035 | ||
| 1021 | /* Here we use super block generation + 1 to handle log tree */ | 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 | if (log->node) { | 3414 | if (log->node) { |
| 3415 | ret = walk_log_tree(trans, log, &wc); | 3415 | ret = walk_log_tree(trans, log, &wc); |
| 3416 | if (ret) { | 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 | if (trans) | 3440 | if (trans) |
| 3418 | btrfs_abort_transaction(trans, ret); | 3441 | btrfs_abort_transaction(trans, ret); |
| 3419 | else | 3442 | else |
| @@ -191,6 +191,64 @@ presubmission_error: · 190 unmodified lines | |||
| 191 | return ret; | 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 | * Handle completion of a write to the cache. | 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 | .write = cachefiles_write, | 603 | .write = cachefiles_write, |
| 546 | .prepare_read = cachefiles_prepare_read, | 604 | .prepare_read = cachefiles_prepare_read, |
| 547 | .prepare_write = cachefiles_prepare_write, | 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 | mutex_unlock(&server->srv_mutex); | 162 | mutex_unlock(&server->srv_mutex); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | /** | 165 | /* |
| 166 | * Mark all sessions and tcons for reconnect. | 166 | * Mark all sessions and tcons for reconnect. |
| 167 | * | 167 | * |
| 168 | * @server needs to be previously set to CifsNeedReconnect. | 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 | int i; | 1831 | int i; |
| 1832 | 1832 | ||
| 1833 | for (i = 1; i < chan_count; i++) { | 1833 | for (i = 1; i < chan_count; i++) { |
| 1834 | /* | 1834 | spin_unlock(&ses->chan_lock); |
| 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 | */ | ||
| 1840 | cifs_put_tcp_session(ses->chans[i].server, 0); | 1835 | cifs_put_tcp_session(ses->chans[i].server, 0); |
| 1836 | spin_lock(&ses->chan_lock); | ||
| 1841 | ses->chans[i].server = NULL; | 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 | out_key_put: | 1993 | out_key_put: |
| 1985 | up_read(&key->sem); | 1994 | up_read(&key->sem); |
| 1986 | key_put(key); | 1995 | key_put(key); |
| @@ -4269,8 +4269,6 @@ cifs_readv_complete(struct work_struct *work) · 4268 unmodified lines | |||
| 4269 | for (i = 0; i < rdata->nr_pages; i++) { | 4269 | for (i = 0; i < rdata->nr_pages; i++) { |
| 4270 | struct page *page = rdata->pages[i]; | 4270 | struct page *page = rdata->pages[i]; |
| 4271 | 4271 | ||
| 4272 | lru_cache_add(page); | ||
| 4273 | |||
| 4274 | if (rdata->result == 0 || | 4272 | if (rdata->result == 0 || |
| 4275 | (rdata->result == -EAGAIN && got_bytes)) { | 4273 | (rdata->result == -EAGAIN && got_bytes)) { |
| 4276 | flush_dcache_page(page); | 4274 | flush_dcache_page(page); |
| @@ -4278,12 +4276,12 @@ cifs_readv_complete(struct work_struct *work) · 1 unmodified line | |||
| 4278 | } else | 4276 | } else |
| 4279 | SetPageError(page); | 4277 | SetPageError(page); |
| 4280 | 4278 | ||
| 4281 | unlock_page(page); | ||
| 4282 | |||
| 4283 | if (rdata->result == 0 || | 4279 | if (rdata->result == 0 || |
| 4284 | (rdata->result == -EAGAIN && got_bytes)) | 4280 | (rdata->result == -EAGAIN && got_bytes)) |
| 4285 | cifs_readpage_to_fscache(rdata->mapping->host, page); | 4281 | cifs_readpage_to_fscache(rdata->mapping->host, page); |
| 4286 | 4282 | ||
| 4283 | unlock_page(page); | ||
| 4284 | |||
| 4287 | got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes); | 4285 | got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes); |
| 4288 | 4286 | ||
| 4289 | put_page(page); | 4287 | put_page(page); |
| @@ -4340,7 +4338,6 @@ readpages_fill_pages(struct TCP_Server_Info *server, · 50 unmodified lines | |||
| 4340 | * fill them until the writes are flushed. | 4338 | * fill them until the writes are flushed. |
| 4341 | */ | 4339 | */ |
| 4342 | zero_user(page, 0, PAGE_SIZE); | 4340 | zero_user(page, 0, PAGE_SIZE); |
| 4343 | lru_cache_add(page); | ||
| 4344 | flush_dcache_page(page); | 4341 | flush_dcache_page(page); |
| 4345 | SetPageUptodate(page); | 4342 | SetPageUptodate(page); |
| 4346 | unlock_page(page); | 4343 | unlock_page(page); |
| @@ -4350,7 +4347,6 @@ readpages_fill_pages(struct TCP_Server_Info *server, · 3 unmodified lines | |||
| 4350 | continue; | 4347 | continue; |
| 4351 | } else { | 4348 | } else { |
| 4352 | /* no need to hold page hostage */ | 4349 | /* no need to hold page hostage */ |
| 4353 | lru_cache_add(page); | ||
| 4354 | unlock_page(page); | 4350 | unlock_page(page); |
| 4355 | put_page(page); | 4351 | put_page(page); |
| 4356 | rdata->pages[i] = NULL; | 4352 | rdata->pages[i] = NULL; |
| @@ -4393,92 +4389,20 @@ cifs_readpages_copy_into_pages(struct TCP_Server_Info *server, · 36 unmodified lines | |||
| 4393 | return readpages_fill_pages(server, rdata, iter, iter->count); | 4389 | return readpages_fill_pages(server, rdata, iter, iter->count); |
| 4394 | } | 4390 | } |
| 4395 | 4391 | ||
| 4396 | static int | 4392 | static void cifs_readahead(struct readahead_control *ractl) |
| 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) | ||
| 4458 | { | 4393 | { |
| 4459 | int rc; | 4394 | int rc; |
| 4460 | int err = 0; | 4395 | struct cifsFileInfo *open_file = ractl->file->private_data; |
| 4461 | struct list_head tmplist; | 4396 | struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file); |
| 4462 | struct cifsFileInfo *open_file = file->private_data; | ||
| 4463 | struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); | ||
| 4464 | struct TCP_Server_Info *server; | 4397 | struct TCP_Server_Info *server; |
| 4465 | pid_t pid; | 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 | xid = get_xid(); | 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 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 4407 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 4484 | pid = open_file->pid; | 4408 | pid = open_file->pid; |
| @@ -4489,39 +4413,73 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 4 unmodified lines | |||
| 4489 | server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); | 4413 | server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); |
| 4490 | 4414 | ||
| 4491 | cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n", | 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 | 4419 | * Chop the readahead request up into rsize-sized read requests. |
| 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. | ||
| 4504 | */ | 4420 | */ |
| 4505 | while (!list_empty(page_list) && !err) { | 4421 | while ((nr_pages = readahead_count(ractl) - last_batch_size)) { |
| 4506 | unsigned int i, nr_pages, bytes, rsize; | 4422 | unsigned int i, got, rsize; |
| 4507 | loff_t offset; | 4423 | struct page *page; |
| 4508 | struct page *page, *tpage; | ||
| 4509 | struct cifs_readdata *rdata; | 4424 | struct cifs_readdata *rdata; |
| 4510 | struct cifs_credits credits_on_stack; | 4425 | struct cifs_credits credits_on_stack; |
| 4511 | struct cifs_credits *credits = &credits_on_stack; | 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 | if (open_file->invalidHandle) { | 4468 | if (open_file->invalidHandle) { |
| 4514 | rc = cifs_reopen_file(open_file, true); | 4469 | rc = cifs_reopen_file(open_file, true); |
| 4515 | if (rc == -EAGAIN) | 4470 | if (rc) { |
| 4516 | continue; | 4471 | if (rc == -EAGAIN) |
| 4517 | else if (rc) | 4472 | continue; |
| 4518 | break; | 4473 | break; |
| 4474 | } | ||
| 4519 | } | 4475 | } |
| 4520 | 4476 | ||
| 4521 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, | 4477 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, |
| 4522 | &rsize, credits); | 4478 | &rsize, credits); |
| 4523 | if (rc) | 4479 | if (rc) |
| 4524 | break; | 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 | * Give up immediately if rsize is too small to read an entire | 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 | * reach this point however since we set ra_pages to 0 when the | 4487 | * reach this point however since we set ra_pages to 0 when the |
| 4530 | * rsize is smaller than a cache page. | 4488 | * rsize is smaller than a cache page. |
| 4531 | */ | 4489 | */ |
| 4532 | if (unlikely(rsize < PAGE_SIZE)) { | 4490 | if (unlikely(!nr_pages)) { |
| 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) { | ||
| 4542 | add_credits_and_wake_if(server, credits, 0); | 4491 | add_credits_and_wake_if(server, credits, 0); |
| 4543 | break; | 4492 | break; |
| 4544 | } | 4493 | } |
| @@ -4546,36 +4495,31 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 1 unmodified line | |||
| 4546 | rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete); | 4495 | rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete); |
| 4547 | if (!rdata) { | 4496 | if (!rdata) { |
| 4548 | /* best to give up if we're out of mem */ | 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 | add_credits_and_wake_if(server, credits, 0); | 4498 | add_credits_and_wake_if(server, credits, 0); |
| 4557 | break; | 4499 | break; |
| 4558 | } | 4500 | } |
| 4559 | 4501 | ||
| 4560 | rdata->cfile = cifsFileInfo_get(open_file); | 4502 | got = __readahead_batch(ractl, rdata->pages, nr_pages); |
| 4561 | rdata->server = server; | 4503 | if (got != nr_pages) { |
| 4562 | rdata->mapping = mapping; | 4504 | pr_warn("__readahead_batch() returned %u/%u\n", |
| 4563 | rdata->offset = offset; | 4505 | got, nr_pages); |
| 4564 | rdata->bytes = bytes; | 4506 | nr_pages = got; |
| 4565 | rdata->pid = pid; | 4507 | } |
| 4566 | rdata->pagesz = PAGE_SIZE; | 4508 | |
| 4567 | rdata->tailsz = PAGE_SIZE; | 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 | rdata->read_into_pages = cifs_readpages_read_into_pages; | 4518 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
| 4569 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; | 4519 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; |
| 4570 | rdata->credits = credits_on_stack; | 4520 | 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 | } | ||
| 4576 | 4521 | ||
| 4577 | rc = adjust_credits(server, &rdata->credits, rdata->bytes); | 4522 | rc = adjust_credits(server, &rdata->credits, rdata->bytes); |
| 4578 | |||
| 4579 | if (!rc) { | 4523 | if (!rc) { |
| 4580 | if (rdata->cfile->invalidHandle) | 4524 | if (rdata->cfile->invalidHandle) |
| 4581 | rc = -EAGAIN; | 4525 | rc = -EAGAIN; |
| @@ -4587,7 +4531,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 5 unmodified lines | |||
| 4587 | add_credits_and_wake_if(server, &rdata->credits, 0); | 4531 | add_credits_and_wake_if(server, &rdata->credits, 0); |
| 4588 | for (i = 0; i < rdata->nr_pages; i++) { | 4532 | for (i = 0; i < rdata->nr_pages; i++) { |
| 4589 | page = rdata->pages[i]; | 4533 | page = rdata->pages[i]; |
| 4590 | lru_cache_add(page); | ||
| 4591 | unlock_page(page); | 4534 | unlock_page(page); |
| 4592 | put_page(page); | 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 | kref_put(&rdata->refcount, cifs_readdata_release); | 4542 | kref_put(&rdata->refcount, cifs_readdata_release); |
| 4543 | last_batch_size = nr_pages; | ||
| 4600 | } | 4544 | } |
| 4601 | 4545 | ||
| 4602 | free_xid(xid); | 4546 | free_xid(xid); |
| 4603 | return rc; | ||
| 4604 | } | 4547 | } |
| 4605 | 4548 | ||
| 4606 | /* | 4549 | /* |
| @@ -4924,7 +4867,7 @@ oplock_break_done: · 317 unmodified lines | |||
| 4924 | * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests | 4867 | * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests |
| 4925 | * so this method should never be called. | 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 | static ssize_t | 4872 | static ssize_t |
| 4930 | cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter) | 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 | const struct address_space_operations cifs_addr_ops = { | 4950 | const struct address_space_operations cifs_addr_ops = { |
| 5008 | .readpage = cifs_readpage, | 4951 | .readpage = cifs_readpage, |
| 5009 | .readpages = cifs_readpages, | 4952 | .readahead = cifs_readahead, |
| 5010 | .writepage = cifs_writepage, | 4953 | .writepage = cifs_writepage, |
| 5011 | .writepages = cifs_writepages, | 4954 | .writepages = cifs_writepages, |
| 5012 | .write_begin = cifs_write_begin, | 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", | 150 | struct netfs_cache_resources cres; |
| 143 | __func__, CIFS_I(inode)->fscache, page, inode); | 151 | struct fscache_cookie *cookie = cifs_inode_cookie(inode); |
| 144 | return -ENOBUFS; // Needs conversion to using netfslib | 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, | 175 | static int fscache_fallback_write_page(struct inode *inode, struct page *page, |
| 151 | struct address_space *mapping, | 176 | bool no_space_allocated_yet) |
| 152 | struct list_head *pages, | ||
| 153 | unsigned *nr_pages) | ||
| 154 | { | 177 | { |
| 155 | cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n", | 178 | struct netfs_cache_resources cres; |
| 156 | __func__, CIFS_I(inode)->fscache, *nr_pages, inode); | 179 | struct fscache_cookie *cookie = cifs_inode_cookie(inode); |
| 157 | return -ENOBUFS; // Needs conversion to using netfslib | 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 | cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n", | 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 | #ifndef _CIFS_FSCACHE_H | 9 | #ifndef _CIFS_FSCACHE_H |
| 10 | #define _CIFS_FSCACHE_H | 10 | #define _CIFS_FSCACHE_H |
| 11 | 11 | ||
| 12 | #include <linux/swap.h> | ||
| 12 | #include <linux/fscache.h> | 13 | #include <linux/fscache.h> |
| 13 | 14 | ||
| 14 | #include "cifsglob.h" | 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 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) | 62 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) |
| 70 | { | 63 | { |
| 71 | return CIFS_I(inode)->fscache; | 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 | i_size_read(inode), flags); | 73 | i_size_read(inode), flags); |
| 81 | } | 74 | } |
| 82 | 75 | ||
| 83 | static inline int cifs_readpage_from_fscache(struct inode *inode, | 76 | extern int __cifs_fscache_query_occupancy(struct inode *inode, |
| 84 | struct page *page) | 77 | pgoff_t first, unsigned int nr_pages, |
| 85 | { | 78 | pgoff_t *_data_first, |
| 86 | if (CIFS_I(inode)->fscache) | 79 | unsigned int *_data_nr_pages); |
| 87 | return __cifs_readpage_from_fscache(inode, page); | ||
| 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, | 92 | extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage); |
| 93 | struct address_space *mapping, | 93 | extern void __cifs_readpage_to_fscache(struct inode *pinode, struct page *ppage); |
| 94 | struct list_head *pages, | 94 | |
| 95 | unsigned *nr_pages) | 95 | |
| 96 | static inline int cifs_readpage_from_fscache(struct inode *inode, | ||
| 97 | struct page *page) | ||
| 96 | { | 98 | { |
| 97 | if (CIFS_I(inode)->fscache) | 99 | if (cifs_inode_cookie(inode)) |
| 98 | return __cifs_readpages_from_fscache(inode, mapping, pages, | 100 | return __cifs_readpage_from_fscache(inode, page); |
| 99 | nr_pages); | ||
| 100 | return -ENOBUFS; | 101 | return -ENOBUFS; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | static inline void cifs_readpage_to_fscache(struct inode *inode, | 104 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
| 104 | struct page *page) | 105 | struct page *page) |
| 105 | { | 106 | { |
| 106 | if (PageFsCache(page)) | 107 | if (cifs_inode_cookie(inode)) |
| 107 | __cifs_readpage_to_fscache(inode, page); | 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 | #else /* CONFIG_CIFS_FSCACHE */ | 122 | #else /* CONFIG_CIFS_FSCACHE */ |
| 111 | static inline | 123 | static inline |
| 112 | void cifs_fscache_fill_coherency(struct inode *inode, | 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 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; } | 135 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; } |
| 124 | static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {} | 136 | static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {} |
| 125 | 137 | ||
| 126 | static inline int | 138 | static inline int cifs_fscache_query_occupancy(struct inode *inode, |
| 127 | cifs_readpage_from_fscache(struct inode *inode, struct page *page) | 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 | return -ENOBUFS; | 145 | return -ENOBUFS; |
| 130 | } | 146 | } |
| 131 | 147 | ||
| 132 | static inline int cifs_readpages_from_fscache(struct inode *inode, | 148 | static inline int |
| 133 | struct address_space *mapping, | 149 | cifs_readpage_from_fscache(struct inode *inode, struct page *page) |
| 134 | struct list_head *pages, | ||
| 135 | unsigned *nr_pages) | ||
| 136 | { | 150 | { |
| 137 | return -ENOBUFS; | 151 | return -ENOBUFS; |
| 138 | } | 152 | } |
| 139 | 153 | ||
| 140 | static inline void cifs_readpage_to_fscache(struct inode *inode, | 154 | static inline |
| 141 | struct page *page) {} | 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 | #endif /* CONFIG_CIFS_FSCACHE */ | 162 | #endif /* CONFIG_CIFS_FSCACHE */ |
| 144 | 163 | ||
| @@ -83,6 +83,7 @@ static void cifs_set_ops(struct inode *inode) · 82 unmodified lines | |||
| 83 | static void | 83 | static void |
| 84 | cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) | 84 | cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) |
| 85 | { | 85 | { |
| 86 | struct cifs_fscache_inode_coherency_data cd; | ||
| 86 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 87 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
| 87 | 88 | ||
| 88 | cifs_dbg(FYI, "%s: revalidating inode %llu\n", | 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 | cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n", | 114 | cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n", |
| 114 | __func__, cifs_i->uniqueid); | 115 | __func__, cifs_i->uniqueid); |
| 115 | set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags); | 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 | int | 2265 | int |
| 2262 | cifs_invalidate_mapping(struct inode *inode) | 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 | int rc = 0; | 2268 | int rc = 0; |
| 2267 | 2269 | ||
| 2268 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 2270 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
| @@ -2272,8 +2274,6 @@ cifs_invalidate_mapping(struct inode *inode) · 3 unmodified lines | |||
| 2272 | __func__, inode); | 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 | return rc; | 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 | else | 713 | else |
| 714 | sz += sizeof(__le16); | 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 | return sz; | 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 | return ret; | 252 | return ret; |
| 253 | 253 | ||
| 254 | iomap->offset = map.m_la; | 254 | iomap->offset = map.m_la; |
| 255 | if (flags & IOMAP_DAX) { | 255 | if (flags & IOMAP_DAX) |
| 256 | iomap->dax_dev = mdev.m_daxdev; | 256 | iomap->dax_dev = mdev.m_daxdev; |
| 257 | iomap->offset += mdev.m_dax_part_off; | 257 | else |
| 258 | } else { | ||
| 259 | iomap->bdev = mdev.m_bdev; | 258 | iomap->bdev = mdev.m_bdev; |
| 260 | } | ||
| 261 | iomap->length = map.m_llen; | 259 | iomap->length = map.m_llen; |
| 262 | iomap->flags = 0; | 260 | iomap->flags = 0; |
| 263 | iomap->private = NULL; | 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 | } else { | 282 | } else { |
| 285 | iomap->type = IOMAP_MAPPED; | 283 | iomap->type = IOMAP_MAPPED; |
| 286 | iomap->addr = mdev.m_pa; | 284 | iomap->addr = mdev.m_pa; |
| 285 | if (flags & IOMAP_DAX) | ||
| 286 | iomap->addr += mdev.m_dax_part_off; | ||
| 287 | } | 287 | } |
| 288 | return 0; | 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 | return false; | 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 | static bool z_erofs_page_is_invalidated(struct page *page) | 813 | static bool z_erofs_page_is_invalidated(struct page *page) |
| 844 | { | 814 | { |
| 845 | return !page->mapping && !z_erofs_is_shortlived_page(page); | 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 | static int z_erofs_decompress_pcluster(struct super_block *sb, | 818 | static int z_erofs_decompress_pcluster(struct super_block *sb, |
| 876 | struct z_erofs_pcluster *pcl, | 819 | struct z_erofs_pcluster *pcl, |
| 877 | struct page **pagepool) | 820 | struct page **pagepool) |
| @@ -1123,6 +1066,35 @@ static void z_erofs_decompressqueue_work(struct work_struct *work) · 245 unmodified lines | |||
| 1123 | kvfree(bgq); | 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 | static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, | 1098 | static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, |
| 1127 | unsigned int nr, | 1099 | unsigned int nr, |
| 1128 | struct page **pagepool, | 1100 | struct page **pagepool, |
| @@ -1300,6 +1272,33 @@ static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, · 171 unmodified lines | |||
| 1300 | qtail[JQ_BYPASS] = &pcl->next; | 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 | static void z_erofs_submit_queue(struct super_block *sb, | 1302 | static void z_erofs_submit_queue(struct super_block *sb, |
| 1304 | struct z_erofs_decompress_frontend *f, | 1303 | struct z_erofs_decompress_frontend *f, |
| 1305 | struct page **pagepool, | 1304 | struct page **pagepool, |
| @@ -630,6 +630,13 @@ static int z_erofs_do_map_blocks(struct inode *inode, · 629 unmodified lines | |||
| 630 | if (endoff >= m.clusterofs) { | 630 | if (endoff >= m.clusterofs) { |
| 631 | m.headtype = m.type; | 631 | m.headtype = m.type; |
| 632 | map->m_la = (m.lcn << lclusterbits) | m.clusterofs; | 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 | break; | 640 | break; |
| 634 | } | 641 | } |
| 635 | /* m.lcn should be >= 1 if endoff < m.clusterofs */ | 642 | /* m.lcn should be >= 1 if endoff < m.clusterofs */ |
| @@ -139,7 +139,7 @@ fail: · 138 unmodified lines | |||
| 139 | /* | 139 | /* |
| 140 | * Inode operation get_posix_acl(). | 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 | struct posix_acl * | 144 | struct posix_acl * |
| 145 | ext4_get_acl(struct inode *inode, int type, bool rcu) | 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 | * Set the access or default ACL of an inode. | 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 | static int | 188 | static int |
| 189 | __ext4_set_acl(handle_t *handle, struct inode *inode, int type, | 189 | __ext4_set_acl(handle_t *handle, struct inode *inode, int type, |
| @@ -271,8 +271,8 @@ out_stop: · 81 unmodified lines | |||
| 271 | /* | 271 | /* |
| 272 | * Initialize the ACLs of a new inode. Called from ext4_new_inode. | 272 | * Initialize the ACLs of a new inode. Called from ext4_new_inode. |
| 273 | * | 273 | * |
| 274 | * dir->i_mutex: down | 274 | * dir->i_rwsem: down |
| 275 | * inode->i_mutex: up (access to inode is still exclusive) | 275 | * inode->i_rwsem: up (access to inode is still exclusive) |
| 276 | */ | 276 | */ |
| 277 | int | 277 | int |
| 278 | ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) | 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 | * Extended attributes can be read independently of the main file | 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 | * between readers of EAs and writers of regular file data, so | 1032 | * between readers of EAs and writers of regular file data, so |
| 1033 | * instead we synchronize on xattr_sem when reading or changing | 1033 | * instead we synchronize on xattr_sem when reading or changing |
| 1034 | * EAs. | 1034 | * EAs. |
| @@ -1750,6 +1750,7 @@ struct ext4_sb_info { · 715 unmodified lines | |||
| 1750 | spinlock_t s_fc_lock; | 1750 | spinlock_t s_fc_lock; |
| 1751 | struct buffer_head *s_fc_bh; | 1751 | struct buffer_head *s_fc_bh; |
| 1752 | struct ext4_fc_stats s_fc_stats; | 1752 | struct ext4_fc_stats s_fc_stats; |
| 1753 | tid_t s_fc_ineligible_tid; | ||
| 1753 | #ifdef CONFIG_EXT4_DEBUG | 1754 | #ifdef CONFIG_EXT4_DEBUG |
| 1754 | int s_fc_debug_max_replay; | 1755 | int s_fc_debug_max_replay; |
| 1755 | #endif | 1756 | #endif |
| @@ -1795,10 +1796,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) · 39 unmodified lines | |||
| 1795 | enum { | 1796 | enum { |
| 1796 | EXT4_MF_MNTDIR_SAMPLED, | 1797 | EXT4_MF_MNTDIR_SAMPLED, |
| 1797 | EXT4_MF_FS_ABORTED, /* Fatal error detected */ | 1798 | EXT4_MF_FS_ABORTED, /* Fatal error detected */ |
| 1798 | EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */ | 1799 | EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ |
| 1799 | EXT4_MF_FC_COMMITTING /* File system underoing a fast | ||
| 1800 | * commit. | ||
| 1801 | */ | ||
| 1802 | }; | 1800 | }; |
| 1803 | 1801 | ||
| 1804 | static inline void ext4_set_mount_flag(struct super_block *sb, int bit) | 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 | struct dentry *dentry); | 2924 | struct dentry *dentry); |
| 2927 | void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); | 2925 | void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); |
| 2928 | void ext4_fc_track_inode(handle_t *handle, struct inode *inode); | 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 | void ext4_fc_start_update(struct inode *inode); | 2928 | void ext4_fc_start_update(struct inode *inode); |
| 2931 | void ext4_fc_stop_update(struct inode *inode); | 2929 | void ext4_fc_stop_update(struct inode *inode); |
| 2932 | void ext4_fc_del(struct inode *inode); | 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 | int ext4_fc_commit(journal_t *journal, tid_t commit_tid); | 2933 | int ext4_fc_commit(journal_t *journal, tid_t commit_tid); |
| 2936 | int __init ext4_fc_init_dentry_cache(void); | 2934 | int __init ext4_fc_init_dentry_cache(void); |
| 2937 | void ext4_fc_destroy_dentry_cache(void); | 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 | /* mballoc.c */ | 2940 | /* mballoc.c */ |
| 2940 | extern const struct seq_operations ext4_mb_seq_groups_ops; | 2941 | extern const struct seq_operations ext4_mb_seq_groups_ops; |
| @@ -3407,7 +3408,7 @@ do { \ · 466 unmodified lines | |||
| 3407 | #define EXT4_FREECLUSTERS_WATERMARK 0 | 3408 | #define EXT4_FREECLUSTERS_WATERMARK 0 |
| 3408 | #endif | 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 | static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) | 3412 | static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) |
| 3412 | { | 3413 | { |
| 3413 | WARN_ON_ONCE(S_ISREG(inode->i_mode) && | 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 | up_write(&EXT4_I(inode)->i_data_sem); | 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 | static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) | 3423 | static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) |
| 3423 | { | 3424 | { |
| 3424 | int changed = 0; | 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 | * This function controls whether or not we should try to go down the | 492 | * This function controls whether or not we should try to go down the |
| 493 | * dioread_nolock code paths, which makes it safe to avoid taking | 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 | * files, and it doesn't work if data journaling is enabled, since the | 495 | * files, and it doesn't work if data journaling is enabled, since the |
| 496 | * dioread_nolock code uses b_private to pass information back to the | 496 | * dioread_nolock code uses b_private to pass information back to the |
| 497 | * I/O completion handler, and this conflicts with the jbd's use of | 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 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this | 97 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this |
| 98 | * moment, get_block can be called only for blocks inside i_size since | 98 | * moment, get_block can be called only for blocks inside i_size since |
| 99 | * page cache has been already dropped and writes are blocked by | 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 | BUG_ON(EXT4_JOURNAL(inode) == NULL); | 102 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 103 | ext4_discard_preallocations(inode, 0); | 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 | flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT; | 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 | inode_dio_wait(inode); | 4576 | inode_dio_wait(inode); |
| 4577 | 4577 | ||
| 4578 | /* Preallocate the range including the unaligned edges */ | 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 | goto out; | 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 | inode_dio_wait(inode); | 4742 | inode_dio_wait(inode); |
| 4743 | 4743 | ||
| 4744 | ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags); | 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 | ret = PTR_ERR(handle); | 5334 | ret = PTR_ERR(handle); |
| 5335 | goto out_mmap; | 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 | down_write(&EXT4_I(inode)->i_data_sem); | 5339 | down_write(&EXT4_I(inode)->i_data_sem); |
| 5340 | ext4_discard_preallocations(inode, 0); | 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 | ret = PTR_ERR(handle); | 5474 | ret = PTR_ERR(handle); |
| 5475 | goto out_mmap; | 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 | /* Expand file to avoid data loss if there is error while shifting */ | 5479 | /* Expand file to avoid data loss if there is error while shifting */ |
| 5480 | inode->i_size += len; | 5480 | inode->i_size += len; |
| @@ -5571,7 +5571,7 @@ out_mutex: · 90 unmodified lines | |||
| 5571 | * stuff such as page-cache locking consistency, bh mapping consistency or | 5571 | * stuff such as page-cache locking consistency, bh mapping consistency or |
| 5572 | * extent's data copying must be performed by caller. | 5572 | * extent's data copying must be performed by caller. |
| 5573 | * Locking: | 5573 | * Locking: |
| 5574 | * i_mutex is held for both inodes | 5574 | * i_rwsem is held for both inodes |
| 5575 | * i_data_sem is locked for write for both inodes | 5575 | * i_data_sem is locked for write for both inodes |
| 5576 | * Assumptions: | 5576 | * Assumptions: |
| 5577 | * All pages from requested range are locked for both inodes | 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 | ext4_mb_mark_bb(inode->i_sb, | 6092 | ext4_mb_mark_bb(inode->i_sb, |
| 6093 | path[j].p_block, 1, 0); | 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 | ext4_ext_drop_refs(path); | 6097 | ext4_ext_drop_refs(path); |
| 6096 | kfree(path); | 6098 | kfree(path); |
| 6097 | } | 6099 | } |
| 6098 | ext4_mb_mark_bb(inode->i_sb, map.m_pblk, map.m_len, 0); | 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 | cur = cur + map.m_len; | 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 | 303 | * Mark file system as fast commit ineligible, and record latest |
| 304 | * operation would result in a full jbd2 commit. | 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 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 309 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 310 | tid_t tid; | ||
| 309 | 311 | ||
| 310 | if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || | 312 | if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || |
| 311 | (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) | 313 | (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) |
| 312 | return; | 314 | return; |
| 313 | 315 | ||
| 314 | ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | 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 | WARN_ON(reason >= EXT4_FC_REASON_MAX); | 329 | WARN_ON(reason >= EXT4_FC_REASON_MAX); |
| 316 | sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; | 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 | spin_lock(&sbi->s_fc_lock); | 375 | spin_lock(&sbi->s_fc_lock); |
| 362 | if (list_empty(&EXT4_I(inode)->i_fc_list)) | 376 | if (list_empty(&EXT4_I(inode)->i_fc_list)) |
| 363 | list_add_tail(&EXT4_I(inode)->i_fc_list, | 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 | &sbi->s_fc_q[FC_Q_STAGING] : | 380 | &sbi->s_fc_q[FC_Q_STAGING] : |
| 366 | &sbi->s_fc_q[FC_Q_MAIN]); | 381 | &sbi->s_fc_q[FC_Q_MAIN]); |
| 367 | spin_unlock(&sbi->s_fc_lock); | 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 | mutex_unlock(&ei->i_fc_lock); | 402 | mutex_unlock(&ei->i_fc_lock); |
| 388 | node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); | 403 | node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); |
| 389 | if (!node) { | 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 | mutex_lock(&ei->i_fc_lock); | 406 | mutex_lock(&ei->i_fc_lock); |
| 392 | return -ENOMEM; | 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 | if (!node->fcd_name.name) { | 415 | if (!node->fcd_name.name) { |
| 401 | kmem_cache_free(ext4_fc_dentry_cachep, node); | 416 | kmem_cache_free(ext4_fc_dentry_cachep, node); |
| 402 | ext4_fc_mark_ineligible(inode->i_sb, | 417 | ext4_fc_mark_ineligible(inode->i_sb, |
| 403 | EXT4_FC_REASON_NOMEM); | 418 | EXT4_FC_REASON_NOMEM, NULL); |
| 404 | mutex_lock(&ei->i_fc_lock); | 419 | mutex_lock(&ei->i_fc_lock); |
| 405 | return -ENOMEM; | 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 | node->fcd_name.len = dentry->d_name.len; | 429 | node->fcd_name.len = dentry->d_name.len; |
| 415 | 430 | ||
| 416 | spin_lock(&sbi->s_fc_lock); | 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 | list_add_tail(&node->fcd_list, | 434 | list_add_tail(&node->fcd_list, |
| 419 | &sbi->s_fc_dentry_q[FC_Q_STAGING]); | 435 | &sbi->s_fc_dentry_q[FC_Q_STAGING]); |
| 420 | else | 436 | else |
| @@ -502,7 +518,7 @@ void ext4_fc_track_inode(handle_t *handle, struct inode *inode) · 81 unmodified lines | |||
| 502 | 518 | ||
| 503 | if (ext4_should_journal_data(inode)) { | 519 | if (ext4_should_journal_data(inode)) { |
| 504 | ext4_fc_mark_ineligible(inode->i_sb, | 520 | ext4_fc_mark_ineligible(inode->i_sb, |
| 505 | EXT4_FC_REASON_INODE_JOURNAL_DATA); | 521 | EXT4_FC_REASON_INODE_JOURNAL_DATA, handle); |
| 506 | return; | 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 | int ret = 0; | 895 | int ret = 0; |
| 880 | 896 | ||
| 881 | spin_lock(&sbi->s_fc_lock); | 897 | spin_lock(&sbi->s_fc_lock); |
| 882 | ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING); | ||
| 883 | list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) { | 898 | list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) { |
| 884 | ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); | 899 | ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); |
| 885 | while (atomic_read(&ei->i_fc_updates)) { | 900 | while (atomic_read(&ei->i_fc_updates)) { |
| @@ -1179,7 +1194,7 @@ fallback: · 293 unmodified lines | |||
| 1179 | * Fast commit cleanup routine. This is called after every fast commit and | 1194 | * Fast commit cleanup routine. This is called after every fast commit and |
| 1180 | * full commit. full is true if we are called after a full commit. | 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 | struct super_block *sb = journal->j_private; | 1199 | struct super_block *sb = journal->j_private; |
| 1185 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 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 | list_del_init(&iter->i_fc_list); | 1212 | list_del_init(&iter->i_fc_list); |
| 1198 | ext4_clear_inode_state(&iter->vfs_inode, | 1213 | ext4_clear_inode_state(&iter->vfs_inode, |
| 1199 | EXT4_STATE_FC_COMMITTING); | 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 | /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ | 1217 | /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ |
| 1202 | smp_mb(); | 1218 | smp_mb(); |
| 1203 | #if (BITS_PER_LONG < 64) | 1219 | #if (BITS_PER_LONG < 64) |
| @@ -1226,8 +1242,10 @@ static void ext4_fc_cleanup(journal_t *journal, int full) · 22 unmodified lines | |||
| 1226 | list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], | 1242 | list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], |
| 1227 | &sbi->s_fc_q[FC_Q_MAIN]); | 1243 | &sbi->s_fc_q[FC_Q_MAIN]); |
| 1228 | 1244 | ||
| 1229 | ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); | 1245 | if (tid >= sbi->s_fc_ineligible_tid) { |
| 1230 | ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | 1246 | sbi->s_fc_ineligible_tid = 0; |
| 1247 | ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | ||
| 1248 | } | ||
| 1231 | 1249 | ||
| 1232 | if (full) | 1250 | if (full) |
| 1233 | sbi->s_fc_bytes = 0; | 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 | if (state->fc_modified_inodes[i] == ino) | 1410 | if (state->fc_modified_inodes[i] == ino) |
| 1393 | return 0; | 1411 | return 0; |
| 1394 | if (state->fc_modified_inodes_used == state->fc_modified_inodes_size) { | 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 | state->fc_modified_inodes = krealloc( | 1413 | state->fc_modified_inodes = krealloc( |
| 1398 | state->fc_modified_inodes, sizeof(int) * | 1414 | state->fc_modified_inodes, |
| 1399 | state->fc_modified_inodes_size, | 1415 | sizeof(int) * (state->fc_modified_inodes_size + |
| 1400 | GFP_KERNEL); | 1416 | EXT4_FC_REPLAY_REALLOC_INCREMENT), |
| 1417 | GFP_KERNEL); | ||
| 1401 | if (!state->fc_modified_inodes) | 1418 | if (!state->fc_modified_inodes) |
| 1402 | return -ENOMEM; | 1419 | return -ENOMEM; |
| 1420 | state->fc_modified_inodes_size += | ||
| 1421 | EXT4_FC_REPLAY_REALLOC_INCREMENT; | ||
| 1403 | } | 1422 | } |
| 1404 | state->fc_modified_inodes[state->fc_modified_inodes_used++] = ino; | 1423 | state->fc_modified_inodes[state->fc_modified_inodes_used++] = ino; |
| 1405 | return 0; | 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 | inode = NULL; | 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 | raw_fc_inode = (struct ext4_inode *) | 1457 | raw_fc_inode = (struct ext4_inode *) |
| 1437 | (val + offsetof(struct ext4_fc_inode, fc_raw_inode)); | 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 | 1587 | * Record physical disk regions which are in use as per fast commit area, |
| 1567 | * simple replay phase allocator excludes these regions from allocation. | 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, | 1591 | int ext4_fc_record_regions(struct super_block *sb, int ino, |
| 1570 | ext4_lblk_t lblk, ext4_fsblk_t pblk, int len) | 1592 | ext4_lblk_t lblk, ext4_fsblk_t pblk, int len, int replay) |
| 1571 | { | 1593 | { |
| 1572 | struct ext4_fc_replay_state *state; | 1594 | struct ext4_fc_replay_state *state; |
| 1573 | struct ext4_fc_alloc_region *region; | 1595 | struct ext4_fc_alloc_region *region; |
| 1574 | 1596 | ||
| 1575 | state = &EXT4_SB(sb)->s_fc_replay_state; | 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 | if (state->fc_regions_used == state->fc_regions_size) { | 1604 | if (state->fc_regions_used == state->fc_regions_size) { |
| 1577 | state->fc_regions_size += | 1605 | state->fc_regions_size += |
| 1578 | EXT4_FC_REPLAY_REALLOC_INCREMENT; | 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 | region->pblk = pblk; | 1618 | region->pblk = pblk; |
| 1591 | region->len = len; | 1619 | region->len = len; |
| 1592 | 1620 | ||
| 1621 | if (replay) | ||
| 1622 | state->fc_regions_valid++; | ||
| 1623 | |||
| 1593 | return 0; | 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 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); | 1654 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); |
| 1655 | if (ret) | ||
| 1656 | goto out; | ||
| 1624 | 1657 | ||
| 1625 | start = le32_to_cpu(ex->ee_block); | 1658 | start = le32_to_cpu(ex->ee_block); |
| 1626 | start_pblk = ext4_ext_pblock(ex); | 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 | map.m_pblk = 0; | 1671 | map.m_pblk = 0; |
| 1639 | ret = ext4_map_blocks(NULL, inode, &map, 0); | 1672 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 1640 | 1673 | ||
| 1641 | if (ret < 0) { | 1674 | if (ret < 0) |
| 1642 | iput(inode); | 1675 | goto out; |
| 1643 | return 0; | ||
| 1644 | } | ||
| 1645 | 1676 | ||
| 1646 | if (ret == 0) { | 1677 | if (ret == 0) { |
| 1647 | /* Range is not mapped */ | 1678 | /* Range is not mapped */ |
| 1648 | path = ext4_find_extent(inode, cur, NULL, 0); | 1679 | path = ext4_find_extent(inode, cur, NULL, 0); |
| 1649 | if (IS_ERR(path)) { | 1680 | if (IS_ERR(path)) |
| 1650 | iput(inode); | 1681 | goto out; |
| 1651 | return 0; | ||
| 1652 | } | ||
| 1653 | memset(&newex, 0, sizeof(newex)); | 1682 | memset(&newex, 0, sizeof(newex)); |
| 1654 | newex.ee_block = cpu_to_le32(cur); | 1683 | newex.ee_block = cpu_to_le32(cur); |
| 1655 | ext4_ext_store_pblock( | 1684 | ext4_ext_store_pblock( |
| @@ -1663,10 +1692,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 7 unmodified lines | |||
| 1663 | up_write((&EXT4_I(inode)->i_data_sem)); | 1692 | up_write((&EXT4_I(inode)->i_data_sem)); |
| 1664 | ext4_ext_drop_refs(path); | 1693 | ext4_ext_drop_refs(path); |
| 1665 | kfree(path); | 1694 | kfree(path); |
| 1666 | if (ret) { | 1695 | if (ret) |
| 1667 | iput(inode); | 1696 | goto out; |
| 1668 | return 0; | ||
| 1669 | } | ||
| 1670 | goto next; | 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 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, | 1706 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, |
| 1680 | ext4_ext_is_unwritten(ex), | 1707 | ext4_ext_is_unwritten(ex), |
| 1681 | start_pblk + cur - start); | 1708 | start_pblk + cur - start); |
| 1682 | if (ret) { | 1709 | if (ret) |
| 1683 | iput(inode); | 1710 | goto out; |
| 1684 | return 0; | ||
| 1685 | } | ||
| 1686 | /* | 1711 | /* |
| 1687 | * Mark the old blocks as free since they aren't used | 1712 | * Mark the old blocks as free since they aren't used |
| 1688 | * anymore. We maintain an array of all the modified | 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 | ext4_ext_is_unwritten(ex), map.m_pblk); | 1727 | ext4_ext_is_unwritten(ex), map.m_pblk); |
| 1703 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, | 1728 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, |
| 1704 | ext4_ext_is_unwritten(ex), map.m_pblk); | 1729 | ext4_ext_is_unwritten(ex), map.m_pblk); |
| 1705 | if (ret) { | 1730 | if (ret) |
| 1706 | iput(inode); | 1731 | goto out; |
| 1707 | return 0; | ||
| 1708 | } | ||
| 1709 | /* | 1732 | /* |
| 1710 | * We may have split the extent tree while toggling the state. | 1733 | * We may have split the extent tree while toggling the state. |
| 1711 | * Try to shrink the extent tree now. | 1734 | * Try to shrink the extent tree now. |
| @@ -1717,6 +1740,7 @@ next: · 5 unmodified lines | |||
| 1717 | } | 1740 | } |
| 1718 | ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >> | 1741 | ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >> |
| 1719 | sb->s_blocksize_bits); | 1742 | sb->s_blocksize_bits); |
| 1743 | out: | ||
| 1720 | iput(inode); | 1744 | iput(inode); |
| 1721 | return 0; | 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 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); | 1772 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); |
| 1773 | if (ret) | ||
| 1774 | goto out; | ||
| 1749 | 1775 | ||
| 1750 | jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", | 1776 | jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", |
| 1751 | inode->i_ino, le32_to_cpu(lrange.fc_lblk), | 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 | map.m_len = remaining; | 1781 | map.m_len = remaining; |
| 1756 | 1782 | ||
| 1757 | ret = ext4_map_blocks(NULL, inode, &map, 0); | 1783 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 1758 | if (ret < 0) { | 1784 | if (ret < 0) |
| 1759 | iput(inode); | 1785 | goto out; |
| 1760 | return 0; | ||
| 1761 | } | ||
| 1762 | if (ret > 0) { | 1786 | if (ret > 0) { |
| 1763 | remaining -= ret; | 1787 | remaining -= ret; |
| 1764 | cur += ret; | 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 | down_write(&EXT4_I(inode)->i_data_sem); | 1796 | down_write(&EXT4_I(inode)->i_data_sem); |
| 1773 | ret = ext4_ext_remove_space(inode, lrange.fc_lblk, | 1797 | ret = ext4_ext_remove_space(inode, le32_to_cpu(lrange.fc_lblk), |
| 1774 | lrange.fc_lblk + lrange.fc_len - 1); | 1798 | le32_to_cpu(lrange.fc_lblk) + |
| 1799 | le32_to_cpu(lrange.fc_len) - 1); | ||
| 1775 | up_write(&EXT4_I(inode)->i_data_sem); | 1800 | up_write(&EXT4_I(inode)->i_data_sem); |
| 1776 | if (ret) { | 1801 | if (ret) |
| 1777 | iput(inode); | 1802 | goto out; |
| 1778 | return 0; | ||
| 1779 | } | ||
| 1780 | ext4_ext_replay_shrink_inode(inode, | 1803 | ext4_ext_replay_shrink_inode(inode, |
| 1781 | i_size_read(inode) >> sb->s_blocksize_bits); | 1804 | i_size_read(inode) >> sb->s_blocksize_bits); |
| 1782 | ext4_mark_inode_dirty(NULL, inode); | 1805 | ext4_mark_inode_dirty(NULL, inode); |
| 1806 | out: | ||
| 1783 | iput(inode); | 1807 | iput(inode); |
| 1784 | |||
| 1785 | return 0; | 1808 | return 0; |
| 1786 | } | 1809 | } |
| 1787 | 1810 | ||
| @@ -1937,7 +1960,7 @@ static int ext4_fc_replay_scan(journal_t *journal, · 149 unmodified lines | |||
| 1937 | ret = ext4_fc_record_regions(sb, | 1960 | ret = ext4_fc_record_regions(sb, |
| 1938 | le32_to_cpu(ext.fc_ino), | 1961 | le32_to_cpu(ext.fc_ino), |
| 1939 | le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex), | 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 | if (ret < 0) | 1964 | if (ret < 0) |
| 1942 | break; | 1965 | break; |
| 1943 | ret = JBD2_FC_REPLAY_CONTINUE; | 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 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this | 696 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this |
| 697 | * moment, get_block can be called only for blocks inside i_size since | 697 | * moment, get_block can be called only for blocks inside i_size since |
| 698 | * page cache has been already dropped and writes are blocked by | 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 | BUG_ON(EXT4_JOURNAL(inode) == NULL); | 701 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 702 | ext4_discard_preallocations(inode, 0); | 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 | struct page **pagep, | 911 | struct page **pagep, |
| 912 | void **fsdata) | 912 | void **fsdata) |
| 913 | { | 913 | { |
| 914 | int ret, inline_size; | 914 | int ret; |
| 915 | handle_t *handle; | 915 | handle_t *handle; |
| 916 | struct page *page; | 916 | struct page *page; |
| 917 | struct ext4_iloc iloc; | 917 | struct ext4_iloc iloc; |
| @@ -928,14 +928,9 @@ retry_journal: · 10 unmodified lines | |||
| 928 | goto out; | 928 | goto out; |
| 929 | } | 929 | } |
| 930 | 930 | ||
| 931 | inline_size = ext4_get_max_inline_size(inode); | 931 | ret = ext4_prepare_inline_data(handle, inode, pos + len); |
| 932 | 932 | if (ret && ret != -ENOSPC) | |
| 933 | ret = -ENOSPC; | 933 | goto out_journal; |
| 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 | } | ||
| 939 | 934 | ||
| 940 | /* | 935 | /* |
| 941 | * We cannot recurse into the filesystem as the transaction | 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 | struct ext4_iloc *iloc, | 1128 | struct ext4_iloc *iloc, |
| 1134 | void *buf, int inline_size) | 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 | ext4_write_inline_data(inode, iloc, buf, 0, inline_size); | 1140 | ext4_write_inline_data(inode, iloc, buf, 0, inline_size); |
| 1138 | ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); | 1141 | ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); |
| 1139 | } | 1142 | } |
| @@ -338,7 +338,7 @@ stop_handle: · 337 unmodified lines | |||
| 338 | return; | 338 | return; |
| 339 | no_delete: | 339 | no_delete: |
| 340 | if (!list_empty(&EXT4_I(inode)->i_fc_list)) | 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 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ | 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 | * __block_write_begin may have instantiated a few blocks | 1225 | * __block_write_begin may have instantiated a few blocks |
| 1226 | * outside i_size. Trim these off again. Don't need | 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 | * Add inode to orphan list in case we crash before | 1229 | * Add inode to orphan list in case we crash before |
| 1230 | * truncate finishes | 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 | inode_dio_wait(inode); | 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 | * There is a possibility that we're either freeing the inode | 4130 | * There is a possibility that we're either freeing the inode |
| 4131 | * or it's a completely new inode. In those cases we might not | 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 | if (!(inode->i_state & (I_NEW|I_FREEING))) | 4134 | if (!(inode->i_state & (I_NEW|I_FREEING))) |
| 4135 | WARN_ON(!inode_is_locked(inode)); | 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 | * transaction are already on disk (truncate waits for pages under | 5271 | * transaction are already on disk (truncate waits for pages under |
| 5272 | * writeback). | 5272 | * writeback). |
| 5273 | * | 5273 | * |
| 5274 | * Called with inode->i_mutex down. | 5274 | * Called with inode->i_rwsem down. |
| 5275 | */ | 5275 | */ |
| 5276 | int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, | 5276 | int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, |
| 5277 | struct iattr *attr) | 5277 | struct iattr *attr) |
| @@ -5983,7 +5983,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) · 705 unmodified lines | |||
| 5983 | return PTR_ERR(handle); | 5983 | return PTR_ERR(handle); |
| 5984 | 5984 | ||
| 5985 | ext4_fc_mark_ineligible(inode->i_sb, | 5985 | ext4_fc_mark_ineligible(inode->i_sb, |
| 5986 | EXT4_FC_REASON_JOURNAL_FLAG_CHANGE); | 5986 | EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, handle); |
| 5987 | err = ext4_mark_inode_dirty(handle, inode); | 5987 | err = ext4_mark_inode_dirty(handle, inode); |
| 5988 | ext4_handle_sync(handle); | 5988 | ext4_handle_sync(handle); |
| 5989 | ext4_journal_stop(handle); | 5989 | ext4_journal_stop(handle); |
| @@ -411,7 +411,7 @@ static long swap_inode_boot_loader(struct super_block *sb, · 410 unmodified lines | |||
| 411 | err = -EINVAL; | 411 | err = -EINVAL; |
| 412 | goto err_out; | 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 | /* Protect extent tree against block allocations via delalloc */ | 416 | /* Protect extent tree against block allocations via delalloc */ |
| 417 | ext4_double_down_write_data_sem(inode, inode_bl); | 417 | ext4_double_down_write_data_sem(inode, inode_bl); |
| @@ -1373,7 +1373,7 @@ mext_out: · 955 unmodified lines | |||
| 1373 | 1373 | ||
| 1374 | err = ext4_resize_fs(sb, n_blocks_count); | 1374 | err = ext4_resize_fs(sb, n_blocks_count); |
| 1375 | if (EXT4_SB(sb)->s_journal) { | 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 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 1377 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
| 1378 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); | 1378 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); |
| 1379 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 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 | struct super_block *sb = ar->inode->i_sb; | 5753 | struct super_block *sb = ar->inode->i_sb; |
| 5754 | ext4_group_t group; | 5754 | ext4_group_t group; |
| 5755 | ext4_grpblk_t blkoff; | 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 | ext4_fsblk_t goal, block; | 5758 | ext4_fsblk_t goal, block; |
| 5758 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 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 | ext4_get_group_no_and_offset(sb, | 5776 | ext4_get_group_no_and_offset(sb, |
| 5776 | max(ext4_group_first_block_no(sb, group), goal), | 5777 | max(ext4_group_first_block_no(sb, group), goal), |
| 5777 | NULL, &blkoff); | 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 | blkoff); | 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 | brelse(bitmap_bh); | 5790 | brelse(bitmap_bh); |
| 5781 | if (i >= sb->s_blocksize) | 5791 | if (i < max) |
| 5782 | continue; | 5792 | break; |
| 5783 | if (ext4_fc_replay_check_excluded(sb, | ||
| 5784 | ext4_group_first_block_no(sb, group) + i)) | ||
| 5785 | continue; | ||
| 5786 | 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 | return 0; | 5797 | return 0; |
| 5798 | } | ||
| 5791 | 5799 | ||
| 5792 | block = ext4_group_first_block_no(sb, group) + i; | 5800 | block = ext4_group_first_block_no(sb, group) + i; |
| 5793 | ext4_mb_mark_bb(sb, block, 1, 1); | 5801 | ext4_mb_mark_bb(sb, block, 1, 1); |
| @@ -485,7 +485,7 @@ int ext4_ext_migrate(struct inode *inode) · 484 unmodified lines | |||
| 485 | * when we add extents we extent the journal | 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 | * allocation via mmap write to holes. If we have allocated | 489 | * allocation via mmap write to holes. If we have allocated |
| 490 | * new blocks we fail migrate. New block allocation will | 490 | * new blocks we fail migrate. New block allocation will |
| 491 | * clear EXT4_STATE_EXT_MIGRATE flag. The flag is updated | 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 | * dirents in directories. | 3889 | * dirents in directories. |
| 3890 | */ | 3890 | */ |
| 3891 | ext4_fc_mark_ineligible(old.inode->i_sb, | 3891 | ext4_fc_mark_ineligible(old.inode->i_sb, |
| 3892 | EXT4_FC_REASON_RENAME_DIR); | 3892 | EXT4_FC_REASON_RENAME_DIR, handle); |
| 3893 | } else { | 3893 | } else { |
| 3894 | if (new.inode) | 3894 | if (new.inode) |
| 3895 | ext4_fc_track_unlink(handle, new.dentry); | 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 | if (unlikely(retval)) | 4049 | if (unlikely(retval)) |
| 4050 | goto end_rename; | 4050 | goto end_rename; |
| 4051 | ext4_fc_mark_ineligible(new.inode->i_sb, | 4051 | ext4_fc_mark_ineligible(new.inode->i_sb, |
| 4052 | EXT4_FC_REASON_CROSS_RENAME); | 4052 | EXT4_FC_REASON_CROSS_RENAME, handle); |
| 4053 | if (old.dir_bh) { | 4053 | if (old.dir_bh) { |
| 4054 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); | 4054 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); |
| 4055 | if (retval) | 4055 | if (retval) |
| @@ -93,7 +93,7 @@ static int ext4_orphan_file_add(handle_t *handle, struct inode *inode) · 92 unmodified lines | |||
| 93 | * At filesystem recovery time, we walk this list deleting unlinked | 93 | * At filesystem recovery time, we walk this list deleting unlinked |
| 94 | * inodes and truncating linked inodes in ext4_orphan_cleanup(). | 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 | * we are just creating the inode or deleting it. | 97 | * we are just creating the inode or deleting it. |
| 98 | */ | 98 | */ |
| 99 | int ext4_orphan_add(handle_t *handle, struct inode *inode) | 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 | * Orphan handling is only valid for files with data blocks | 120 | * Orphan handling is only valid for files with data blocks |
| 121 | * being truncated, or files being unlinked. Note that we either | 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 | * so i_nlink should not be bumped due to race | 123 | * so i_nlink should not be bumped due to race |
| 124 | */ | 124 | */ |
| 125 | ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 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 | INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]); | 5082 | INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]); |
| 5083 | sbi->s_fc_bytes = 0; | 5083 | sbi->s_fc_bytes = 0; |
| 5084 | ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | 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 | spin_lock_init(&sbi->s_fc_lock); | 5086 | spin_lock_init(&sbi->s_fc_lock); |
| 5087 | memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); | 5087 | memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); |
| 5088 | sbi->s_fc_replay_state.fc_regions = NULL; | 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 | sbi = ext4_alloc_sbi(sb); | 5541 | sbi = ext4_alloc_sbi(sb); |
| 5542 | if (!sbi) | 5542 | if (!sbi) |
| 5543 | ret = -ENOMEM; | 5543 | return -ENOMEM; |
| 5544 | 5544 | ||
| 5545 | fc->s_fs_info = sbi; | 5545 | fc->s_fs_info = sbi; |
| 5546 | 5546 | ||
| @@ -2408,7 +2408,7 @@ retry_inode: · 2407 unmodified lines | |||
| 2408 | if (IS_SYNC(inode)) | 2408 | if (IS_SYNC(inode)) |
| 2409 | ext4_handle_sync(handle); | 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 | cleanup: | 2413 | cleanup: |
| 2414 | brelse(is.iloc.bh); | 2414 | brelse(is.iloc.bh); |
| @@ -2486,7 +2486,7 @@ retry: · 71 unmodified lines | |||
| 2486 | if (error == 0) | 2486 | if (error == 0) |
| 2487 | error = error2; | 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 | return error; | 2491 | return error; |
| 2492 | } | 2492 | } |
| @@ -2920,7 +2920,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, · 427 unmodified lines | |||
| 2920 | error); | 2920 | error); |
| 2921 | goto cleanup; | 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 | error = 0; | 2925 | error = 0; |
| 2926 | cleanup: | 2926 | cleanup: |
| @@ -119,6 +119,8 @@ static struct ctl_table fs_stat_sysctls[] = { · 118 unmodified lines | |||
| 119 | static int __init init_fs_stat_sysctls(void) | 119 | static int __init init_fs_stat_sysctls(void) |
| 120 | { | 120 | { |
| 121 | register_sysctl_init("fs", fs_stat_sysctls); | 121 | register_sysctl_init("fs", fs_stat_sysctls); |
| 122 | if (IS_ENABLED(CONFIG_BINFMT_MISC)) | ||
| 123 | register_sysctl_mount_point("fs/binfmt_misc"); | ||
| 122 | return 0; | 124 | return 0; |
| 123 | } | 125 | } |
| 124 | fs_initcall(init_fs_stat_sysctls); | 126 | fs_initcall(init_fs_stat_sysctls); |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #include "../internal.h" | 22 | #include "../internal.h" |
| 23 | 23 | ||
| 24 | #define IOEND_BATCH_SIZE 4096 | ||
| 25 | |||
| 24 | /* | 26 | /* |
| 25 | * Structure allocated for each folio when block size < folio size | 27 | * Structure allocated for each folio when block size < folio size |
| 26 | * to track sub-folio uptodate status and I/O completions. | 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 | * state, release holds on bios, and finally free up memory. Do not use the | 1041 | * state, release holds on bios, and finally free up memory. Do not use the |
| 1040 | * ioend after this. | 1042 | * ioend after this. |
| 1041 | */ | 1043 | */ |
| 1042 | static void | 1044 | static u32 |
| 1043 | iomap_finish_ioend(struct iomap_ioend *ioend, int error) | 1045 | iomap_finish_ioend(struct iomap_ioend *ioend, int error) |
| 1044 | { | 1046 | { |
| 1045 | struct inode *inode = ioend->io_inode; | 1047 | struct inode *inode = ioend->io_inode; |
| @@ -1048,6 +1050,7 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error) · 2 unmodified lines | |||
| 1048 | u64 start = bio->bi_iter.bi_sector; | 1050 | u64 start = bio->bi_iter.bi_sector; |
| 1049 | loff_t offset = ioend->io_offset; | 1051 | loff_t offset = ioend->io_offset; |
| 1050 | bool quiet = bio_flagged(bio, BIO_QUIET); | 1052 | bool quiet = bio_flagged(bio, BIO_QUIET); |
| 1053 | u32 folio_count = 0; | ||
| 1051 | 1054 | ||
| 1052 | for (bio = &ioend->io_inline_bio; bio; bio = next) { | 1055 | for (bio = &ioend->io_inline_bio; bio; bio = next) { |
| 1053 | struct folio_iter fi; | 1056 | struct folio_iter fi; |
| @@ -1062,9 +1065,11 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error) · 8 unmodified lines | |||
| 1062 | next = bio->bi_private; | 1065 | next = bio->bi_private; |
| 1063 | 1066 | ||
| 1064 | /* walk all folios in bio, ending page IO on them */ | 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 | iomap_finish_folio_write(inode, fi.folio, fi.length, | 1069 | iomap_finish_folio_write(inode, fi.folio, fi.length, |
| 1067 | error); | 1070 | error); |
| 1071 | folio_count++; | ||
| 1072 | } | ||
| 1068 | bio_put(bio); | 1073 | bio_put(bio); |
| 1069 | } | 1074 | } |
| 1070 | /* The ioend has been freed by bio_put() */ | 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 | "%s: writeback error on inode %lu, offset %lld, sector %llu", | 1079 | "%s: writeback error on inode %lu, offset %lld, sector %llu", |
| 1075 | inode->i_sb->s_id, inode->i_ino, offset, start); | 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 | void | 1093 | void |
| 1080 | iomap_finish_ioends(struct iomap_ioend *ioend, int error) | 1094 | iomap_finish_ioends(struct iomap_ioend *ioend, int error) |
| 1081 | { | 1095 | { |
| 1082 | struct list_head tmp; | 1096 | struct list_head tmp; |
| 1097 | u32 completions; | ||
| 1098 | |||
| 1099 | might_sleep(); | ||
| 1083 | 1100 | ||
| 1084 | list_replace_init(&ioend->io_list, &tmp); | 1101 | list_replace_init(&ioend->io_list, &tmp); |
| 1085 | iomap_finish_ioend(ioend, error); | 1102 | completions = iomap_finish_ioend(ioend, error); |
| 1086 | 1103 | ||
| 1087 | while (!list_empty(&tmp)) { | 1104 | while (!list_empty(&tmp)) { |
| 1105 | if (completions > IOEND_BATCH_SIZE * 8) { | ||
| 1106 | cond_resched(); | ||
| 1107 | completions = 0; | ||
| 1108 | } | ||
| 1088 | ioend = list_first_entry(&tmp, struct iomap_ioend, io_list); | 1109 | ioend = list_first_entry(&tmp, struct iomap_ioend, io_list); |
| 1089 | list_del_init(&ioend->io_list); | 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 | EXPORT_SYMBOL_GPL(iomap_finish_ioends); | 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 | return false; | 1129 | return false; |
| 1109 | if (ioend->io_offset + ioend->io_size != next->io_offset) | 1130 | if (ioend->io_offset + ioend->io_size != next->io_offset) |
| 1110 | return false; | 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 | return true; | 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 | ioend->io_flags = wpc->iomap.flags; | 1242 | ioend->io_flags = wpc->iomap.flags; |
| 1210 | ioend->io_inode = inode; | 1243 | ioend->io_inode = inode; |
| 1211 | ioend->io_size = 0; | 1244 | ioend->io_size = 0; |
| 1245 | ioend->io_folios = 0; | ||
| 1212 | ioend->io_offset = offset; | 1246 | ioend->io_offset = offset; |
| 1213 | ioend->io_bio = bio; | 1247 | ioend->io_bio = bio; |
| 1248 | ioend->io_sector = sector; | ||
| 1214 | return ioend; | 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 | return false; | 1286 | return false; |
| 1252 | if (sector != bio_end_sector(wpc->ioend->io_bio)) | 1287 | if (sector != bio_end_sector(wpc->ioend->io_bio)) |
| 1253 | return false; | 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 | return true; | 1296 | return true; |
| 1255 | } | 1297 | } |
| 1256 | 1298 | ||
| @@ -1335,6 +1377,8 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc, · 78 unmodified lines | |||
| 1335 | &submit_list); | 1377 | &submit_list); |
| 1336 | count++; | 1378 | count++; |
| 1337 | } | 1379 | } |
| 1380 | if (count) | ||
| 1381 | wpc->ioend->io_folios++; | ||
| 1338 | 1382 | ||
| 1339 | WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list)); | 1383 | WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list)); |
| 1340 | WARN_ON_ONCE(!folio_test_locked(folio)); | 1384 | WARN_ON_ONCE(!folio_test_locked(folio)); |
| @@ -484,22 +484,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) · 483 unmodified lines | |||
| 484 | stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start, | 484 | stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start, |
| 485 | stats.run.rs_locked); | 485 | stats.run.rs_locked); |
| 486 | 486 | ||
| 487 | spin_lock(&commit_transaction->t_handle_lock); | 487 | // waits for any t_updates to finish |
| 488 | while (atomic_read(&commit_transaction->t_updates)) { | 488 | jbd2_journal_wait_updates(journal); |
| 489 | DEFINE_WAIT(wait); | ||
| 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 | commit_transaction->t_state = T_SWITCH; | 490 | commit_transaction->t_state = T_SWITCH; |
| 504 | write_unlock(&journal->j_state_lock); | 491 | write_unlock(&journal->j_state_lock); |
| 505 | 492 | ||
| @@ -817,7 +804,7 @@ start_journal_io: · 311 unmodified lines | |||
| 817 | commit_transaction->t_state = T_COMMIT_DFLUSH; | 804 | commit_transaction->t_state = T_COMMIT_DFLUSH; |
| 818 | write_unlock(&journal->j_state_lock); | 805 | write_unlock(&journal->j_state_lock); |
| 819 | 806 | ||
| 820 | /* | 807 | /* |
| 821 | * If the journal is not located on the file system device, | 808 | * If the journal is not located on the file system device, |
| 822 | * then we must flush the file system device before we issue | 809 | * then we must flush the file system device before we issue |
| 823 | * the commit record | 810 | * the commit record |
| @@ -1170,7 +1157,7 @@ restart_loop: · 346 unmodified lines | |||
| 1170 | if (journal->j_commit_callback) | 1157 | if (journal->j_commit_callback) |
| 1171 | journal->j_commit_callback(journal, commit_transaction); | 1158 | journal->j_commit_callback(journal, commit_transaction); |
| 1172 | if (journal->j_fc_cleanup_callback) | 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 | trace_jbd2_end_commit(journal, commit_transaction); | 1162 | trace_jbd2_end_commit(journal, commit_transaction); |
| 1176 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", | 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 | jbd2_journal_unlock_updates(journal); | 772 | jbd2_journal_unlock_updates(journal); |
| 773 | if (journal->j_fc_cleanup_callback) | 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 | write_lock(&journal->j_state_lock); | 775 | write_lock(&journal->j_state_lock); |
| 776 | journal->j_flags &= ~JBD2_FAST_COMMIT_ONGOING; | 776 | journal->j_flags &= ~JBD2_FAST_COMMIT_ONGOING; |
| 777 | if (fallback) | 777 | if (fallback) |
| @@ -1287,6 +1287,8 @@ static int jbd2_min_tag_size(void) · 509 unmodified lines | |||
| 1287 | 1287 | ||
| 1288 | /** | 1288 | /** |
| 1289 | * jbd2_journal_shrink_scan() | 1289 | * jbd2_journal_shrink_scan() |
| 1290 | * @shrink: shrinker to work on | ||
| 1291 | * @sc: reclaim request to process | ||
| 1290 | * | 1292 | * |
| 1291 | * Scan the checkpointed buffer on the checkpoint list and release the | 1293 | * Scan the checkpointed buffer on the checkpoint list and release the |
| 1292 | * journal_head. | 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 | * jbd2_journal_shrink_count() | 1316 | * jbd2_journal_shrink_count() |
| 1317 | * @shrink: shrinker to work on | ||
| 1318 | * @sc: reclaim request to process | ||
| 1315 | * | 1319 | * |
| 1316 | * Count the number of checkpoint buffers on the checkpoint list. | 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 | /* OK, account for the buffers that this operation expects to | 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 | update_t_max_wait(transaction, ts); | 454 | update_t_max_wait(transaction, ts); |
| 455 | handle->h_transaction = transaction; | 455 | handle->h_transaction = transaction; |
| @@ -836,6 +836,35 @@ int jbd2_journal_restart(handle_t *handle, int nblocks) · 380 unmodified lines | |||
| 836 | } | 836 | } |
| 837 | EXPORT_SYMBOL(jbd2_journal_restart); | 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 | * jbd2_journal_lock_updates () - establish a transaction barrier. | 869 | * jbd2_journal_lock_updates () - establish a transaction barrier. |
| 841 | * @journal: Journal to establish a barrier on. | 870 | * @journal: Journal to establish a barrier on. |
| @@ -863,27 +892,9 @@ void jbd2_journal_lock_updates(journal_t *journal) · 21 unmodified lines | |||
| 863 | write_lock(&journal->j_state_lock); | 892 | write_lock(&journal->j_state_lock); |
| 864 | } | 893 | } |
| 865 | 894 | ||
| 866 | /* Wait until there are no running updates */ | 895 | /* Wait until there are no running t_updates */ |
| 867 | while (1) { | 896 | jbd2_journal_wait_updates(journal); |
| 868 | transaction_t *transaction = journal->j_running_transaction; | ||
| 869 | |||
| 870 | if (!transaction) | ||
| 871 | break; | ||
| 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 | write_unlock(&journal->j_state_lock); | 898 | write_unlock(&journal->j_state_lock); |
| 888 | 899 | ||
| 889 | /* | 900 | /* |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | |||
| 29 | #include "mgmt/user_config.h" | 29 | #include "mgmt/user_config.h" |
| 30 | #include "crypto_ctx.h" | 30 | #include "crypto_ctx.h" |
| 31 | #include "transport_ipc.h" | 31 | #include "transport_ipc.h" |
| 32 | #include "../smbfs_common/arc4.h" | ||
| 32 | 33 | ||
| 33 | /* | 34 | /* |
| 34 | * Fixed format data defining GSS header and fixed string | 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 | nt_len - CIFS_ENCPWD_SIZE, | 337 | nt_len - CIFS_ENCPWD_SIZE, |
| 337 | domain_name, conn->ntlmssp.cryptkey); | 338 | domain_name, conn->ntlmssp.cryptkey); |
| 338 | kfree(domain_name); | 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 | return ret; | 363 | return ret; |
| 340 | } | 364 | } |
| 341 | 365 | ||
| @@ -408,6 +432,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, · 66 unmodified lines | |||
| 408 | (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) | 432 | (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) |
| 409 | flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 433 | flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
| 410 | 434 | ||
| 435 | if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH) | ||
| 436 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | ||
| 437 | |||
| 411 | chgblob->NegotiateFlags = cpu_to_le32(flags); | 438 | chgblob->NegotiateFlags = cpu_to_le32(flags); |
| 412 | len = strlen(ksmbd_netbios_name()); | 439 | len = strlen(ksmbd_netbios_name()); |
| 413 | name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL); | 440 | name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL); |
| @@ -2688,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work) · 2687 unmodified lines | |||
| 2688 | (struct create_posix *)context; | 2688 | (struct create_posix *)context; |
| 2689 | if (le16_to_cpu(context->DataOffset) + | 2689 | if (le16_to_cpu(context->DataOffset) + |
| 2690 | le32_to_cpu(context->DataLength) < | 2690 | le32_to_cpu(context->DataLength) < |
| 2691 | sizeof(struct create_posix)) { | 2691 | sizeof(struct create_posix) - 4) { |
| 2692 | rc = -EINVAL; | 2692 | rc = -EINVAL; |
| 2693 | goto err_out1; | 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 | goto free_conv_name; | 3422 | goto free_conv_name; |
| 3423 | } | 3423 | } |
| 3424 | 3424 | ||
| 3425 | struct_sz = readdir_info_level_struct_sz(info_level); | 3425 | struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len; |
| 3426 | next_entry_offset = ALIGN(struct_sz - 1 + conv_len, | 3426 | next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT); |
| 3427 | KSMBD_DIR_INFO_ALIGNMENT); | 3427 | d_info->last_entry_off_align = next_entry_offset - struct_sz; |
| 3428 | 3428 | ||
| 3429 | if (next_entry_offset > d_info->out_buf_len) { | 3429 | if (next_entry_offset > d_info->out_buf_len) { |
| 3430 | d_info->out_buf_len = 0; | 3430 | d_info->out_buf_len = 0; |
| @@ -3976,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work) · 545 unmodified lines | |||
| 3976 | ((struct file_directory_info *) | 3976 | ((struct file_directory_info *) |
| 3977 | ((char *)rsp->Buffer + d_info.last_entry_offset)) | 3977 | ((char *)rsp->Buffer + d_info.last_entry_offset)) |
| 3978 | ->NextEntryOffset = 0; | 3978 | ->NextEntryOffset = 0; |
| 3979 | d_info.data_count -= d_info.last_entry_off_align; | ||
| 3979 | 3980 | ||
| 3980 | rsp->StructureSize = cpu_to_le16(9); | 3981 | rsp->StructureSize = cpu_to_le16(9); |
| 3981 | rsp->OutputBufferOffset = cpu_to_le16(72); | 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 | __le16 ChannelInfoOffset, | 6127 | __le16 ChannelInfoOffset, |
| 6127 | __le16 ChannelInfoLength) | 6128 | __le16 ChannelInfoLength) |
| 6128 | { | 6129 | { |
| 6130 | unsigned int i, ch_count; | ||
| 6131 | |||
| 6129 | if (work->conn->dialect == SMB30_PROT_ID && | 6132 | if (work->conn->dialect == SMB30_PROT_ID && |
| 6130 | Channel != SMB2_CHANNEL_RDMA_V1) | 6133 | Channel != SMB2_CHANNEL_RDMA_V1) |
| 6131 | return -EINVAL; | 6134 | return -EINVAL; |
| 6132 | 6135 | ||
| 6133 | if (ChannelInfoOffset == 0 || | 6136 | ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc); |
| 6134 | 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 | return -EINVAL; | 6148 | return -EINVAL; |
| 6149 | } | ||
| 6136 | 6150 | ||
| 6137 | work->need_invalidate_rkey = | 6151 | work->need_invalidate_rkey = |
| 6138 | (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); | 6152 | (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); |
| @@ -6185,9 +6199,15 @@ int smb2_read(struct ksmbd_work *work) · 46 unmodified lines | |||
| 6185 | 6199 | ||
| 6186 | if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || | 6200 | if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || |
| 6187 | req->Channel == SMB2_CHANNEL_RDMA_V1) { | 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 | err = smb2_set_remote_key_for_rdma(work, | 6208 | err = smb2_set_remote_key_for_rdma(work, |
| 6189 | (struct smb2_buffer_desc_v1 *) | 6209 | (struct smb2_buffer_desc_v1 *) |
| 6190 | &req->Buffer[0], | 6210 | ((char *)req + ch_offset), |
| 6191 | req->Channel, | 6211 | req->Channel, |
| 6192 | req->ReadChannelInfoOffset, | 6212 | req->ReadChannelInfoOffset, |
| 6193 | req->ReadChannelInfoLength); | 6213 | req->ReadChannelInfoLength); |
| @@ -6428,11 +6448,16 @@ int smb2_write(struct ksmbd_work *work) · 234 unmodified lines | |||
| 6428 | 6448 | ||
| 6429 | if (req->Channel == SMB2_CHANNEL_RDMA_V1 || | 6449 | if (req->Channel == SMB2_CHANNEL_RDMA_V1 || |
| 6430 | req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { | 6450 | req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { |
| 6431 | if (req->Length != 0 || req->DataOffset != 0) | 6451 | unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset); |
| 6432 | return -EINVAL; | 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 | err = smb2_set_remote_key_for_rdma(work, | 6458 | err = smb2_set_remote_key_for_rdma(work, |
| 6434 | (struct smb2_buffer_desc_v1 *) | 6459 | (struct smb2_buffer_desc_v1 *) |
| 6435 | &req->Buffer[0], | 6460 | ((char *)req + ch_offset), |
| 6436 | req->Channel, | 6461 | req->Channel, |
| 6437 | req->WriteChannelInfoOffset, | 6462 | req->WriteChannelInfoOffset, |
| 6438 | req->WriteChannelInfoLength); | 6463 | req->WriteChannelInfoLength); |
| @@ -308,14 +308,17 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, · 307 unmodified lines | |||
| 308 | for (i = 0; i < 2; i++) { | 308 | for (i = 0; i < 2; i++) { |
| 309 | struct kstat kstat; | 309 | struct kstat kstat; |
| 310 | struct ksmbd_kstat ksmbd_kstat; | 310 | struct ksmbd_kstat ksmbd_kstat; |
| 311 | struct dentry *dentry; | ||
| 311 | 312 | ||
| 312 | if (!dir->dot_dotdot[i]) { /* fill dot entry info */ | 313 | if (!dir->dot_dotdot[i]) { /* fill dot entry info */ |
| 313 | if (i == 0) { | 314 | if (i == 0) { |
| 314 | d_info->name = "."; | 315 | d_info->name = "."; |
| 315 | d_info->name_len = 1; | 316 | d_info->name_len = 1; |
| 317 | dentry = dir->filp->f_path.dentry; | ||
| 316 | } else { | 318 | } else { |
| 317 | d_info->name = ".."; | 319 | d_info->name = ".."; |
| 318 | d_info->name_len = 2; | 320 | d_info->name_len = 2; |
| 321 | dentry = dir->filp->f_path.dentry->d_parent; | ||
| 319 | } | 322 | } |
| 320 | 323 | ||
| 321 | if (!match_pattern(d_info->name, d_info->name_len, | 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 | ksmbd_kstat.kstat = &kstat; | 330 | ksmbd_kstat.kstat = &kstat; |
| 328 | ksmbd_vfs_fill_dentry_attrs(work, | 331 | ksmbd_vfs_fill_dentry_attrs(work, |
| 329 | user_ns, | 332 | user_ns, |
| 330 | dir->filp->f_path.dentry->d_parent, | 333 | dentry, |
| 331 | &ksmbd_kstat); | 334 | &ksmbd_kstat); |
| 332 | rc = fn(conn, info_level, d_info, &ksmbd_kstat); | 335 | rc = fn(conn, info_level, d_info, &ksmbd_kstat); |
| 333 | if (rc) | 336 | if (rc) |
| @@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024; · 79 unmodified lines | |||
| 80 | /* The maximum single-message size which can be received */ | 80 | /* The maximum single-message size which can be received */ |
| 81 | static int smb_direct_max_receive_size = 8192; | 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 | static int smb_direct_max_outstanding_rw_ops = 8; | 85 | static int smb_direct_max_outstanding_rw_ops = 8; |
| 86 | 86 | ||
| @@ -47,6 +47,7 @@ struct ksmbd_dir_info { · 46 unmodified lines | |||
| 47 | int last_entry_offset; | 47 | int last_entry_offset; |
| 48 | bool hide_dot_file; | 48 | bool hide_dot_file; |
| 49 | int flags; | 49 | int flags; |
| 50 | int last_entry_off_align; | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | struct ksmbd_readdir_data { | 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 | INIT_LIST_HEAD(&clp->cl_superblocks); | 177 | INIT_LIST_HEAD(&clp->cl_superblocks); |
| 178 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | 178 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
| 179 | 179 | ||
| 180 | clp->cl_flags = cl_init->init_flags; | ||
| 180 | clp->cl_proto = cl_init->proto; | 181 | clp->cl_proto = cl_init->proto; |
| 181 | clp->cl_nconnect = cl_init->nconnect; | 182 | clp->cl_nconnect = cl_init->nconnect; |
| 182 | clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1; | 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 | list_add_tail(&new->cl_share_link, | 424 | list_add_tail(&new->cl_share_link, |
| 424 | &nn->nfs_client_list); | 425 | &nn->nfs_client_list); |
| 425 | spin_unlock(&nn->nfs_client_lock); | 426 | spin_unlock(&nn->nfs_client_lock); |
| 426 | new->cl_flags = cl_init->init_flags; | ||
| 427 | return rpc_ops->init_client(new, cl_init); | 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 | ctx->dir_cookie = 0; | 80 | ctx->dir_cookie = 0; |
| 81 | ctx->dup_cookie = 0; | 81 | ctx->dup_cookie = 0; |
| 82 | ctx->page_index = 0; | 82 | ctx->page_index = 0; |
| 83 | ctx->eof = false; | ||
| 83 | spin_lock(&dir->i_lock); | 84 | spin_lock(&dir->i_lock); |
| 84 | if (list_empty(&nfsi->open_files) && | 85 | if (list_empty(&nfsi->open_files) && |
| 85 | (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) | 86 | (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) |
| @@ -168,6 +169,7 @@ struct nfs_readdir_descriptor { · 82 unmodified lines | |||
| 168 | unsigned int cache_entry_index; | 169 | unsigned int cache_entry_index; |
| 169 | signed char duped; | 170 | signed char duped; |
| 170 | bool plus; | 171 | bool plus; |
| 172 | bool eob; | ||
| 171 | bool eof; | 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 | status = nfs_readdir_page_filler(desc, entry, pages, pglen, | 870 | status = nfs_readdir_page_filler(desc, entry, pages, pglen, |
| 869 | arrays, narrays); | 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 | nfs_readdir_free_pages(pages, array_size); | 875 | nfs_readdir_free_pages(pages, array_size); |
| 873 | out: | 876 | out: |
| @@ -988,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, · 114 unmodified lines | |||
| 988 | ent = &array->array[i]; | 991 | ent = &array->array[i]; |
| 989 | if (!dir_emit(desc->ctx, ent->name, ent->name_len, | 992 | if (!dir_emit(desc->ctx, ent->name, ent->name_len, |
| 990 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { | 993 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { |
| 991 | desc->eof = true; | 994 | desc->eob = true; |
| 992 | break; | 995 | break; |
| 993 | } | 996 | } |
| 994 | memcpy(desc->verf, verf, sizeof(desc->verf)); | 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 | desc->duped = 1; | 1007 | desc->duped = 1; |
| 1005 | } | 1008 | } |
| 1006 | if (array->page_is_eof) | 1009 | if (array->page_is_eof) |
| 1007 | desc->eof = true; | 1010 | desc->eof = !desc->eob; |
| 1008 | 1011 | ||
| 1009 | kunmap(desc->page); | 1012 | kunmap(desc->page); |
| 1010 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n", | 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 | goto out; | 1044 | goto out; |
| 1042 | 1045 | ||
| 1043 | desc->page_index = 0; | 1046 | desc->page_index = 0; |
| 1047 | desc->cache_entry_index = 0; | ||
| 1044 | desc->last_cookie = desc->dir_cookie; | 1048 | desc->last_cookie = desc->dir_cookie; |
| 1045 | desc->duped = 0; | 1049 | desc->duped = 0; |
| 1046 | 1050 | ||
| 1047 | status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz); | 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 | desc->page = arrays[i]; | 1054 | desc->page = arrays[i]; |
| 1051 | nfs_do_filldir(desc, verf); | 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 | desc->duped = dir_ctx->duped; | 1109 | desc->duped = dir_ctx->duped; |
| 1106 | page_index = dir_ctx->page_index; | 1110 | page_index = dir_ctx->page_index; |
| 1107 | desc->attr_gencount = dir_ctx->attr_gencount; | 1111 | desc->attr_gencount = dir_ctx->attr_gencount; |
| 1112 | desc->eof = dir_ctx->eof; | ||
| 1108 | memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf)); | 1113 | memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf)); |
| 1109 | spin_unlock(&file->f_lock); | 1114 | spin_unlock(&file->f_lock); |
| 1110 | 1115 | ||
| 1116 | if (desc->eof) { | ||
| 1117 | res = 0; | ||
| 1118 | goto out_free; | ||
| 1119 | } | ||
| 1120 | |||
| 1111 | if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) && | 1121 | if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) && |
| 1112 | list_is_singular(&nfsi->open_files)) | 1122 | list_is_singular(&nfsi->open_files)) |
| 1113 | invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1); | 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 | nfs_do_filldir(desc, nfsi->cookieverf); | 1152 | nfs_do_filldir(desc, nfsi->cookieverf); |
| 1143 | nfs_readdir_page_unlock_and_put_cached(desc); | 1153 | nfs_readdir_page_unlock_and_put_cached(desc); |
| 1144 | } while (!desc->eof); | 1154 | } while (!desc->eob && !desc->eof); |
| 1145 | 1155 | ||
| 1146 | spin_lock(&file->f_lock); | 1156 | spin_lock(&file->f_lock); |
| 1147 | dir_ctx->dir_cookie = desc->dir_cookie; | 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 | dir_ctx->duped = desc->duped; | 1159 | dir_ctx->duped = desc->duped; |
| 1150 | dir_ctx->attr_gencount = desc->attr_gencount; | 1160 | dir_ctx->attr_gencount = desc->attr_gencount; |
| 1151 | dir_ctx->page_index = desc->page_index; | 1161 | dir_ctx->page_index = desc->page_index; |
| 1162 | dir_ctx->eof = desc->eof; | ||
| 1152 | memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf)); | 1163 | memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf)); |
| 1153 | spin_unlock(&file->f_lock); | 1164 | spin_unlock(&file->f_lock); |
| 1154 | 1165 | out_free: | |
| 1155 | kfree(desc); | 1166 | kfree(desc); |
| 1156 | 1167 | ||
| 1157 | out: | 1168 | out: |
| @@ -1193,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) · 35 unmodified lines | |||
| 1193 | if (offset == 0) | 1204 | if (offset == 0) |
| 1194 | memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf)); | 1205 | memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf)); |
| 1195 | dir_ctx->duped = 0; | 1206 | dir_ctx->duped = 0; |
| 1207 | dir_ctx->eof = false; | ||
| 1196 | } | 1208 | } |
| 1197 | spin_unlock(&filp->f_lock); | 1209 | spin_unlock(&filp->f_lock); |
| 1198 | return offset; | 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 | * nfs4_proc_get_locations - discover locations for a migrated FSID | 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 | * @locations: result of query | 8037 | * @locations: result of query |
| 8037 | * @page: buffer | 8038 | * @page: buffer |
| 8038 | * @cred: credential to use for this operation | 8039 | * @cred: credential to use for this operation |
| @@ -150,13 +150,17 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 149 unmodified lines | |||
| 150 | unsigned int len; | 150 | unsigned int len; |
| 151 | int v; | 151 | int v; |
| 152 | 152 | ||
| 153 | argp->count = min_t(u32, argp->count, max_blocksize); | ||
| 154 | |||
| 155 | dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", | 153 | dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", |
| 156 | SVCFH_fmt(&argp->fh), | 154 | SVCFH_fmt(&argp->fh), |
| 157 | (unsigned long) argp->count, | 155 | (unsigned long) argp->count, |
| 158 | (unsigned long long) argp->offset); | 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 | v = 0; | 164 | v = 0; |
| 161 | len = argp->count; | 165 | len = argp->count; |
| 162 | resp->pages = rqstp->rq_next_page; | 166 | resp->pages = rqstp->rq_next_page; |
| @@ -199,6 +203,11 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 36 unmodified lines | |||
| 199 | (unsigned long long) argp->offset, | 203 | (unsigned long long) argp->offset, |
| 200 | argp->stable? " stable" : ""); | 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 | fh_copy(&resp->fh, &argp->fh); | 211 | fh_copy(&resp->fh, &argp->fh); |
| 203 | resp->committed = argp->stable; | 212 | resp->committed = argp->stable; |
| 204 | nvecs = svc_fill_write_vector(rqstp, &argp->payload); | 213 | nvecs = svc_fill_write_vector(rqstp, &argp->payload); |
| @@ -651,15 +660,9 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) · 446 unmodified lines | |||
| 651 | argp->count, | 660 | argp->count, |
| 652 | (unsigned long long) argp->offset); | 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 | fh_copy(&resp->fh, &argp->fh); | 663 | fh_copy(&resp->fh, &argp->fh); |
| 660 | resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset, | 664 | resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset, |
| 661 | argp->count, resp->verf); | 665 | argp->count, resp->verf); |
| 662 | out: | ||
| 663 | return rpc_success; | 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 | if (xdr_stream_decode_u64(xdr, &newsize) < 0) | 254 | if (xdr_stream_decode_u64(xdr, &newsize) < 0) |
| 255 | return false; | 255 | return false; |
| 256 | iap->ia_valid |= ATTR_SIZE; | 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 | if (xdr_stream_decode_u32(xdr, &set_it) < 0) | 259 | if (xdr_stream_decode_u32(xdr, &set_it) < 0) |
| 260 | return false; | 260 | return false; |
| @@ -1060,7 +1060,7 @@ svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name, · 799 unmodified lines | |||
| 1060 | return false; | 1060 | return false; |
| 1061 | /* cookie */ | 1061 | /* cookie */ |
| 1062 | resp->cookie_offset = dirlist->len; | 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 | return false; | 1064 | return false; |
| 1065 | 1065 | ||
| 1066 | return true; | 1066 | return true; |
| @@ -782,12 +782,16 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 781 unmodified lines | |||
| 782 | __be32 status; | 782 | __be32 status; |
| 783 | 783 | ||
| 784 | read->rd_nf = NULL; | 784 | read->rd_nf = NULL; |
| 785 | if (read->rd_offset >= OFFSET_MAX) | ||
| 786 | return nfserr_inval; | ||
| 787 | 785 | ||
| 788 | trace_nfsd_read_start(rqstp, &cstate->current_fh, | 786 | trace_nfsd_read_start(rqstp, &cstate->current_fh, |
| 789 | read->rd_offset, read->rd_length); | 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 | * If we do a zero copy read, then a client will see read data | 796 | * If we do a zero copy read, then a client will see read data |
| 793 | * that reflects the state of the file *after* performing the | 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 | unsigned long cnt; | 1022 | unsigned long cnt; |
| 1019 | int nvecs; | 1023 | int nvecs; |
| 1020 | 1024 | ||
| 1021 | if (write->wr_offset >= OFFSET_MAX) | 1025 | if (write->wr_offset > (u64)OFFSET_MAX || |
| 1022 | return nfserr_inval; | 1026 | write->wr_offset + write->wr_buflen > (u64)OFFSET_MAX) |
| 1027 | return nfserr_fbig; | ||
| 1023 | 1028 | ||
| 1024 | cnt = write->wr_buflen; | 1029 | cnt = write->wr_buflen; |
| 1025 | trace_nfsd_write_start(rqstp, &cstate->current_fh, | 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 | p = xdr_reserve_space(xdr, 3*4 + namlen); | 3495 | p = xdr_reserve_space(xdr, 3*4 + namlen); |
| 3496 | if (!p) | 3496 | if (!p) |
| 3497 | goto fail; | 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 | p = xdr_encode_array(p, name, namlen); /* name length & name */ | 3499 | p = xdr_encode_array(p, name, namlen); /* name length & name */ |
| 3500 | 3500 | ||
| 3501 | nfserr = nfsd4_encode_dirent_fattr(xdr, cd, name, namlen); | 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 | xdr_commit_encode(xdr); | 3987 | xdr_commit_encode(xdr); |
| 3988 | 3988 | ||
| 3989 | maxcount = svc_max_payload(resp->rqstp); | 3989 | maxcount = min_t(unsigned long, read->rd_length, |
| 3990 | maxcount = min_t(unsigned long, maxcount, | ||
| 3991 | (xdr->buf->buflen - xdr->buf->len)); | 3990 | (xdr->buf->buflen - xdr->buf->len)); |
| 3992 | maxcount = min_t(unsigned long, maxcount, read->rd_length); | ||
| 3993 | 3991 | ||
| 3994 | if (file->f_op->splice_read && | 3992 | if (file->f_op->splice_read && |
| 3995 | test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) | 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 | return nfserr_resource; | 4824 | return nfserr_resource; |
| 4827 | xdr_commit_encode(xdr); | 4825 | xdr_commit_encode(xdr); |
| 4828 | 4826 | ||
| 4829 | maxcount = svc_max_payload(resp->rqstp); | 4827 | maxcount = min_t(unsigned long, read->rd_length, |
| 4830 | maxcount = min_t(unsigned long, maxcount, | ||
| 4831 | (xdr->buf->buflen - xdr->buf->len)); | 4828 | (xdr->buf->buflen - xdr->buf->len)); |
| 4832 | maxcount = min_t(unsigned long, maxcount, read->rd_length); | ||
| 4833 | count = maxcount; | 4829 | count = maxcount; |
| 4834 | 4830 | ||
| 4835 | eof = read->rd_offset >= i_size_read(file_inode(file)); | 4831 | eof = read->rd_offset >= i_size_read(file_inode(file)); |
| @@ -306,14 +306,14 @@ TRACE_EVENT(nfsd_export_update, · 305 unmodified lines | |||
| 306 | DECLARE_EVENT_CLASS(nfsd_io_class, | 306 | DECLARE_EVENT_CLASS(nfsd_io_class, |
| 307 | TP_PROTO(struct svc_rqst *rqstp, | 307 | TP_PROTO(struct svc_rqst *rqstp, |
| 308 | struct svc_fh *fhp, | 308 | struct svc_fh *fhp, |
| 309 | loff_t offset, | 309 | u64 offset, |
| 310 | unsigned long len), | 310 | u32 len), |
| 311 | TP_ARGS(rqstp, fhp, offset, len), | 311 | TP_ARGS(rqstp, fhp, offset, len), |
| 312 | TP_STRUCT__entry( | 312 | TP_STRUCT__entry( |
| 313 | __field(u32, xid) | 313 | __field(u32, xid) |
| 314 | __field(u32, fh_hash) | 314 | __field(u32, fh_hash) |
| 315 | __field(loff_t, offset) | 315 | __field(u64, offset) |
| 316 | __field(unsigned long, len) | 316 | __field(u32, len) |
| 317 | ), | 317 | ), |
| 318 | TP_fast_assign( | 318 | TP_fast_assign( |
| 319 | __entry->xid = be32_to_cpu(rqstp->rq_xid); | 319 | __entry->xid = be32_to_cpu(rqstp->rq_xid); |
| @@ -321,7 +321,7 @@ DECLARE_EVENT_CLASS(nfsd_io_class, · 1 unmodified line | |||
| 321 | __entry->offset = offset; | 321 | __entry->offset = offset; |
| 322 | __entry->len = len; | 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 | __entry->xid, __entry->fh_hash, | 325 | __entry->xid, __entry->fh_hash, |
| 326 | __entry->offset, __entry->len) | 326 | __entry->offset, __entry->len) |
| 327 | ) | 327 | ) |
| @@ -330,8 +330,8 @@ DECLARE_EVENT_CLASS(nfsd_io_class, · 2 unmodified lines | |||
| 330 | DEFINE_EVENT(nfsd_io_class, nfsd_##name, \ | 330 | DEFINE_EVENT(nfsd_io_class, nfsd_##name, \ |
| 331 | TP_PROTO(struct svc_rqst *rqstp, \ | 331 | TP_PROTO(struct svc_rqst *rqstp, \ |
| 332 | struct svc_fh *fhp, \ | 332 | struct svc_fh *fhp, \ |
| 333 | loff_t offset, \ | 333 | u64 offset, \ |
| 334 | unsigned long len), \ | 334 | u32 len), \ |
| 335 | TP_ARGS(rqstp, fhp, offset, len)) | 335 | TP_ARGS(rqstp, fhp, offset, len)) |
| 336 | 336 | ||
| 337 | DEFINE_NFSD_IO_EVENT(read_start); | 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 | .ia_size = iap->ia_size, | 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 | host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL); | 442 | host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL); |
| 439 | if (host_err) | 443 | if (host_err) |
| 440 | goto out_unlock; | 444 | goto out_unlock; |
| @@ -1110,42 +1114,61 @@ out: · 669 unmodified lines | |||
| 1110 | } | 1114 | } |
| 1111 | 1115 | ||
| 1112 | #ifdef CONFIG_NFSD_V3 | 1116 | #ifdef CONFIG_NFSD_V3 |
| 1113 | /* | 1117 | /** |
| 1114 | * Commit all pending writes to stable storage. | 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 | 1125 | * Note: we guarantee that data that lies within the range specified |
| 1117 | * by the 'offset' and 'count' parameters will be synced. | 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 | * Unfortunately we cannot lock the file to make sure we return full WCC | 1130 | * Unfortunately we cannot lock the file to make sure we return full WCC |
| 1120 | * data to the client, as locking happens lower down in the filesystem. | 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 | __be32 | 1136 | __be32 |
| 1123 | nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1137 | nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset, |
| 1124 | loff_t offset, unsigned long count, __be32 *verf) | 1138 | u32 count, __be32 *verf) |
| 1125 | { | 1139 | { |
| 1140 | u64 maxbytes; | ||
| 1141 | loff_t start, end; | ||
| 1126 | struct nfsd_net *nn; | 1142 | struct nfsd_net *nn; |
| 1127 | struct nfsd_file *nf; | 1143 | struct nfsd_file *nf; |
| 1128 | loff_t end = LLONG_MAX; | 1144 | __be32 err; |
| 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 | } | ||
| 1138 | 1145 | ||
| 1139 | err = nfsd_file_acquire(rqstp, fhp, | 1146 | err = nfsd_file_acquire(rqstp, fhp, |
| 1140 | NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf); | 1147 | NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf); |
| 1141 | if (err) | 1148 | if (err) |
| 1142 | goto out; | 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 | nn = net_generic(nf->nf_net, nfsd_net_id); | 1166 | nn = net_generic(nf->nf_net, nfsd_net_id); |
| 1144 | if (EX_ISSYNC(fhp->fh_export)) { | 1167 | if (EX_ISSYNC(fhp->fh_export)) { |
| 1145 | errseq_t since = READ_ONCE(nf->nf_file->f_wb_err); | 1168 | errseq_t since = READ_ONCE(nf->nf_file->f_wb_err); |
| 1146 | int err2; | 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 | switch (err2) { | 1172 | switch (err2) { |
| 1150 | case 0: | 1173 | case 0: |
| 1151 | nfsd_copy_write_verifier(verf, nn); | 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 | char *name, int len, struct iattr *attrs, | 74 | char *name, int len, struct iattr *attrs, |
| 75 | struct svc_fh *res, int createmode, | 75 | struct svc_fh *res, int createmode, |
| 76 | u32 *verifier, bool *truncp, bool *created); | 76 | u32 *verifier, bool *truncp, bool *created); |
| 77 | __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, | 77 | __be32 nfsd_commit(struct svc_rqst *rqst, struct svc_fh *fhp, |
| 78 | loff_t, unsigned long, __be32 *verf); | 78 | u64 offset, u32 count, __be32 *verf); |
| 79 | #endif /* CONFIG_NFSD_V3 */ | 79 | #endif /* CONFIG_NFSD_V3 */ |
| 80 | #ifdef CONFIG_NFSD_V4 | 80 | #ifdef CONFIG_NFSD_V4 |
| 81 | __be32 nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, | 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 | /* This is not very clever (and fast) but currently I don't know about | 690 | /* This is not very clever (and fast) but currently I don't know about |
| 691 | * any other simple way of getting quota data to disk and we must get | 691 | * any other simple way of getting quota data to disk and we must get |
| 692 | * them there for userspace to be visible... */ | 692 | * them there for userspace to be visible... */ |
| 693 | if (sb->s_op->sync_fs) | 693 | if (sb->s_op->sync_fs) { |
| 694 | sb->s_op->sync_fs(sb, 1); | 694 | ret = sb->s_op->sync_fs(sb, 1); |
| 695 | sync_blockdev(sb->s_bdev); | 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 | * Now when everything is written we can discard the pagecache so | 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 | percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_); | 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; | 1621 | for (level--; level >= 0; level--) |
| 1622 | |||
| 1623 | for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) | ||
| 1624 | percpu_up_write(sb->s_writers.rw_sem + level); | 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 | sb_wait_write(sb, SB_FREEZE_PAGEFAULT); | 1689 | sb_wait_write(sb, SB_FREEZE_PAGEFAULT); |
| 1692 | 1690 | ||
| 1693 | /* All writers are done so after syncing there won't be dirty data */ | 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 | /* Now wait for internal filesystem counter */ | 1701 | /* Now wait for internal filesystem counter */ |
| 1697 | sb->s_writers.frozen = SB_FREEZE_FS; | 1702 | sb->s_writers.frozen = SB_FREEZE_FS; |
| @@ -1703,7 +1708,7 @@ int freeze_super(struct super_block *sb) · 5 unmodified lines | |||
| 1703 | printk(KERN_ERR | 1708 | printk(KERN_ERR |
| 1704 | "VFS:Filesystem freeze failed\n"); | 1709 | "VFS:Filesystem freeze failed\n"); |
| 1705 | sb->s_writers.frozen = SB_UNFROZEN; | 1710 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1706 | sb_freeze_unlock(sb); | 1711 | sb_freeze_unlock(sb, SB_FREEZE_FS); |
| 1707 | wake_up(&sb->s_writers.wait_unfrozen); | 1712 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1708 | deactivate_locked_super(sb); | 1713 | deactivate_locked_super(sb); |
| 1709 | return ret; | 1714 | return ret; |
| @@ -1748,7 +1753,7 @@ static int thaw_super_locked(struct super_block *sb) · 38 unmodified lines | |||
| 1748 | } | 1753 | } |
| 1749 | 1754 | ||
| 1750 | sb->s_writers.frozen = SB_UNFROZEN; | 1755 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1751 | sb_freeze_unlock(sb); | 1756 | sb_freeze_unlock(sb, SB_FREEZE_FS); |
| 1752 | out: | 1757 | out: |
| 1753 | wake_up(&sb->s_writers.wait_unfrozen); | 1758 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1754 | deactivate_locked_super(sb); | 1759 | deactivate_locked_super(sb); |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | |||
| 29 | */ | 29 | */ |
| 30 | int sync_filesystem(struct super_block *sb) | 30 | int sync_filesystem(struct super_block *sb) |
| 31 | { | 31 | { |
| 32 | int ret; | 32 | int ret = 0; |
| 33 | 33 | ||
| 34 | /* | 34 | /* |
| 35 | * We need to be protected against the filesystem going from | 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 | * at a time. | 52 | * at a time. |
| 53 | */ | 53 | */ |
| 54 | writeback_inodes_sb(sb, WB_REASON_SYNC); | 54 | writeback_inodes_sb(sb, WB_REASON_SYNC); |
| 55 | if (sb->s_op->sync_fs) | 55 | if (sb->s_op->sync_fs) { |
| 56 | sb->s_op->sync_fs(sb, 0); | 56 | ret = sb->s_op->sync_fs(sb, 0); |
| 57 | if (ret) | ||
| 58 | return ret; | ||
| 59 | } | ||
| 57 | ret = sync_blockdev_nowait(sb->s_bdev); | 60 | ret = sync_blockdev_nowait(sb->s_bdev); |
| 58 | if (ret < 0) | 61 | if (ret) |
| 59 | return ret; | 62 | return ret; |
| 60 | 63 | ||
| 61 | sync_inodes_sb(sb); | 64 | sync_inodes_sb(sb); |
| 62 | if (sb->s_op->sync_fs) | 65 | if (sb->s_op->sync_fs) { |
| 63 | sb->s_op->sync_fs(sb, 1); | 66 | ret = sb->s_op->sync_fs(sb, 1); |
| 67 | if (ret) | ||
| 68 | return ret; | ||
| 69 | } | ||
| 64 | return sync_blockdev(sb->s_bdev); | 70 | return sync_blockdev(sb->s_bdev); |
| 65 | } | 71 | } |
| 66 | EXPORT_SYMBOL(sync_filesystem); | 72 | EXPORT_SYMBOL(sync_filesystem); |
| @@ -136,7 +136,20 @@ done: · 135 unmodified lines | |||
| 136 | memalloc_nofs_restore(nofs_flag); | 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 | void | 153 | void |
| 141 | xfs_end_io( | 154 | xfs_end_io( |
| 142 | struct work_struct *work) | 155 | struct work_struct *work) |
| @@ -157,6 +170,7 @@ xfs_end_io( · 14 unmodified lines | |||
| 157 | list_del_init(&ioend->io_list); | 170 | list_del_init(&ioend->io_list); |
| 158 | iomap_ioend_try_merge(ioend, &tmp); | 171 | iomap_ioend_try_merge(ioend, &tmp); |
| 159 | xfs_end_ioend(ioend); | 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 | rblocks = 0; | 850 | rblocks = 0; |
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | /* | ||
| 854 | * Allocate and setup the transaction. | ||
| 855 | */ | ||
| 856 | error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, | 853 | error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, |
| 857 | dblocks, rblocks, false, &tp); | 854 | dblocks, rblocks, false, &tp); |
| 858 | if (error) | 855 | if (error) |
| @@ -869,9 +866,9 @@ xfs_alloc_file_space( · 10 unmodified lines | |||
| 869 | if (error) | 866 | if (error) |
| 870 | goto error; | 867 | goto error; |
| 871 | 868 | ||
| 872 | /* | 869 | ip->i_diflags |= XFS_DIFLAG_PREALLOC; |
| 873 | * Complete the transaction | 870 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
| 874 | */ | 871 | |
| 875 | error = xfs_trans_commit(tp); | 872 | error = xfs_trans_commit(tp); |
| 876 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 873 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 877 | if (error) | 874 | if (error) |
| @@ -66,40 +66,6 @@ xfs_is_falloc_aligned( · 65 unmodified lines | |||
| 66 | return !((pos | len) & mask); | 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 | * Fsync operations on directories are much simpler than on regular files, | 70 | * Fsync operations on directories are much simpler than on regular files, |
| 105 | * as there is no file data to flush, and thus also no need for explicit | 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 | return error; | 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 | #define XFS_FALLOC_FL_SUPPORTED \ | 879 | #define XFS_FALLOC_FL_SUPPORTED \ |
| 899 | (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ | 880 | (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ |
| 900 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ | 881 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ |
| @@ -910,7 +891,6 @@ xfs_file_fallocate( · 9 unmodified lines | |||
| 910 | struct inode *inode = file_inode(file); | 891 | struct inode *inode = file_inode(file); |
| 911 | struct xfs_inode *ip = XFS_I(inode); | 892 | struct xfs_inode *ip = XFS_I(inode); |
| 912 | long error; | 893 | long error; |
| 913 | enum xfs_prealloc_flags flags = 0; | ||
| 914 | uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; | 894 | uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; |
| 915 | loff_t new_size = 0; | 895 | loff_t new_size = 0; |
| 916 | bool do_file_insert = false; | 896 | bool do_file_insert = false; |
| @@ -955,6 +935,10 @@ xfs_file_fallocate( · 38 unmodified lines | |||
| 955 | goto out_unlock; | 935 | goto out_unlock; |
| 956 | } | 936 | } |
| 957 | 937 | ||
| 938 | error = file_modified(file); | ||
| 939 | if (error) | ||
| 940 | goto out_unlock; | ||
| 941 | |||
| 958 | if (mode & FALLOC_FL_PUNCH_HOLE) { | 942 | if (mode & FALLOC_FL_PUNCH_HOLE) { |
| 959 | error = xfs_free_file_space(ip, offset, len); | 943 | error = xfs_free_file_space(ip, offset, len); |
| 960 | if (error) | 944 | if (error) |
| @@ -1004,8 +988,6 @@ xfs_file_fallocate( · 43 unmodified lines | |||
| 1004 | } | 988 | } |
| 1005 | do_file_insert = true; | 989 | do_file_insert = true; |
| 1006 | } else { | 990 | } else { |
| 1007 | flags |= XFS_PREALLOC_SET; | ||
| 1008 | |||
| 1009 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 991 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
| 1010 | offset + len > i_size_read(inode)) { | 992 | offset + len > i_size_read(inode)) { |
| 1011 | new_size = offset + len; | 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 | /* Change file size if needed */ | 1042 | /* Change file size if needed */ |
| 1068 | if (new_size) { | 1043 | if (new_size) { |
| 1069 | struct iattr iattr; | 1044 | struct iattr iattr; |
| @@ -1082,8 +1057,14 @@ xfs_file_fallocate( · 12 unmodified lines | |||
| 1082 | * leave shifted extents past EOF and hence losing access to | 1057 | * leave shifted extents past EOF and hence losing access to |
| 1083 | * the data that is contained within them. | 1058 | * the data that is contained within them. |
| 1084 | */ | 1059 | */ |
| 1085 | if (do_file_insert) | 1060 | if (do_file_insert) { |
| 1086 | error = xfs_insert_file_space(ip, offset, len); | 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 | out_unlock: | 1069 | out_unlock: |
| 1089 | xfs_iunlock(ip, iolock); | 1070 | xfs_iunlock(ip, iolock); |
| @@ -1115,21 +1096,6 @@ xfs_file_fadvise( · 25 unmodified lines | |||
| 1115 | return ret; | 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 | STATIC loff_t | 1099 | STATIC loff_t |
| 1134 | xfs_file_remap_range( | 1100 | xfs_file_remap_range( |
| 1135 | struct file *file_in, | 1101 | struct file *file_in, |
| @@ -462,15 +462,6 @@ xfs_itruncate_extents( · 461 unmodified lines | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | /* from xfs_file.c */ | 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 | int xfs_break_layouts(struct inode *inode, uint *iolock, | 465 | int xfs_break_layouts(struct inode *inode, uint *iolock, |
| 475 | enum layout_break_reason reason); | 466 | enum layout_break_reason reason); |
| 476 | 467 | ||
| @@ -1464,7 +1464,7 @@ xfs_ioc_getbmap( · 1463 unmodified lines | |||
| 1464 | 1464 | ||
| 1465 | if (bmx.bmv_count < 2) | 1465 | if (bmx.bmv_count < 2) |
| 1466 | return -EINVAL; | 1466 | return -EINVAL; |
| 1467 | if (bmx.bmv_count > ULONG_MAX / recsize) | 1467 | if (bmx.bmv_count >= INT_MAX / recsize) |
| 1468 | return -ENOMEM; | 1468 | return -ENOMEM; |
| 1469 | 1469 | ||
| 1470 | buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL); | 1470 | buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL); |
| @@ -70,6 +70,40 @@ xfs_fs_get_uuid( · 69 unmodified lines | |||
| 70 | return 0; | 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 | * Get a layout for the pNFS client. | 108 | * Get a layout for the pNFS client. |
| 75 | */ | 109 | */ |
| @@ -164,10 +198,12 @@ xfs_fs_map_blocks( · 88 unmodified lines | |||
| 164 | * that the blocks allocated and handed out to the client are | 198 | * that the blocks allocated and handed out to the client are |
| 165 | * guaranteed to be present even after a server crash. | 199 | * guaranteed to be present even after a server crash. |
| 166 | */ | 200 | */ |
| 167 | error = xfs_update_prealloc_flags(ip, | 201 | error = xfs_fs_map_update_inode(ip); |
| 168 | XFS_PREALLOC_SET | XFS_PREALLOC_SYNC); | 202 | if (!error) |
| 203 | error = xfs_log_force_inode(ip); | ||
| 169 | if (error) | 204 | if (error) |
| 170 | goto out_unlock; | 205 | goto out_unlock; |
| 206 | |||
| 171 | } else { | 207 | } else { |
| 172 | xfs_iunlock(ip, lock_flags); | 208 | xfs_iunlock(ip, lock_flags); |
| 173 | } | 209 | } |
| @@ -255,7 +291,7 @@ xfs_fs_commit_blocks( · 81 unmodified lines | |||
| 255 | length = end - start; | 291 | length = end - start; |
| 256 | if (!length) | 292 | if (!length) |
| 257 | continue; | 293 | continue; |
| 258 | 294 | ||
| 259 | /* | 295 | /* |
| 260 | * Make sure reads through the pagecache see the new data. | 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 | int wait) | 735 | int wait) |
| 736 | { | 736 | { |
| 737 | struct xfs_mount *mp = XFS_M(sb); | 737 | struct xfs_mount *mp = XFS_M(sb); |
| 738 | int error; | ||
| 738 | 739 | ||
| 739 | trace_xfs_fs_sync_fs(mp, __return_address); | 740 | trace_xfs_fs_sync_fs(mp, __return_address); |
| 740 | 741 | ||
| @@ -744,7 +745,10 @@ xfs_fs_sync_fs( · 3 unmodified lines | |||
| 744 | if (!wait) | 745 | if (!wait) |
| 745 | return 0; | 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 | if (laptop_mode) { | 752 | if (laptop_mode) { |
| 749 | /* | 753 | /* |
| 750 | * The disk must be active because we're syncing. | 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 | state->f[0] = -1; | 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 | /* Helper functions for BLAKE2s shared by the library and shash APIs */ | 27 | /* Helper functions for BLAKE2s shared by the library and shash APIs */ |
| 31 | 28 | ||
| 32 | static inline void __blake2s_update(struct blake2s_state *state, | 29 | static __always_inline void |
| 33 | const u8 *in, size_t inlen, | 30 | __blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen, |
| 34 | blake2s_compress_t compress) | 31 | bool force_generic) |
| 35 | { | 32 | { |
| 36 | const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; | 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 | return; | 36 | return; |
| 40 | if (inlen > fill) { | 37 | if (inlen > fill) { |
| 41 | memcpy(state->buf + state->buflen, in, fill); | 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 | state->buflen = 0; | 45 | state->buflen = 0; |
| 44 | in += fill; | 46 | in += fill; |
| 45 | inlen -= fill; | 47 | inlen -= fill; |
| @@ -47,7 +49,12 @@ static inline void __blake2s_update(struct blake2s_state *state, · 1 unmodified line | |||
| 47 | if (inlen > BLAKE2S_BLOCK_SIZE) { | 49 | if (inlen > BLAKE2S_BLOCK_SIZE) { |
| 48 | const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); | 50 | const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); |
| 49 | /* Hash one less (full) block than strictly possible */ | 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 | in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); | 58 | in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); |
| 52 | inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); | 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 | state->buflen += inlen; | 62 | state->buflen += inlen; |
| 56 | } | 63 | } |
| 57 | 64 | ||
| 58 | static inline void __blake2s_final(struct blake2s_state *state, u8 *out, | 65 | static __always_inline void |
| 59 | blake2s_compress_t compress) | 66 | __blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic) |
| 60 | { | 67 | { |
| 61 | blake2s_set_lastblock(state); | 68 | blake2s_set_lastblock(state); |
| 62 | memset(state->buf + state->buflen, 0, | 69 | memset(state->buf + state->buflen, 0, |
| 63 | BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ | 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 | cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); | 75 | cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); |
| 66 | memcpy(out, state->h, state->outlen); | 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 | static inline int crypto_blake2s_update(struct shash_desc *desc, | 110 | static inline int crypto_blake2s_update(struct shash_desc *desc, |
| 101 | const u8 *in, unsigned int inlen, | 111 | const u8 *in, unsigned int inlen, |
| 102 | blake2s_compress_t compress) | 112 | bool force_generic) |
| 103 | { | 113 | { |
| 104 | struct blake2s_state *state = shash_desc_ctx(desc); | 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 | return 0; | 117 | return 0; |
| 108 | } | 118 | } |
| 109 | 119 | ||
| 110 | static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out, | 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 | struct blake2s_state *state = shash_desc_ctx(desc); | 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 | return 0; | 126 | return 0; |
| 117 | } | 127 | } |
| 118 | 128 | ||
| @@ -324,12 +324,12 @@ enum { · 323 unmodified lines | |||
| 324 | ATA_LOG_NCQ_NON_DATA = 0x12, | 324 | ATA_LOG_NCQ_NON_DATA = 0x12, |
| 325 | ATA_LOG_NCQ_SEND_RECV = 0x13, | 325 | ATA_LOG_NCQ_SEND_RECV = 0x13, |
| 326 | ATA_LOG_IDENTIFY_DEVICE = 0x30, | 326 | ATA_LOG_IDENTIFY_DEVICE = 0x30, |
| 327 | ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, | ||
| 327 | 328 | ||
| 328 | /* Identify device log pages: */ | 329 | /* Identify device log pages: */ |
| 329 | ATA_LOG_SECURITY = 0x06, | 330 | ATA_LOG_SECURITY = 0x06, |
| 330 | ATA_LOG_SATA_SETTINGS = 0x08, | 331 | ATA_LOG_SATA_SETTINGS = 0x08, |
| 331 | ATA_LOG_ZONED_INFORMATION = 0x09, | 332 | ATA_LOG_ZONED_INFORMATION = 0x09, |
| 332 | ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, | ||
| 333 | 333 | ||
| 334 | /* Identify device SATA settings log:*/ | 334 | /* Identify device SATA settings log:*/ |
| 335 | ATA_LOG_DEVSLP_OFFSET = 0x30, | 335 | ATA_LOG_DEVSLP_OFFSET = 0x30, |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | |||
| 35 | #define CEPH_OPT_TCP_NODELAY (1<<4) /* TCP_NODELAY on TCP sockets */ | 35 | #define CEPH_OPT_TCP_NODELAY (1<<4) /* TCP_NODELAY on TCP sockets */ |
| 36 | #define CEPH_OPT_NOMSGSIGN (1<<5) /* don't sign msgs (msgr1) */ | 36 | #define CEPH_OPT_NOMSGSIGN (1<<5) /* don't sign msgs (msgr1) */ |
| 37 | #define CEPH_OPT_ABORT_ON_FULL (1<<6) /* abort w/ ENOSPC when full */ | 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 | #define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY) | 40 | #define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY) |
| 40 | 41 | ||
| @@ -383,6 +383,10 @@ struct ceph_connection_v2_info { · 382 unmodified lines | |||
| 383 | struct ceph_gcm_nonce in_gcm_nonce; | 383 | struct ceph_gcm_nonce in_gcm_nonce; |
| 384 | struct ceph_gcm_nonce out_gcm_nonce; | 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 | struct page **out_enc_pages; | 390 | struct page **out_enc_pages; |
| 387 | int out_enc_page_cnt; | 391 | int out_enc_page_cnt; |
| 388 | int out_enc_resid; | 392 | int out_enc_resid; |
| @@ -457,6 +461,7 @@ struct ceph_connection { · 68 unmodified lines | |||
| 457 | struct ceph_msg *out_msg; /* sending message (== tail of | 461 | struct ceph_msg *out_msg; /* sending message (== tail of |
| 458 | out_sent) */ | 462 | out_sent) */ |
| 459 | 463 | ||
| 464 | struct page *bounce_page; | ||
| 460 | u32 in_front_crc, in_middle_crc, in_data_crc; /* calculated crc */ | 465 | u32 in_front_crc, in_middle_crc, in_data_crc; /* calculated crc */ |
| 461 | 466 | ||
| 462 | struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */ | 467 | struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */ |
| @@ -262,7 +262,7 @@ struct fb_ops { · 261 unmodified lines | |||
| 262 | 262 | ||
| 263 | /* Draws a rectangle */ | 263 | /* Draws a rectangle */ |
| 264 | void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); | 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 | void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); | 266 | void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); |
| 267 | /* Draws a image to the display */ | 267 | /* Draws a image to the display */ |
| 268 | void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); | 268 | void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); |
| @@ -263,9 +263,11 @@ struct iomap_ioend { · 262 unmodified lines | |||
| 263 | struct list_head io_list; /* next ioend in chain */ | 263 | struct list_head io_list; /* next ioend in chain */ |
| 264 | u16 io_type; | 264 | u16 io_type; |
| 265 | u16 io_flags; /* IOMAP_F_* */ | 265 | u16 io_flags; /* IOMAP_F_* */ |
| 266 | u32 io_folios; /* folios added to ioend */ | ||
| 266 | struct inode *io_inode; /* file being written to */ | 267 | struct inode *io_inode; /* file being written to */ |
| 267 | size_t io_size; /* size of the extent */ | 268 | size_t io_size; /* size of the extent */ |
| 268 | loff_t io_offset; /* offset in the file */ | 269 | loff_t io_offset; /* offset in the file */ |
| 270 | sector_t io_sector; /* start sector of ioend */ | ||
| 269 | struct bio *io_bio; /* bio being built */ | 271 | struct bio *io_bio; /* bio being built */ |
| 270 | struct bio io_inline_bio; /* MUST BE LAST! */ | 272 | struct bio io_inline_bio; /* MUST BE LAST! */ |
| 271 | }; | 273 | }; |
| @@ -594,7 +594,7 @@ struct transaction_s · 593 unmodified lines | |||
| 594 | */ | 594 | */ |
| 595 | unsigned long t_log_start; | 595 | unsigned long t_log_start; |
| 596 | 596 | ||
| 597 | /* | 597 | /* |
| 598 | * Number of buffers on the t_buffers list [j_list_lock, no locks | 598 | * Number of buffers on the t_buffers list [j_list_lock, no locks |
| 599 | * needed for jbd2 thread] | 599 | * needed for jbd2 thread] |
| 600 | */ | 600 | */ |
| @@ -1295,7 +1295,7 @@ struct journal_s · 694 unmodified lines | |||
| 1295 | * Clean-up after fast commit or full commit. JBD2 calls this function | 1295 | * Clean-up after fast commit or full commit. JBD2 calls this function |
| 1296 | * after every commit operation. | 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 | * @j_fc_replay_callback: | 1301 | * @j_fc_replay_callback: |
| @@ -1419,9 +1419,7 @@ extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *); · 117 unmodified lines | |||
| 1419 | extern bool __jbd2_journal_refile_buffer(struct journal_head *); | 1419 | extern bool __jbd2_journal_refile_buffer(struct journal_head *); |
| 1420 | extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); | 1420 | extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); |
| 1421 | extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); | 1421 | extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); |
| 1422 | extern void __journal_free_buffer(struct journal_head *bh); | ||
| 1423 | extern void jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); | 1422 | extern void jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); |
| 1424 | extern void __journal_clean_data_list(transaction_t *transaction); | ||
| 1425 | static inline void jbd2_file_log_bh(struct list_head *head, struct buffer_head *bh) | 1423 | static inline void jbd2_file_log_bh(struct list_head *head, struct buffer_head *bh) |
| 1426 | { | 1424 | { |
| 1427 | list_add_tail(&bh->b_assoc_buffers, head); | 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 | struct buffer_head **bh_out, | 1484 | struct buffer_head **bh_out, |
| 1487 | sector_t blocknr); | 1485 | sector_t blocknr); |
| 1488 | 1486 | ||
| 1489 | /* Transaction locking */ | ||
| 1490 | extern void __wait_on_journal (journal_t *); | ||
| 1491 | |||
| 1492 | /* Transaction cache support */ | 1487 | /* Transaction cache support */ |
| 1493 | extern void jbd2_journal_destroy_transaction_cache(void); | 1488 | extern void jbd2_journal_destroy_transaction_cache(void); |
| 1494 | extern int __init jbd2_journal_init_transaction_cache(void); | 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 | extern void jbd2_journal_lock_updates (journal_t *); | 1538 | extern void jbd2_journal_lock_updates (journal_t *); |
| 1544 | extern void jbd2_journal_unlock_updates (journal_t *); | 1539 | extern void jbd2_journal_unlock_updates (journal_t *); |
| 1545 | 1540 | ||
| 1541 | void jbd2_journal_wait_updates(journal_t *); | ||
| 1542 | |||
| 1546 | extern journal_t * jbd2_journal_init_dev(struct block_device *bdev, | 1543 | extern journal_t * jbd2_journal_init_dev(struct block_device *bdev, |
| 1547 | struct block_device *fs_dev, | 1544 | struct block_device *fs_dev, |
| 1548 | unsigned long long start, int len, int bsize); | 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 | #define BJ_Reserved 4 /* Buffer is reserved for access by journal */ | 1771 | #define BJ_Reserved 4 /* Buffer is reserved for access by journal */ |
| 1775 | #define BJ_Types 5 | 1772 | #define BJ_Types 5 |
| 1776 | 1773 | ||
| 1777 | extern int jbd_blocks_per_page(struct inode *inode); | ||
| 1778 | |||
| 1779 | /* JBD uses a CRC32 checksum */ | 1774 | /* JBD uses a CRC32 checksum */ |
| 1780 | #define JBD_MAX_CHECKSUM_SIZE 4 | 1775 | #define JBD_MAX_CHECKSUM_SIZE 4 |
| 1781 | 1776 | ||
| @@ -29,7 +29,9 @@ · 28 unmodified lines | |||
| 29 | #include <linux/refcount.h> | 29 | #include <linux/refcount.h> |
| 30 | #include <linux/nospec.h> | 30 | #include <linux/nospec.h> |
| 31 | #include <linux/notifier.h> | 31 | #include <linux/notifier.h> |
| 32 | #include <linux/ftrace.h> | ||
| 32 | #include <linux/hashtable.h> | 33 | #include <linux/hashtable.h> |
| 34 | #include <linux/instrumentation.h> | ||
| 33 | #include <linux/interval_tree.h> | 35 | #include <linux/interval_tree.h> |
| 34 | #include <linux/rbtree.h> | 36 | #include <linux/rbtree.h> |
| 35 | #include <linux/xarray.h> | 37 | #include <linux/xarray.h> |
| @@ -368,8 +370,11 @@ struct kvm_vcpu { · 332 unmodified lines | |||
| 368 | u64 last_used_slot_gen; | 370 | u64 last_used_slot_gen; |
| 369 | }; | 371 | }; |
| 370 | 372 | ||
| 371 | /* must be called with irqs disabled */ | 373 | /* |
| 372 | static __always_inline void guest_enter_irqoff(void) | 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 | * This is running in ioctl context so its safe to assume that it's the | 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 | instrumentation_begin(); | 383 | instrumentation_begin(); |
| 379 | vtime_account_guest_enter(); | 384 | vtime_account_guest_enter(); |
| 380 | instrumentation_end(); | 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 | * KVM does not hold any references to rcu protected data when it | 399 | * KVM does not hold any references to rcu protected data when it |
| 384 | * switches CPU into a guest mode. In fact switching to a guest mode | 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 | context_tracking_guest_exit(); | 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 | instrumentation_begin(); | 470 | instrumentation_begin(); |
| 402 | /* Flush the guest cputime we spent on the guest */ | 471 | /* Flush the guest cputime we spent on the guest */ |
| 403 | vtime_account_guest_exit(); | 472 | vtime_account_guest_exit(); |
| 404 | instrumentation_end(); | 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 | static inline void guest_exit(void) | 486 | static inline void guest_exit(void) |
| 408 | { | 487 | { |
| 409 | unsigned long flags; | 488 | unsigned long flags; |
| @@ -413,6 +492,33 @@ static inline void guest_exit(void) · 3 unmodified lines | |||
| 413 | local_irq_restore(flags); | 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 | static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu) | 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 | ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ | 380 | ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ |
| 381 | ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ | 381 | ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ |
| 382 | ATA_HORKAGE_NO_ID_DEV_LOG = (1 << 28), /* Identify device log missing */ | 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 | /* DMA mask for user DMA control: User visible values; DO NOT | 385 | /* DMA mask for user DMA control: User visible values; DO NOT |
| 385 | renumber */ | 386 | renumber */ |
| @@ -244,6 +244,13 @@ struct netfs_cache_ops { · 243 unmodified lines | |||
| 244 | int (*prepare_write)(struct netfs_cache_resources *cres, | 244 | int (*prepare_write)(struct netfs_cache_resources *cres, |
| 245 | loff_t *_start, size_t *_len, loff_t i_size, | 245 | loff_t *_start, size_t *_len, loff_t i_size, |
| 246 | bool no_space_allocated_yet); | 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 | struct readahead_control; | 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 | memcpy(target->data, source->data, source->size); | 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 | enum nfs3_stable_how { | 39 | enum nfs3_stable_how { |
| 48 | NFS_UNSTABLE = 0, | 40 | NFS_UNSTABLE = 0, |
| 49 | NFS_DATA_SYNC = 1, | 41 | NFS_DATA_SYNC = 1, |
| @@ -107,6 +107,7 @@ struct nfs_open_dir_context { · 106 unmodified lines | |||
| 107 | __u64 dup_cookie; | 107 | __u64 dup_cookie; |
| 108 | pgoff_t page_index; | 108 | pgoff_t page_index; |
| 109 | signed char duped; | 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 | pmd_t *pmdp, pmd_t pmd); | 26 | pmd_t *pmdp, pmd_t pmd); |
| 27 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, | 27 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 28 | pud_t *pudp, pud_t pud); | 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 | static inline void page_table_check_alloc(struct page *page, unsigned int order) | 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 | __page_table_check_pud_set(mm, addr, pudp, pud); | 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 | #else | 116 | #else |
| 104 | 117 | ||
| 105 | static inline void page_table_check_alloc(struct page *page, unsigned int order) | 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 | #endif /* CONFIG_PAGE_TABLE_CHECK */ | 165 | #endif /* CONFIG_PAGE_TABLE_CHECK */ |
| 147 | #endif /* __LINUX_PAGE_TABLE_CHECK_H */ | 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 | return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); | 63 | return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); |
| 64 | } | 64 | } |
| 65 | #define pte_index pte_index | ||
| 65 | 66 | ||
| 66 | #ifndef pmd_index | 67 | #ifndef pmd_index |
| 67 | static inline unsigned long pmd_index(unsigned long address) | 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 | memcpy(&new_md->u.tun_info, &md_dst->u.tun_info, | 124 | memcpy(&new_md->u.tun_info, &md_dst->u.tun_info, |
| 125 | sizeof(struct ip_tunnel_info) + md_size); | 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 | skb_dst_drop(skb); | 139 | skb_dst_drop(skb); |
| 127 | dst_hold(&new_md->dst); | ||
| 128 | skb_dst_set(skb, &new_md->dst); | 140 | skb_dst_set(skb, &new_md->dst); |
| 129 | return new_md; | 141 | return new_md; |
| 130 | } | 142 | } |
| @@ -617,6 +617,7 @@ void snd_pcm_stream_unlock(struct snd_pcm_substream *substream); · 616 unmodified lines | |||
| 617 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream); | 617 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream); |
| 618 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream); | 618 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream); |
| 619 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream); | 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 | * snd_pcm_stream_lock_irqsave - Lock the PCM stream | 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 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, | 636 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, |
| 636 | unsigned long flags); | 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 | * snd_pcm_group_for_each_entry - iterate over the linked substreams | 654 | * snd_pcm_group_for_each_entry - iterate over the linked substreams |
| 640 | * @s: the iterator | 655 | * @s: the iterator |
| @@ -1624,9 +1624,6 @@ struct kvm_enc_region { · 1623 unmodified lines | |||
| 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) | 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) |
| 1625 | #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) | 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 | struct kvm_s390_pv_sec_parm { | 1627 | struct kvm_s390_pv_sec_parm { |
| 1631 | __u64 origin; | 1628 | __u64 origin; |
| 1632 | __u64 length; | 1629 | __u64 length; |
| @@ -2048,4 +2045,7 @@ struct kvm_stats_desc { · 415 unmodified lines | |||
| 2048 | 2045 | ||
| 2049 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) | 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 | #endif /* __LINUX_KVM_H */ | 2051 | #endif /* __LINUX_KVM_H */ |
| @@ -106,7 +106,7 @@ enum ip_conntrack_status { · 105 unmodified lines | |||
| 106 | IPS_NAT_CLASH = IPS_UNTRACKED, | 106 | IPS_NAT_CLASH = IPS_UNTRACKED, |
| 107 | #endif | 107 | #endif |
| 108 | 108 | ||
| 109 | /* Conntrack got a helper explicitly attached via CT target. */ | 109 | /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */ |
| 110 | IPS_HELPER_BIT = 13, | 110 | IPS_HELPER_BIT = 13, |
| 111 | IPS_HELPER = (1 << IPS_HELPER_BIT), | 111 | IPS_HELPER = (1 << IPS_HELPER_BIT), |
| 112 | 112 | ||
| @@ -465,6 +465,8 @@ struct perf_event_attr { · 464 unmodified lines | |||
| 465 | /* | 465 | /* |
| 466 | * User provided data if sigtrap=1, passed back to user via | 466 | * User provided data if sigtrap=1, passed back to user via |
| 467 | * siginfo_t::si_perf_data, e.g. to permit user to identify the event. | 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 | __u64 sig_data; | 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 | struct snd_aes_iec958 { | 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 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ | 63 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ |
| 62 | unsigned char pad; /* nothing */ | 64 | unsigned char pad; /* nothing */ |
| 63 | unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ | 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 | * Inserts the grant references into the mapping table of an instance | 48 | * Inserts the grant references into the mapping table of an instance |
| 49 | * of gntdev. N.B. This does not perform the mapping, which is deferred | 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 | #define IOCTL_GNTDEV_MAP_GRANT_REF \ | 58 | #define IOCTL_GNTDEV_MAP_GRANT_REF \ |
| 53 | _IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) | 59 | _IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) |
| @@ -1,6 +1,4 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * evtchn.h | ||
| 3 | * | ||
| 4 | * Interface to /dev/xen/xenbus_backend. | 2 | * Interface to /dev/xen/xenbus_backend. |
| 5 | * | 3 | * |
| 6 | * Copyright (c) 2011 Bastian Blank <waldi@debian.org> | 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 | un = lookup_undo(ulp, semid); | 1965 | un = lookup_undo(ulp, semid); |
| 1966 | if (un) { | 1966 | if (un) { |
| 1967 | spin_unlock(&ulp->lock); | ||
| 1967 | kvfree(new); | 1968 | kvfree(new); |
| 1968 | goto success; | 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 | ipc_assert_locked_object(&sma->sem_perm); | 1977 | ipc_assert_locked_object(&sma->sem_perm); |
| 1977 | list_add(&new->list_id, &sma->list_id); | 1978 | list_add(&new->list_id, &sma->list_id); |
| 1978 | un = new; | 1979 | un = new; |
| 1979 | |||
| 1980 | success: | ||
| 1981 | spin_unlock(&ulp->lock); | 1980 | spin_unlock(&ulp->lock); |
| 1981 | success: | ||
| 1982 | sem_unlock(sma, -1); | 1982 | sem_unlock(sma, -1); |
| 1983 | out: | 1983 | out: |
| 1984 | return un; | 1984 | return un; |
| @@ -185,7 +185,7 @@ static int audit_match_perm(struct audit_context *ctx, int mask) · 184 unmodified lines | |||
| 185 | case AUDITSC_EXECVE: | 185 | case AUDITSC_EXECVE: |
| 186 | return mask & AUDIT_PERM_EXEC; | 186 | return mask & AUDIT_PERM_EXEC; |
| 187 | case AUDITSC_OPENAT2: | 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 | default: | 189 | default: |
| 190 | return 0; | 190 | return 0; |
| 191 | } | 191 | } |
| @@ -3238,6 +3238,15 @@ static int perf_event_modify_breakpoint(struct perf_event *bp, · 3237 unmodified lines | |||
| 3238 | return err; | 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 | static int perf_event_modify_attr(struct perf_event *event, | 3250 | static int perf_event_modify_attr(struct perf_event *event, |
| 3242 | struct perf_event_attr *attr) | 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 | WARN_ON_ONCE(event->ctx->parent_ctx); | 3269 | WARN_ON_ONCE(event->ctx->parent_ctx); |
| 3261 | 3270 | ||
| 3262 | mutex_lock(&event->child_mutex); | 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 | err = func(event, attr); | 3278 | err = func(event, attr); |
| 3264 | if (err) | 3279 | if (err) |
| 3265 | goto out; | 3280 | goto out; |
| 3266 | list_for_each_entry(child, &event->child_list, child_list) { | 3281 | list_for_each_entry(child, &event->child_list, child_list) { |
| 3282 | perf_event_modify_copy_attr(&child->attr, attr); | ||
| 3267 | err = func(child, attr); | 3283 | err = func(child, attr); |
| 3268 | if (err) | 3284 | if (err) |
| 3269 | goto out; | 3285 | goto out; |
| @@ -18,14 +18,14 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) | 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 | EXPORT_SYMBOL(blake2s_update); | 23 | EXPORT_SYMBOL(blake2s_update); |
| 24 | 24 | ||
| 25 | void blake2s_final(struct blake2s_state *state, u8 *out) | 25 | void blake2s_final(struct blake2s_state *state, u8 *out) |
| 26 | { | 26 | { |
| 27 | WARN_ON(IS_ENABLED(DEBUG) && !out); | 27 | WARN_ON(IS_ENABLED(DEBUG) && !out); |
| 28 | __blake2s_final(state, out, blake2s_compress); | 28 | __blake2s_final(state, out, false); |
| 29 | memzero_explicit(state, sizeof(*state)); | 29 | memzero_explicit(state, sizeof(*state)); |
| 30 | } | 30 | } |
| 31 | EXPORT_SYMBOL(blake2s_final); | 31 | EXPORT_SYMBOL(blake2s_final); |
| @@ -171,6 +171,8 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args) · 170 unmodified lines | |||
| 171 | ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep); | 171 | ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep); |
| 172 | pte = ptep_get(args->ptep); | 172 | pte = ptep_get(args->ptep); |
| 173 | WARN_ON(pte_young(pte)); | 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 | static void __init pte_savedwrite_tests(struct pgtable_debug_args *args) | 178 | static void __init pte_savedwrite_tests(struct pgtable_debug_args *args) |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <linux/hashtable.h> | 16 | #include <linux/hashtable.h> |
| 17 | #include <linux/userfaultfd_k.h> | 17 | #include <linux/userfaultfd_k.h> |
| 18 | #include <linux/page_idle.h> | 18 | #include <linux/page_idle.h> |
| 19 | #include <linux/page_table_check.h> | ||
| 19 | #include <linux/swapops.h> | 20 | #include <linux/swapops.h> |
| 20 | #include <linux/shmem_fs.h> | 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 | return 0; | 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 | * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at | 1436 | * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at |
| 1421 | * address haddr. | 1437 | * address haddr. |
| @@ -1433,7 +1449,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 11 unmodified lines | |||
| 1433 | struct vm_area_struct *vma = find_vma(mm, haddr); | 1449 | struct vm_area_struct *vma = find_vma(mm, haddr); |
| 1434 | struct page *hpage; | 1450 | struct page *hpage; |
| 1435 | pte_t *start_pte, *pte; | 1451 | pte_t *start_pte, *pte; |
| 1436 | pmd_t *pmd, _pmd; | 1452 | pmd_t *pmd; |
| 1437 | spinlock_t *ptl; | 1453 | spinlock_t *ptl; |
| 1438 | int count = 0; | 1454 | int count = 0; |
| 1439 | int i; | 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 | /* step 4: collapse pmd */ | 1527 | /* step 4: collapse pmd */ |
| 1512 | ptl = pmd_lock(vma->vm_mm, pmd); | 1528 | collapse_and_free_pmd(mm, vma, haddr, 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 | |||
| 1518 | drop_hpage: | 1529 | drop_hpage: |
| 1519 | unlock_page(hpage); | 1530 | unlock_page(hpage); |
| 1520 | put_page(hpage); | 1531 | put_page(hpage); |
| @@ -1552,7 +1563,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) · 31 unmodified lines | |||
| 1552 | struct vm_area_struct *vma; | 1563 | struct vm_area_struct *vma; |
| 1553 | struct mm_struct *mm; | 1564 | struct mm_struct *mm; |
| 1554 | unsigned long addr; | 1565 | unsigned long addr; |
| 1555 | pmd_t *pmd, _pmd; | 1566 | pmd_t *pmd; |
| 1556 | 1567 | ||
| 1557 | i_mmap_lock_write(mapping); | 1568 | i_mmap_lock_write(mapping); |
| 1558 | vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { | 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 | * reverse order. Trylock is a way to avoid deadlock. | 1602 | * reverse order. Trylock is a way to avoid deadlock. |
| 1592 | */ | 1603 | */ |
| 1593 | if (mmap_write_trylock(mm)) { | 1604 | if (mmap_write_trylock(mm)) { |
| 1594 | if (!khugepaged_test_exit(mm)) { | 1605 | if (!khugepaged_test_exit(mm)) |
| 1595 | spinlock_t *ptl = pmd_lock(mm, pmd); | 1606 | collapse_and_free_pmd(mm, vma, addr, 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 | } | ||
| 1602 | mmap_write_unlock(mm); | 1607 | mmap_write_unlock(mm); |
| 1603 | } else { | 1608 | } else { |
| 1604 | /* Try again later */ | 1609 | /* Try again later */ |
| @@ -1410,7 +1410,8 @@ static void kmemleak_scan(void) · 1409 unmodified lines | |||
| 1410 | { | 1410 | { |
| 1411 | unsigned long flags; | 1411 | unsigned long flags; |
| 1412 | struct kmemleak_object *object; | 1412 | struct kmemleak_object *object; |
| 1413 | int i; | 1413 | struct zone *zone; |
| 1414 | int __maybe_unused i; | ||
| 1414 | int new_leaks = 0; | 1415 | int new_leaks = 0; |
| 1415 | 1416 | ||
| 1416 | jiffies_last_scan = jiffies; | 1417 | jiffies_last_scan = jiffies; |
| @@ -1450,9 +1451,9 @@ static void kmemleak_scan(void) · 33 unmodified lines | |||
| 1450 | * Struct page scanning for each node. | 1451 | * Struct page scanning for each node. |
| 1451 | */ | 1452 | */ |
| 1452 | get_online_mems(); | 1453 | get_online_mems(); |
| 1453 | for_each_online_node(i) { | 1454 | for_each_populated_zone(zone) { |
| 1454 | unsigned long start_pfn = node_start_pfn(i); | 1455 | unsigned long start_pfn = zone->zone_start_pfn; |
| 1455 | unsigned long end_pfn = node_end_pfn(i); | 1456 | unsigned long end_pfn = zone_end_pfn(zone); |
| 1456 | unsigned long pfn; | 1457 | unsigned long pfn; |
| 1457 | 1458 | ||
| 1458 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { | 1459 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
| @@ -1461,8 +1462,8 @@ static void kmemleak_scan(void) · 2 unmodified lines | |||
| 1461 | if (!page) | 1462 | if (!page) |
| 1462 | continue; | 1463 | continue; |
| 1463 | 1464 | ||
| 1464 | /* only scan pages belonging to this node */ | 1465 | /* only scan pages belonging to this zone */ |
| 1465 | if (page_to_nid(page) != i) | 1466 | if (page_zone(page) != zone) |
| 1466 | continue; | 1467 | continue; |
| 1467 | /* only scan if page is in use */ | 1468 | /* only scan if page is in use */ |
| 1468 | if (page_count(page) == 0) | 1469 | if (page_count(page) == 0) |
| @@ -115,7 +115,7 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype) · 114 unmodified lines | |||
| 115 | * onlining - just onlined memory won't immediately be considered for | 115 | * onlining - just onlined memory won't immediately be considered for |
| 116 | * allocation. | 116 | * allocation. |
| 117 | */ | 117 | */ |
| 118 | if (!isolated_page && PageBuddy(page)) { | 118 | if (!isolated_page) { |
| 119 | nr_pages = move_freepages_block(zone, page, migratetype, NULL); | 119 | nr_pages = move_freepages_block(zone, page, migratetype, NULL); |
| 120 | __mod_zone_freepage_state(zone, nr_pages, migratetype); | 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 | struct page_ext *page_ext; | 87 | struct page_ext *page_ext; |
| 88 | struct page *page; | 88 | struct page *page; |
| 89 | unsigned long i; | ||
| 89 | bool anon; | 90 | bool anon; |
| 90 | int i; | ||
| 91 | 91 | ||
| 92 | if (!pfn_valid(pfn)) | 92 | if (!pfn_valid(pfn)) |
| 93 | return; | 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 | struct page_ext *page_ext; | 122 | struct page_ext *page_ext; |
| 123 | struct page *page; | 123 | struct page *page; |
| 124 | unsigned long i; | ||
| 124 | bool anon; | 125 | bool anon; |
| 125 | int i; | ||
| 126 | 126 | ||
| 127 | if (!pfn_valid(pfn)) | 127 | if (!pfn_valid(pfn)) |
| 128 | return; | 128 | return; |
| @@ -152,10 +152,10 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr, · 23 unmodified lines | |||
| 152 | void __page_table_check_zero(struct page *page, unsigned int order) | 152 | void __page_table_check_zero(struct page *page, unsigned int order) |
| 153 | { | 153 | { |
| 154 | struct page_ext *page_ext = lookup_page_ext(page); | 154 | struct page_ext *page_ext = lookup_page_ext(page); |
| 155 | int i; | 155 | unsigned long i; |
| 156 | 156 | ||
| 157 | BUG_ON(!page_ext); | 157 | BUG_ON(!page_ext); |
| 158 | for (i = 0; i < (1 << order); i++) { | 158 | for (i = 0; i < (1ul << order); i++) { |
| 159 | struct page_table_check *ptc = get_page_table_check(page_ext); | 159 | struct page_table_check *ptc = get_page_table_check(page_ext); |
| 160 | 160 | ||
| 161 | BUG_ON(atomic_read(&ptc->anon_map_count)); | 161 | BUG_ON(atomic_read(&ptc->anon_map_count)); |
| @@ -206,17 +206,10 @@ EXPORT_SYMBOL(__page_table_check_pud_clear); · 44 unmodified lines | |||
| 206 | void __page_table_check_pte_set(struct mm_struct *mm, unsigned long addr, | 206 | void __page_table_check_pte_set(struct mm_struct *mm, unsigned long addr, |
| 207 | pte_t *ptep, pte_t pte) | 207 | pte_t *ptep, pte_t pte) |
| 208 | { | 208 | { |
| 209 | pte_t old_pte; | ||
| 210 | |||
| 211 | if (&init_mm == mm) | 209 | if (&init_mm == mm) |
| 212 | return; | 210 | return; |
| 213 | 211 | ||
| 214 | old_pte = *ptep; | 212 | __page_table_check_pte_clear(mm, addr, *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 | |||
| 220 | if (pte_user_accessible_page(pte)) { | 213 | if (pte_user_accessible_page(pte)) { |
| 221 | page_table_check_set(mm, addr, pte_pfn(pte), | 214 | page_table_check_set(mm, addr, pte_pfn(pte), |
| 222 | PAGE_SIZE >> PAGE_SHIFT, | 215 | PAGE_SIZE >> PAGE_SHIFT, |
| @@ -228,17 +221,10 @@ EXPORT_SYMBOL(__page_table_check_pte_set); · 5 unmodified lines | |||
| 228 | void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, | 221 | void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, |
| 229 | pmd_t *pmdp, pmd_t pmd) | 222 | pmd_t *pmdp, pmd_t pmd) |
| 230 | { | 223 | { |
| 231 | pmd_t old_pmd; | ||
| 232 | |||
| 233 | if (&init_mm == mm) | 224 | if (&init_mm == mm) |
| 234 | return; | 225 | return; |
| 235 | 226 | ||
| 236 | old_pmd = *pmdp; | 227 | __page_table_check_pmd_clear(mm, addr, *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 | |||
| 242 | if (pmd_user_accessible_page(pmd)) { | 228 | if (pmd_user_accessible_page(pmd)) { |
| 243 | page_table_check_set(mm, addr, pmd_pfn(pmd), | 229 | page_table_check_set(mm, addr, pmd_pfn(pmd), |
| 244 | PMD_PAGE_SIZE >> PAGE_SHIFT, | 230 | PMD_PAGE_SIZE >> PAGE_SHIFT, |
| @@ -250,17 +236,10 @@ EXPORT_SYMBOL(__page_table_check_pmd_set); · 5 unmodified lines | |||
| 250 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, | 236 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 251 | pud_t *pudp, pud_t pud) | 237 | pud_t *pudp, pud_t pud) |
| 252 | { | 238 | { |
| 253 | pud_t old_pud; | ||
| 254 | |||
| 255 | if (&init_mm == mm) | 239 | if (&init_mm == mm) |
| 256 | return; | 240 | return; |
| 257 | 241 | ||
| 258 | old_pud = *pudp; | 242 | __page_table_check_pud_clear(mm, addr, *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 | |||
| 264 | if (pud_user_accessible_page(pud)) { | 243 | if (pud_user_accessible_page(pud)) { |
| 265 | page_table_check_set(mm, addr, pud_pfn(pud), | 244 | page_table_check_set(mm, addr, pud_pfn(pud), |
| 266 | PUD_PAGE_SIZE >> PAGE_SHIFT, | 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 | EXPORT_SYMBOL(__page_table_check_pud_set); | 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 | u32 skb_prio, u16 vlan_prio); | 129 | u32 skb_prio, u16 vlan_prio); |
| 130 | int vlan_dev_set_egress_priority(const struct net_device *dev, | 130 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
| 131 | u32 skb_prio, u16 vlan_prio); | 131 | u32 skb_prio, u16 vlan_prio); |
| 132 | void vlan_dev_free_egress_priority(const struct net_device *dev); | ||
| 132 | int vlan_dev_change_flags(const struct net_device *dev, u32 flag, u32 mask); | 133 | int vlan_dev_change_flags(const struct net_device *dev, u32 flag, u32 mask); |
| 133 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result, | 134 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result, |
| 134 | size_t size); | 135 | size_t size); |
| @@ -139,7 +140,6 @@ int vlan_check_real_dev(struct net_device *real_dev, · 4 unmodified lines | |||
| 139 | void vlan_setup(struct net_device *dev); | 140 | void vlan_setup(struct net_device *dev); |
| 140 | int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack); | 141 | int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack); |
| 141 | void unregister_vlan_dev(struct net_device *dev, struct list_head *head); | 142 | void unregister_vlan_dev(struct net_device *dev, struct list_head *head); |
| 142 | void vlan_dev_uninit(struct net_device *dev); | ||
| 143 | bool vlan_dev_inherit_address(struct net_device *dev, | 143 | bool vlan_dev_inherit_address(struct net_device *dev, |
| 144 | struct net_device *real_dev); | 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 | /* Note: this function might be called multiple times for the same device. */ | 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 | struct vlan_priority_tci_mapping *pm; | 627 | struct vlan_priority_tci_mapping *pm; |
| 628 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | 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 | static netdev_features_t vlan_dev_fix_features(struct net_device *dev, | 649 | static netdev_features_t vlan_dev_fix_features(struct net_device *dev, |
| 640 | netdev_features_t features) | 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 | free_percpu(vlan->vlan_pcpu_stats); | 857 | free_percpu(vlan->vlan_pcpu_stats); |
| 848 | vlan->vlan_pcpu_stats = NULL; | 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 | void vlan_setup(struct net_device *dev) | 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 | return -EINVAL; | 183 | return -EINVAL; |
| 184 | 184 | ||
| 185 | err = vlan_changelink(dev, tb, data, extack); | 185 | err = vlan_changelink(dev, tb, data, extack); |
| 186 | if (!err) | ||
| 187 | err = register_vlan_dev(dev, extack); | ||
| 188 | if (err) | 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 | return err; | 191 | return err; |
| 191 | } | 192 | } |
| 192 | 193 | ||
| @@ -91,9 +91,10 @@ again: · 90 unmodified lines | |||
| 91 | spin_unlock_bh(&ax25_list_lock); | 91 | spin_unlock_bh(&ax25_list_lock); |
| 92 | lock_sock(sk); | 92 | lock_sock(sk); |
| 93 | s->ax25_dev = NULL; | 93 | s->ax25_dev = NULL; |
| 94 | dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker); | ||
| 94 | ax25_dev_put(ax25_dev); | 95 | ax25_dev_put(ax25_dev); |
| 95 | release_sock(sk); | ||
| 96 | ax25_disconnect(s, ENETUNREACH); | 96 | ax25_disconnect(s, ENETUNREACH); |
| 97 | release_sock(sk); | ||
| 97 | spin_lock_bh(&ax25_list_lock); | 98 | spin_lock_bh(&ax25_list_lock); |
| 98 | sock_put(sk); | 99 | sock_put(sk); |
| 99 | /* The entry could have been deleted from the | 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 | ax25_fillin_cb(ax25, ax25_dev); | 1121 | ax25_fillin_cb(ax25, ax25_dev); |
| 1122 | dev_hold_track(ax25_dev->dev, &ax25_dev->dev_tracker, GFP_ATOMIC); | ||
| 1123 | } | ||
| 1121 | 1124 | ||
| 1122 | done: | 1125 | done: |
| 1123 | ax25_cb_add(ax25); | 1126 | ax25_cb_add(ax25); |
| @@ -56,6 +56,7 @@ · 55 unmodified lines | |||
| 56 | #include <linux/module.h> | 56 | #include <linux/module.h> |
| 57 | #include <linux/init.h> | 57 | #include <linux/init.h> |
| 58 | #include <linux/interrupt.h> | 58 | #include <linux/interrupt.h> |
| 59 | #include <linux/spinlock.h> | ||
| 59 | #include <linux/hrtimer.h> | 60 | #include <linux/hrtimer.h> |
| 60 | #include <linux/wait.h> | 61 | #include <linux/wait.h> |
| 61 | #include <linux/uio.h> | 62 | #include <linux/uio.h> |
| @@ -145,6 +146,7 @@ struct isotp_sock { · 83 unmodified lines | |||
| 145 | struct tpcon rx, tx; | 146 | struct tpcon rx, tx; |
| 146 | struct list_head notifier; | 147 | struct list_head notifier; |
| 147 | wait_queue_head_t wait; | 148 | wait_queue_head_t wait; |
| 149 | spinlock_t rx_lock; /* protect single thread state machine */ | ||
| 148 | }; | 150 | }; |
| 149 | 151 | ||
| 150 | static LIST_HEAD(isotp_notifier_list); | 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 | n_pci_type = cf->data[ae] & 0xF0; | 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 | if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) { | 626 | if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) { |
| 619 | /* check rx/tx path half duplex expectations */ | 627 | /* check rx/tx path half duplex expectations */ |
| 620 | if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) || | 628 | if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) || |
| 621 | (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC)) | 629 | (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC)) |
| 622 | return; | 630 | goto out_unlock; |
| 623 | } | 631 | } |
| 624 | 632 | ||
| 625 | switch (n_pci_type) { | 633 | switch (n_pci_type) { |
| @@ -668,6 +676,9 @@ static void isotp_rcv(struct sk_buff *skb, void *data) · 42 unmodified lines | |||
| 668 | isotp_rcv_cf(sk, cf, ae, skb); | 676 | isotp_rcv_cf(sk, cf, ae, skb); |
| 669 | break; | 677 | break; |
| 670 | } | 678 | } |
| 679 | |||
| 680 | out_unlock: | ||
| 681 | spin_unlock(&so->rx_lock); | ||
| 671 | } | 682 | } |
| 672 | 683 | ||
| 673 | static void isotp_fill_dataframe(struct canfd_frame *cf, struct isotp_sock *so, | 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 | if (!size || size > MAX_MSG_LENGTH) { | 888 | if (!size || size > MAX_MSG_LENGTH) { |
| 878 | err = -EINVAL; | 889 | err = -EINVAL; |
| 879 | goto err_out; | 890 | goto err_out_drop; |
| 880 | } | 891 | } |
| 881 | 892 | ||
| 882 | /* take care of a potential SF_DL ESC offset for TX_DL > 8 */ | 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 | if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && | 897 | if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && |
| 887 | (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { | 898 | (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { |
| 888 | err = -EINVAL; | 899 | err = -EINVAL; |
| 889 | goto err_out; | 900 | goto err_out_drop; |
| 890 | } | 901 | } |
| 891 | 902 | ||
| 892 | err = memcpy_from_msg(so->tx.buf, msg, size); | 903 | err = memcpy_from_msg(so->tx.buf, msg, size); |
| 893 | if (err < 0) | 904 | if (err < 0) |
| 894 | goto err_out; | 905 | goto err_out_drop; |
| 895 | 906 | ||
| 896 | dev = dev_get_by_index(sock_net(sk), so->ifindex); | 907 | dev = dev_get_by_index(sock_net(sk), so->ifindex); |
| 897 | if (!dev) { | 908 | if (!dev) { |
| 898 | err = -ENXIO; | 909 | err = -ENXIO; |
| 899 | goto err_out; | 910 | goto err_out_drop; |
| 900 | } | 911 | } |
| 901 | 912 | ||
| 902 | skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv), | 913 | skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv), |
| 903 | msg->msg_flags & MSG_DONTWAIT, &err); | 914 | msg->msg_flags & MSG_DONTWAIT, &err); |
| 904 | if (!skb) { | 915 | if (!skb) { |
| 905 | dev_put(dev); | 916 | dev_put(dev); |
| 906 | goto err_out; | 917 | goto err_out_drop; |
| 907 | } | 918 | } |
| 908 | 919 | ||
| 909 | can_skb_reserve(skb); | 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 | if (err) { | 976 | if (err) { |
| 966 | pr_notice_once("can-isotp: %s: can_send_ret %pe\n", | 977 | pr_notice_once("can-isotp: %s: can_send_ret %pe\n", |
| 967 | __func__, ERR_PTR(err)); | 978 | __func__, ERR_PTR(err)); |
| 968 | goto err_out; | 979 | goto err_out_drop; |
| 969 | } | 980 | } |
| 970 | 981 | ||
| 971 | if (wait_tx_done) { | 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 | return size; | 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 | err_out: | 995 | err_out: |
| 982 | so->tx.state = old_state; | 996 | so->tx.state = old_state; |
| 983 | if (so->tx.state == ISOTP_IDLE) | 997 | if (so->tx.state == ISOTP_IDLE) |
| @@ -1444,6 +1458,7 @@ static int isotp_init(struct sock *sk) · 460 unmodified lines | |||
| 1444 | so->txtimer.function = isotp_tx_timer_handler; | 1458 | so->txtimer.function = isotp_tx_timer_handler; |
| 1445 | 1459 | ||
| 1446 | init_waitqueue_head(&so->wait); | 1460 | init_waitqueue_head(&so->wait); |
| 1461 | spin_lock_init(&so->rx_lock); | ||
| 1447 | 1462 | ||
| 1448 | spin_lock(&isotp_notifier_lock); | 1463 | spin_lock(&isotp_notifier_lock); |
| 1449 | list_add_tail(&so->notifier, &isotp_notifier_list); | 1464 | list_add_tail(&so->notifier, &isotp_notifier_list); |
| @@ -246,6 +246,7 @@ enum { · 245 unmodified lines | |||
| 246 | Opt_cephx_sign_messages, | 246 | Opt_cephx_sign_messages, |
| 247 | Opt_tcp_nodelay, | 247 | Opt_tcp_nodelay, |
| 248 | Opt_abort_on_full, | 248 | Opt_abort_on_full, |
| 249 | Opt_rxbounce, | ||
| 249 | }; | 250 | }; |
| 250 | 251 | ||
| 251 | enum { | 252 | enum { |
| @@ -295,6 +296,7 @@ static const struct fs_parameter_spec ceph_parameters[] = { · 43 unmodified lines | |||
| 295 | fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout), | 296 | fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout), |
| 296 | fsparam_enum ("read_from_replica", Opt_read_from_replica, | 297 | fsparam_enum ("read_from_replica", Opt_read_from_replica, |
| 297 | ceph_param_read_from_replica), | 298 | ceph_param_read_from_replica), |
| 299 | fsparam_flag ("rxbounce", Opt_rxbounce), | ||
| 298 | fsparam_enum ("ms_mode", Opt_ms_mode, | 300 | fsparam_enum ("ms_mode", Opt_ms_mode, |
| 299 | ceph_param_ms_mode), | 301 | ceph_param_ms_mode), |
| 300 | fsparam_string ("secret", Opt_secret), | 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 | case Opt_abort_on_full: | 586 | case Opt_abort_on_full: |
| 585 | opt->flags |= CEPH_OPT_ABORT_ON_FULL; | 587 | opt->flags |= CEPH_OPT_ABORT_ON_FULL; |
| 586 | break; | 588 | break; |
| 589 | case Opt_rxbounce: | ||
| 590 | opt->flags |= CEPH_OPT_RXBOUNCE; | ||
| 591 | break; | ||
| 587 | 592 | ||
| 588 | default: | 593 | default: |
| 589 | BUG(); | 594 | BUG(); |
| @@ -660,6 +665,8 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client, · 70 unmodified lines | |||
| 660 | seq_puts(m, "notcp_nodelay,"); | 665 | seq_puts(m, "notcp_nodelay,"); |
| 661 | if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL)) | 666 | if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL)) |
| 662 | seq_puts(m, "abort_on_full,"); | 667 | seq_puts(m, "abort_on_full,"); |
| 668 | if (opt->flags & CEPH_OPT_RXBOUNCE) | ||
| 669 | seq_puts(m, "rxbounce,"); | ||
| 663 | 670 | ||
| 664 | if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) | 671 | if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) |
| 665 | seq_printf(m, "mount_timeout=%d,", | 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 | ceph_msg_put(con->out_msg); | 515 | ceph_msg_put(con->out_msg); |
| 516 | con->out_msg = NULL; | 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 | if (ceph_msgr2(from_msgr(con->msgr))) | 523 | if (ceph_msgr2(from_msgr(con->msgr))) |
| 520 | ceph_con_v2_reset_protocol(con); | 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 | static int read_partial_msg_data(struct ceph_connection *con) | 993 | static int read_partial_msg_data(struct ceph_connection *con) |
| 994 | { | 994 | { |
| 995 | struct ceph_msg *msg = con->in_msg; | 995 | struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; |
| 996 | struct ceph_msg_data_cursor *cursor = &msg->cursor; | ||
| 997 | bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); | 996 | bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); |
| 998 | struct page *page; | 997 | struct page *page; |
| 999 | size_t page_offset; | 998 | size_t page_offset; |
| @@ -1001,9 +1000,6 @@ static int read_partial_msg_data(struct ceph_connection *con) · 1 unmodified line | |||
| 1001 | u32 crc = 0; | 1000 | u32 crc = 0; |
| 1002 | int ret; | 1001 | int ret; |
| 1003 | 1002 | ||
| 1004 | if (!msg->num_data_items) | ||
| 1005 | return -EIO; | ||
| 1006 | |||
| 1007 | if (do_datacrc) | 1003 | if (do_datacrc) |
| 1008 | crc = con->in_data_crc; | 1004 | crc = con->in_data_crc; |
| 1009 | while (cursor->total_resid) { | 1005 | while (cursor->total_resid) { |
| @@ -1031,6 +1027,46 @@ static int read_partial_msg_data(struct ceph_connection *con) · 21 unmodified lines | |||
| 1031 | return 1; /* must return > 0 to indicate success */ | 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 | * read (part of) a message. | 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 | /* (page) data */ | 1178 | /* (page) data */ |
| 1143 | if (data_len) { | 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 | if (ret <= 0) | 1187 | if (ret <= 0) |
| 1146 | return ret; | 1188 | return ret; |
| 1147 | } | 1189 | } |
| @@ -57,8 +57,9 @@ · 56 unmodified lines | |||
| 57 | #define IN_S_HANDLE_CONTROL_REMAINDER 3 | 57 | #define IN_S_HANDLE_CONTROL_REMAINDER 3 |
| 58 | #define IN_S_PREPARE_READ_DATA 4 | 58 | #define IN_S_PREPARE_READ_DATA 4 |
| 59 | #define IN_S_PREPARE_READ_DATA_CONT 5 | 59 | #define IN_S_PREPARE_READ_DATA_CONT 5 |
| 60 | #define IN_S_HANDLE_EPILOGUE 6 | 60 | #define IN_S_PREPARE_READ_ENC_PAGE 6 |
| 61 | #define IN_S_FINISH_SKIP 7 | 61 | #define IN_S_HANDLE_EPILOGUE 7 |
| 62 | #define IN_S_FINISH_SKIP 8 | ||
| 62 | 63 | ||
| 63 | #define OUT_S_QUEUE_DATA 1 | 64 | #define OUT_S_QUEUE_DATA 1 |
| 64 | #define OUT_S_QUEUE_DATA_CONT 2 | 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 | padded_len(rem_len) + CEPH_GCM_TAG_LEN); | 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 | struct sg_table sgt = {}; | 1039 | struct sg_table sgt = {}; |
| 1040 | int tail_len; | ||
| 1038 | int ret; | 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 | ret = setup_message_sgs(&sgt, con->in_msg, FRONT_PAD(con->v2.in_buf), | 1050 | ret = setup_message_sgs(&sgt, con->in_msg, FRONT_PAD(con->v2.in_buf), |
| 1041 | MIDDLE_PAD(con->v2.in_buf), DATA_PAD(con->v2.in_buf), | 1051 | MIDDLE_PAD(con->v2.in_buf), DATA_PAD(con->v2.in_buf), |
| 1042 | con->v2.in_buf, true); | 1052 | con->v2.in_buf, true); |
| 1043 | if (ret) | 1053 | if (ret) |
| 1044 | goto out; | 1054 | goto out; |
| 1045 | 1055 | ||
| 1046 | ret = gcm_crypt(con, false, sgt.sgl, sgt.sgl, | 1056 | dout("%s con %p msg %p enc_page_cnt %d sg_cnt %d\n", __func__, con, |
| 1047 | tail_onwire_len(con->in_msg, true)); | 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 | out: | 1068 | out: |
| 1050 | sg_free_table(&sgt); | 1069 | sg_free_table(&sgt); |
| 1070 | sg_free_table(&enc_sgt); | ||
| 1051 | return ret; | 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 | return 0; | 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 | struct bio_vec bv; | 1758 | struct bio_vec bv; |
| 1739 | 1759 | ||
| 1740 | if (!con_secure(con)) | 1760 | con->in_data_crc = -1; |
| 1741 | con->in_data_crc = -1; | ||
| 1742 | ceph_msg_data_cursor_init(&con->v2.in_cursor, con->in_msg, | 1761 | ceph_msg_data_cursor_init(&con->v2.in_cursor, con->in_msg, |
| 1743 | data_len(con->in_msg)); | 1762 | data_len(con->in_msg)); |
| 1744 | 1763 | ||
| 1745 | get_bvec_at(&con->v2.in_cursor, &bv); | 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 | con->v2.in_state = IN_S_PREPARE_READ_DATA_CONT; | 1780 | con->v2.in_state = IN_S_PREPARE_READ_DATA_CONT; |
| 1781 | return 0; | ||
| 1748 | } | 1782 | } |
| 1749 | 1783 | ||
| 1750 | static void prepare_read_data_cont(struct ceph_connection *con) | 1784 | static void prepare_read_data_cont(struct ceph_connection *con) |
| 1751 | { | 1785 | { |
| 1752 | struct bio_vec bv; | 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 | con->in_data_crc = ceph_crc32c_page(con->in_data_crc, | 1798 | con->in_data_crc = ceph_crc32c_page(con->in_data_crc, |
| 1756 | con->v2.in_bvec.bv_page, | 1799 | con->v2.in_bvec.bv_page, |
| 1757 | con->v2.in_bvec.bv_offset, | 1800 | con->v2.in_bvec.bv_offset, |
| 1758 | con->v2.in_bvec.bv_len); | 1801 | con->v2.in_bvec.bv_len); |
| 1802 | } | ||
| 1759 | 1803 | ||
| 1760 | ceph_msg_data_advance(&con->v2.in_cursor, con->v2.in_bvec.bv_len); | 1804 | ceph_msg_data_advance(&con->v2.in_cursor, con->v2.in_bvec.bv_len); |
| 1761 | if (con->v2.in_cursor.total_resid) { | 1805 | if (con->v2.in_cursor.total_resid) { |
| 1762 | get_bvec_at(&con->v2.in_cursor, &bv); | 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 | WARN_ON(con->v2.in_state != IN_S_PREPARE_READ_DATA_CONT); | 1814 | WARN_ON(con->v2.in_state != IN_S_PREPARE_READ_DATA_CONT); |
| 1765 | return; | 1815 | return; |
| 1766 | } | 1816 | } |
| 1767 | 1817 | ||
| 1768 | /* | 1818 | /* |
| 1769 | * We've read all data. Prepare to read data padding (if any) | 1819 | * We've read all data. Prepare to read epilogue. |
| 1770 | * and epilogue. | ||
| 1771 | */ | 1820 | */ |
| 1772 | reset_in_kvecs(con); | 1821 | reset_in_kvecs(con); |
| 1773 | if (con_secure(con)) { | 1822 | add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_PLAIN_LEN); |
| 1774 | if (need_padding(data_len(con->in_msg))) | 1823 | con->v2.in_state = IN_S_HANDLE_EPILOGUE; |
| 1775 | add_in_kvec(con, DATA_PAD(con->v2.in_buf), | 1824 | } |
| 1776 | padding_len(data_len(con->in_msg))); | 1825 | |
| 1777 | add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_SECURE_LEN); | 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 | } else { | 1847 | } else { |
| 1779 | add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_PLAIN_LEN); | 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 | con->v2.in_state = IN_S_HANDLE_EPILOGUE; | 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 | static void __finish_skip(struct ceph_connection *con) | 1907 | static void __finish_skip(struct ceph_connection *con) |
| 1785 | { | 1908 | { |
| 1786 | con->in_seq++; | 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 | msg = con->in_msg; /* set in process_message_header() */ | 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 | if (front_len(msg)) { | 2715 | if (front_len(msg)) { |
| 2602 | WARN_ON(front_len(msg) > msg->front_alloc_len); | 2716 | WARN_ON(front_len(msg) > msg->front_alloc_len); |
| 2603 | add_in_kvec(con, msg->front.iov_base, front_len(msg)); | ||
| 2604 | msg->front.iov_len = front_len(msg); | 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 | } else { | 2718 | } else { |
| 2610 | msg->front.iov_len = 0; | 2719 | msg->front.iov_len = 0; |
| 2611 | } | 2720 | } |
| 2612 | if (middle_len(msg)) { | 2721 | if (middle_len(msg)) { |
| 2613 | WARN_ON(middle_len(msg) > msg->middle->alloc_len); | 2722 | WARN_ON(middle_len(msg) > msg->middle->alloc_len); |
| 2614 | add_in_kvec(con, msg->middle->vec.iov_base, middle_len(msg)); | ||
| 2615 | msg->middle->vec.iov_len = middle_len(msg); | 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 | } else if (msg->middle) { | 2724 | } else if (msg->middle) { |
| 2621 | msg->middle->vec.iov_len = 0; | 2725 | msg->middle->vec.iov_len = 0; |
| 2622 | } | 2726 | } |
| 2623 | 2727 | ||
| 2624 | if (data_len(msg)) { | 2728 | if (!front_len(msg) && !middle_len(msg) && !data_len(msg)) |
| 2625 | con->v2.in_state = IN_S_PREPARE_READ_DATA; | 2729 | return process_message(con); |
| 2626 | } else { | 2730 | |
| 2627 | add_in_kvec(con, con->v2.in_buf, | 2731 | if (con_secure(con)) |
| 2628 | con_secure(con) ? CEPH_EPILOGUE_SECURE_LEN : | 2732 | return prepare_read_tail_secure(con); |
| 2629 | CEPH_EPILOGUE_PLAIN_LEN); | 2733 | |
| 2630 | con->v2.in_state = IN_S_HANDLE_EPILOGUE; | 2734 | return prepare_read_tail_plain(con); |
| 2631 | } | ||
| 2632 | return 0; | ||
| 2633 | } | 2735 | } |
| 2634 | 2736 | ||
| 2635 | static int handle_preamble(struct ceph_connection *con) | 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 | int ret; | 2819 | int ret; |
| 2718 | 2820 | ||
| 2719 | if (con_secure(con)) { | 2821 | if (con_secure(con)) { |
| 2720 | ret = decrypt_message(con); | 2822 | ret = decrypt_tail(con); |
| 2721 | if (ret) { | 2823 | if (ret) { |
| 2722 | if (ret == -EBADMSG) | 2824 | if (ret == -EBADMSG) |
| 2723 | con->error_msg = "integrity error, bad epilogue auth tag"; | 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 | ret = handle_control_remainder(con); | 2887 | ret = handle_control_remainder(con); |
| 2786 | break; | 2888 | break; |
| 2787 | case IN_S_PREPARE_READ_DATA: | 2889 | case IN_S_PREPARE_READ_DATA: |
| 2788 | prepare_read_data(con); | 2890 | ret = prepare_read_data(con); |
| 2789 | ret = 0; | ||
| 2790 | break; | 2891 | break; |
| 2791 | case IN_S_PREPARE_READ_DATA_CONT: | 2892 | case IN_S_PREPARE_READ_DATA_CONT: |
| 2792 | prepare_read_data_cont(con); | 2893 | prepare_read_data_cont(con); |
| 2793 | ret = 0; | 2894 | ret = 0; |
| 2794 | break; | 2895 | break; |
| 2896 | case IN_S_PREPARE_READ_ENC_PAGE: | ||
| 2897 | prepare_read_enc_page(con); | ||
| 2898 | ret = 0; | ||
| 2899 | break; | ||
| 2795 | case IN_S_HANDLE_EPILOGUE: | 2900 | case IN_S_HANDLE_EPILOGUE: |
| 2796 | ret = handle_epilogue(con); | 2901 | ret = handle_epilogue(con); |
| 2797 | break; | 2902 | break; |
| @@ -3326,20 +3431,16 @@ void ceph_con_v2_revoke(struct ceph_connection *con) · 528 unmodified lines | |||
| 3326 | 3431 | ||
| 3327 | static void revoke_at_prepare_read_data(struct ceph_connection *con) | 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 | int resid; | 3435 | int resid; |
| 3331 | 3436 | ||
| 3437 | WARN_ON(con_secure(con)); | ||
| 3332 | WARN_ON(!data_len(con->in_msg)); | 3438 | WARN_ON(!data_len(con->in_msg)); |
| 3333 | WARN_ON(!iov_iter_is_kvec(&con->v2.in_iter)); | 3439 | WARN_ON(!iov_iter_is_kvec(&con->v2.in_iter)); |
| 3334 | resid = iov_iter_count(&con->v2.in_iter); | 3440 | resid = iov_iter_count(&con->v2.in_iter); |
| 3335 | WARN_ON(!resid); | 3441 | WARN_ON(!resid); |
| 3336 | 3442 | ||
| 3337 | if (con_secure(con)) | 3443 | remaining = data_len(con->in_msg) + CEPH_EPILOGUE_PLAIN_LEN; |
| 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 | |||
| 3343 | dout("%s con %p resid %d remaining %d\n", __func__, con, resid, | 3444 | dout("%s con %p resid %d remaining %d\n", __func__, con, resid, |
| 3344 | remaining); | 3445 | remaining); |
| 3345 | con->v2.in_iter.count -= resid; | 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 | static void revoke_at_prepare_read_data_cont(struct ceph_connection *con) | 3451 | static void revoke_at_prepare_read_data_cont(struct ceph_connection *con) |
| 3351 | { | 3452 | { |
| 3352 | int recved, resid; /* current piece of data */ | 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 | WARN_ON(!data_len(con->in_msg)); | 3457 | WARN_ON(!data_len(con->in_msg)); |
| 3356 | WARN_ON(!iov_iter_is_bvec(&con->v2.in_iter)); | 3458 | WARN_ON(!iov_iter_is_bvec(&con->v2.in_iter)); |
| 3357 | resid = iov_iter_count(&con->v2.in_iter); | 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 | ceph_msg_data_advance(&con->v2.in_cursor, recved); | 3465 | ceph_msg_data_advance(&con->v2.in_cursor, recved); |
| 3364 | WARN_ON(resid > con->v2.in_cursor.total_resid); | 3466 | WARN_ON(resid > con->v2.in_cursor.total_resid); |
| 3365 | 3467 | ||
| 3366 | if (con_secure(con)) | 3468 | remaining = CEPH_EPILOGUE_PLAIN_LEN; |
| 3367 | remaining = padding_len(data_len(con->in_msg)) + | ||
| 3368 | CEPH_EPILOGUE_SECURE_LEN; | ||
| 3369 | else | ||
| 3370 | remaining = CEPH_EPILOGUE_PLAIN_LEN; | ||
| 3371 | |||
| 3372 | dout("%s con %p total_resid %zu remaining %d\n", __func__, con, | 3469 | dout("%s con %p total_resid %zu remaining %d\n", __func__, con, |
| 3373 | con->v2.in_cursor.total_resid, remaining); | 3470 | con->v2.in_cursor.total_resid, remaining); |
| 3374 | con->v2.in_iter.count -= resid; | 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 | con->v2.in_state = IN_S_FINISH_SKIP; | 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 | static void revoke_at_handle_epilogue(struct ceph_connection *con) | 3492 | static void revoke_at_handle_epilogue(struct ceph_connection *con) |
| 3380 | { | 3493 | { |
| 3381 | int resid; | 3494 | int resid; |
| 3382 | 3495 | ||
| 3383 | WARN_ON(!iov_iter_is_kvec(&con->v2.in_iter)); | ||
| 3384 | resid = iov_iter_count(&con->v2.in_iter); | 3496 | resid = iov_iter_count(&con->v2.in_iter); |
| 3385 | WARN_ON(!resid); | 3497 | WARN_ON(!resid); |
| 3386 | 3498 | ||
| @@ -3399,6 +3511,9 @@ void ceph_con_v2_revoke_incoming(struct ceph_connection *con) · 12 unmodified lines | |||
| 3399 | case IN_S_PREPARE_READ_DATA_CONT: | 3511 | case IN_S_PREPARE_READ_DATA_CONT: |
| 3400 | revoke_at_prepare_read_data_cont(con); | 3512 | revoke_at_prepare_read_data_cont(con); |
| 3401 | break; | 3513 | break; |
| 3514 | case IN_S_PREPARE_READ_ENC_PAGE: | ||
| 3515 | revoke_at_prepare_read_enc_page(con); | ||
| 3516 | break; | ||
| 3402 | case IN_S_HANDLE_EPILOGUE: | 3517 | case IN_S_HANDLE_EPILOGUE: |
| 3403 | revoke_at_handle_epilogue(con); | 3518 | revoke_at_handle_epilogue(con); |
| 3404 | break; | 3519 | break; |
| @@ -3432,6 +3547,13 @@ void ceph_con_v2_reset_protocol(struct ceph_connection *con) · 27 unmodified lines | |||
| 3432 | clear_out_sign_kvecs(con); | 3547 | clear_out_sign_kvecs(con); |
| 3433 | free_conn_bufs(con); | 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 | if (con->v2.out_enc_pages) { | 3557 | if (con->v2.out_enc_pages) { |
| 3436 | WARN_ON(!con->v2.out_enc_page_cnt); | 3558 | WARN_ON(!con->v2.out_enc_page_cnt); |
| 3437 | ceph_release_page_vector(con->v2.out_enc_pages, | 3559 | ceph_release_page_vector(con->v2.out_enc_pages, |
| @@ -681,7 +681,7 @@ exit: · 680 unmodified lines | |||
| 681 | * while trying to recycle fragments on __skb_frag_unref() we need | 681 | * while trying to recycle fragments on __skb_frag_unref() we need |
| 682 | * to make one SKB responsible for triggering the recycle path. | 682 | * to make one SKB responsible for triggering the recycle path. |
| 683 | * So disable the recycling bit if an SKB is cloned and we have | 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 | * Eventually the last SKB will have the recycling bit set and it's | 685 | * Eventually the last SKB will have the recycling bit set and it's |
| 686 | * dataref set to 0, which will trigger the recycling | 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 | void dsa_switch_shutdown(struct dsa_switch *ds) | 1784 | void dsa_switch_shutdown(struct dsa_switch *ds) |
| 1785 | { | 1785 | { |
| 1786 | struct net_device *master, *slave_dev; | 1786 | struct net_device *master, *slave_dev; |
| 1787 | LIST_HEAD(unregister_list); | ||
| 1788 | struct dsa_port *dp; | 1787 | struct dsa_port *dp; |
| 1789 | 1788 | ||
| 1790 | mutex_lock(&dsa2_mutex); | 1789 | mutex_lock(&dsa2_mutex); |
| @@ -1795,25 +1794,13 @@ void dsa_switch_shutdown(struct dsa_switch *ds) · 4 unmodified lines | |||
| 1795 | slave_dev = dp->slave; | 1794 | slave_dev = dp->slave; |
| 1796 | 1795 | ||
| 1797 | netdev_upper_dev_unlink(master, slave_dev); | 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 | rtnl_unlock(); | 1805 | rtnl_unlock(); |
| 1819 | mutex_unlock(&dsa2_mutex); | 1806 | mutex_unlock(&dsa2_mutex); |
| @@ -256,7 +256,9 @@ static int __net_init ipmr_rules_init(struct net *net) · 255 unmodified lines | |||
| 256 | return 0; | 256 | return 0; |
| 257 | 257 | ||
| 258 | err2: | 258 | err2: |
| 259 | rtnl_lock(); | ||
| 259 | ipmr_free_table(mrt); | 260 | ipmr_free_table(mrt); |
| 261 | rtnl_unlock(); | ||
| 260 | err1: | 262 | err1: |
| 261 | fib_rules_unregister(ops); | 263 | fib_rules_unregister(ops); |
| 262 | return err; | 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 | static struct sk_buff *tcp_build_frag(struct sock *sk, int size_goal, int flags, | 955 | static struct sk_buff *tcp_build_frag(struct sock *sk, int size_goal, int flags, |
| 940 | struct page *page, int offset, size_t *size) | 956 | struct page *page, int offset, size_t *size) |
| 941 | { | 957 | { |
| @@ -971,7 +987,7 @@ new_segment: · 29 unmodified lines | |||
| 971 | tcp_mark_push(tp, skb); | 987 | tcp_mark_push(tp, skb); |
| 972 | goto new_segment; | 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 | return NULL; | 991 | return NULL; |
| 976 | 992 | ||
| 977 | if (can_coalesce) { | 993 | if (can_coalesce) { |
| @@ -1319,19 +1335,8 @@ new_segment: · 341 unmodified lines | |||
| 1319 | 1335 | ||
| 1320 | copy = min_t(int, copy, pfrag->size - pfrag->offset); | 1336 | copy = min_t(int, copy, pfrag->size - pfrag->offset); |
| 1321 | 1337 | ||
| 1322 | /* skb changing from pure zc to mixed, must charge zc */ | 1338 | if (tcp_downgrade_zcopy_pure(sk, skb) || |
| 1323 | if (unlikely(skb_zcopy_pure(skb))) { | 1339 | !sk_wmem_schedule(sk, copy)) |
| 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)) | ||
| 1335 | goto wait_for_space; | 1340 | goto wait_for_space; |
| 1336 | 1341 | ||
| 1337 | err = skb_copy_to_page_nocache(sk, &msg->msg_iter, skb, | 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 | return 0; | 243 | return 0; |
| 244 | 244 | ||
| 245 | err2: | 245 | err2: |
| 246 | rtnl_lock(); | ||
| 246 | ip6mr_free_table(mrt); | 247 | ip6mr_free_table(mrt); |
| 248 | rtnl_unlock(); | ||
| 247 | err1: | 249 | err1: |
| 248 | fib_rules_unregister(ops); | 250 | fib_rules_unregister(ops); |
| 249 | return err; | 251 | return err; |
| @@ -1607,6 +1607,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 1606 unmodified lines | |||
| 1607 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 1607 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 1608 | struct mpls_dev *mdev; | 1608 | struct mpls_dev *mdev; |
| 1609 | unsigned int flags; | 1609 | unsigned int flags; |
| 1610 | int err; | ||
| 1610 | 1611 | ||
| 1611 | if (event == NETDEV_REGISTER) { | 1612 | if (event == NETDEV_REGISTER) { |
| 1612 | mdev = mpls_add_dev(dev); | 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 | return NOTIFY_OK; | 1622 | return NOTIFY_OK; |
| 1622 | 1623 | ||
| 1623 | switch (event) { | 1624 | switch (event) { |
| 1624 | int err; | ||
| 1625 | 1625 | ||
| 1626 | case NETDEV_DOWN: | 1626 | case NETDEV_DOWN: |
| 1627 | err = mpls_ifdown(dev, event); | 1627 | err = mpls_ifdown(dev, event); |
| @@ -925,6 +925,7 @@ out: · 924 unmodified lines | |||
| 925 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, | 925 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, |
| 926 | struct mptcp_pm_addr_entry *entry) | 926 | struct mptcp_pm_addr_entry *entry) |
| 927 | { | 927 | { |
| 928 | int addrlen = sizeof(struct sockaddr_in); | ||
| 928 | struct sockaddr_storage addr; | 929 | struct sockaddr_storage addr; |
| 929 | struct mptcp_sock *msk; | 930 | struct mptcp_sock *msk; |
| 930 | struct socket *ssock; | 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 | mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family); | 952 | mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family); |
| 952 | err = kernel_bind(ssock, (struct sockaddr *)&addr, | 953 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
| 953 | sizeof(struct sockaddr_in)); | 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 | if (err) { | 958 | if (err) { |
| 955 | pr_warn("kernel_bind error, err=%d", err); | 959 | pr_warn("kernel_bind error, err=%d", err); |
| 956 | goto out; | 960 | goto out; |
| @@ -2321,7 +2321,8 @@ ctnetlink_create_conntrack(struct net *net, · 2320 unmodified lines | |||
| 2321 | if (helper->from_nlattr) | 2321 | if (helper->from_nlattr) |
| 2322 | helper->from_nlattr(helpinfo, ct); | 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 | RCU_INIT_POINTER(help->helper, helper); | 2326 | RCU_INIT_POINTER(help->helper, helper); |
| 2326 | } | 2327 | } |
| 2327 | } else { | 2328 | } else { |
| @@ -489,6 +489,15 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 488 unmodified lines | |||
| 489 | pr_debug("Setting vtag %x for dir %d\n", | 489 | pr_debug("Setting vtag %x for dir %d\n", |
| 490 | ih->init_tag, !dir); | 490 | ih->init_tag, !dir); |
| 491 | ct->proto.sctp.vtag[!dir] = ih->init_tag; | 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 | ct->proto.sctp.state = new_state; | 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 | static bool tcp_in_window(struct nf_conn *ct, | 475 | static bool tcp_in_window(struct nf_conn *ct, |
| 450 | enum ip_conntrack_dir dir, | 476 | enum ip_conntrack_dir dir, |
| 451 | unsigned int index, | 477 | unsigned int index, |
| @@ -499,24 +525,9 @@ static bool tcp_in_window(struct nf_conn *ct, · 47 unmodified lines | |||
| 499 | * Initialize sender data. | 525 | * Initialize sender data. |
| 500 | */ | 526 | */ |
| 501 | if (tcph->syn) { | 527 | if (tcph->syn) { |
| 502 | /* | 528 | tcp_init_sender(sender, receiver, |
| 503 | * SYN-ACK in reply to a SYN | 529 | skb, dataoff, tcph, |
| 504 | * or SYN from reply direction in simultaneous open. | 530 | end, win); |
| 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; | ||
| 520 | if (!tcph->ack) | 531 | if (!tcph->ack) |
| 521 | /* Simultaneous open */ | 532 | /* Simultaneous open */ |
| 522 | return true; | 533 | return true; |
| @@ -560,6 +571,18 @@ static bool tcp_in_window(struct nf_conn *ct, · 37 unmodified lines | |||
| 560 | sender->td_maxwin = (win == 0 ? 1 : win); | 571 | sender->td_maxwin = (win == 0 ? 1 : win); |
| 561 | 572 | ||
| 562 | tcp_options(skb, dataoff, tcph, sender); | 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 | if (!(tcph->ack)) { | 588 | if (!(tcph->ack)) { |
| @@ -167,7 +167,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt, · 166 unmodified lines | |||
| 167 | { | 167 | { |
| 168 | struct tcphdr *tcph; | 168 | struct tcphdr *tcph; |
| 169 | 169 | ||
| 170 | if (pkt->tprot != IPPROTO_TCP) | 170 | if (pkt->tprot != IPPROTO_TCP || pkt->fragoff) |
| 171 | return NULL; | 171 | return NULL; |
| 172 | 172 | ||
| 173 | tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt), sizeof(*tcph), buffer); | 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 | unsigned int thoff = nft_thoff(pkt); | 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 | return -1; | 87 | return -1; |
| 88 | 88 | ||
| 89 | switch (pkt->tprot) { | 89 | switch (pkt->tprot) { |
| @@ -147,7 +147,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 57 unmodified lines | |||
| 147 | offset = skb_network_offset(skb); | 147 | offset = skb_network_offset(skb); |
| 148 | break; | 148 | break; |
| 149 | case NFT_PAYLOAD_TRANSPORT_HEADER: | 149 | case NFT_PAYLOAD_TRANSPORT_HEADER: |
| 150 | if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) | 150 | if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff) |
| 151 | goto err; | 151 | goto err; |
| 152 | offset = nft_thoff(pkt); | 152 | offset = nft_thoff(pkt); |
| 153 | break; | 153 | break; |
| @@ -688,7 +688,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr, · 534 unmodified lines | |||
| 688 | offset = skb_network_offset(skb); | 688 | offset = skb_network_offset(skb); |
| 689 | break; | 689 | break; |
| 690 | case NFT_PAYLOAD_TRANSPORT_HEADER: | 690 | case NFT_PAYLOAD_TRANSPORT_HEADER: |
| 691 | if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) | 691 | if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff) |
| 692 | goto err; | 692 | goto err; |
| 693 | offset = nft_thoff(pkt); | 693 | offset = nft_thoff(pkt); |
| 694 | break; | 694 | break; |
| @@ -728,7 +728,8 @@ static void nft_payload_set_eval(const struct nft_expr *expr, · 33 unmodified lines | |||
| 728 | if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP && | 728 | if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP && |
| 729 | pkt->tprot == IPPROTO_SCTP && | 729 | pkt->tprot == IPPROTO_SCTP && |
| 730 | skb->ip_summed != CHECKSUM_PARTIAL) { | 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 | goto err; | 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 | new_pe->type = SMC_PNET_ETH; | 368 | new_pe->type = SMC_PNET_ETH; |
| 369 | memcpy(new_pe->pnet_name, pnet_name, SMC_MAX_PNETID_LEN); | 369 | memcpy(new_pe->pnet_name, pnet_name, SMC_MAX_PNETID_LEN); |
| 370 | strncpy(new_pe->eth_name, eth_name, IFNAMSIZ); | 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 | rc = -EEXIST; | 371 | rc = -EEXIST; |
| 375 | new_netdev = true; | 372 | new_netdev = true; |
| 376 | write_lock(&pnettable->lock); | 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 | if (new_netdev) { | 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 | list_add_tail(&new_pe->list, &pnettable->pnetlist); | 387 | list_add_tail(&new_pe->list, &pnettable->pnetlist); |
| 386 | write_unlock(&pnettable->lock); | 388 | write_unlock(&pnettable->lock); |
| 387 | } else { | 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 | sock = container_of(xprt, struct sock_xprt, xprt); | 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 | goto out; | 121 | goto out; |
| 120 | 122 | ||
| 121 | ret = sprintf(buf, "%pISc\n", &saddr); | 123 | ret = sprintf(buf, "%pISc\n", &saddr); |
| 122 | out: | 124 | out: |
| 125 | mutex_unlock(&sock->recv_mutex); | ||
| 123 | xprt_put(xprt); | 126 | xprt_put(xprt); |
| 124 | return ret + 1; | 127 | return ret + 1; |
| 125 | } | 128 | } |
| @@ -413,6 +413,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) · 412 unmodified lines | |||
| 413 | IB_POLL_WORKQUEUE); | 413 | IB_POLL_WORKQUEUE); |
| 414 | if (IS_ERR(ep->re_attr.send_cq)) { | 414 | if (IS_ERR(ep->re_attr.send_cq)) { |
| 415 | rc = PTR_ERR(ep->re_attr.send_cq); | 415 | rc = PTR_ERR(ep->re_attr.send_cq); |
| 416 | ep->re_attr.send_cq = NULL; | ||
| 416 | goto out_destroy; | 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 | IB_POLL_WORKQUEUE); | 422 | IB_POLL_WORKQUEUE); |
| 422 | if (IS_ERR(ep->re_attr.recv_cq)) { | 423 | if (IS_ERR(ep->re_attr.recv_cq)) { |
| 423 | rc = PTR_ERR(ep->re_attr.recv_cq); | 424 | rc = PTR_ERR(ep->re_attr.recv_cq); |
| 425 | ep->re_attr.recv_cq = NULL; | ||
| 424 | goto out_destroy; | 426 | goto out_destroy; |
| 425 | } | 427 | } |
| 426 | ep->re_receive_count = 0; | 428 | ep->re_receive_count = 0; |
| @@ -459,6 +461,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) · 32 unmodified lines | |||
| 459 | ep->re_pd = ib_alloc_pd(device, 0); | 461 | ep->re_pd = ib_alloc_pd(device, 0); |
| 460 | if (IS_ERR(ep->re_pd)) { | 462 | if (IS_ERR(ep->re_pd)) { |
| 461 | rc = PTR_ERR(ep->re_pd); | 463 | rc = PTR_ERR(ep->re_pd); |
| 464 | ep->re_pd = NULL; | ||
| 462 | goto out_destroy; | 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 | unsigned short get_srcport(struct rpc_xprt *xprt) | 1641 | unsigned short get_srcport(struct rpc_xprt *xprt) |
| 1642 | { | 1642 | { |
| 1643 | struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt); | 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 | EXPORT_SYMBOL(get_srcport); | 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 | struct tipc_msg *hdr = buf_msg(skb); | 2200 | struct tipc_msg *hdr = buf_msg(skb); |
| 2201 | struct tipc_gap_ack_blks *ga = NULL; | 2201 | struct tipc_gap_ack_blks *ga = NULL; |
| 2202 | bool reply = msg_probe(hdr), retransmitted = false; | 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 | u16 peers_snd_nxt = msg_next_sent(hdr); | 2204 | u16 peers_snd_nxt = msg_next_sent(hdr); |
| 2205 | u16 peers_tol = msg_link_tolerance(hdr); | 2205 | u16 peers_tol = msg_link_tolerance(hdr); |
| 2206 | u16 peers_prio = msg_linkprio(hdr); | 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 | void *data; | 2214 | void *data; |
| 2215 | 2215 | ||
| 2216 | trace_tipc_proto_rcv(skb, false, l->name); | 2216 | trace_tipc_proto_rcv(skb, false, l->name); |
| 2217 | |||
| 2218 | if (dlen > U16_MAX) | ||
| 2219 | goto exit; | ||
| 2220 | |||
| 2217 | if (tipc_link_is_blocked(l) || !xmitq) | 2221 | if (tipc_link_is_blocked(l) || !xmitq) |
| 2218 | goto exit; | 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 | /* Receive Gap ACK blocks from peer if any */ | 2314 | /* Receive Gap ACK blocks from peer if any */ |
| 2311 | glen = tipc_get_gap_ack_blks(&ga, l, hdr, true); | 2315 | glen = tipc_get_gap_ack_blks(&ga, l, hdr, true); |
| 2312 | 2316 | if(glen > dlen) | |
| 2317 | break; | ||
| 2313 | tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr, | 2318 | tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr, |
| 2314 | &l->mon_state, l->bearer_id); | 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 | state->probing = false; | 496 | state->probing = false; |
| 497 | 497 | ||
| 498 | /* Sanity check received domain record */ | 498 | /* Sanity check received domain record */ |
| 499 | if (new_member_cnt > MAX_MON_DOMAIN) | ||
| 500 | return; | ||
| 499 | if (dlen < dom_rec_len(arrv_dom, 0)) | 501 | if (dlen < dom_rec_len(arrv_dom, 0)) |
| 500 | return; | 502 | return; |
| 501 | if (dlen != dom_rec_len(arrv_dom, new_member_cnt)) | 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 | pr_warn_ratelimited("Failed to remove binding %u,%u from %u\n", | 313 | pr_warn_ratelimited("Failed to remove binding %u,%u from %u\n", |
| 314 | ua.sr.type, ua.sr.lower, node); | 314 | ua.sr.type, ua.sr.lower, node); |
| 315 | } else { | 315 | } else { |
| 316 | pr_warn("Unrecognized name table message received\n"); | 316 | pr_warn_ratelimited("Unknown name table message received\n"); |
| 317 | } | 317 | } |
| 318 | return false; | 318 | return false; |
| 319 | } | 319 | } |
| @@ -109,22 +109,25 @@ int asymmetric_verify(struct key *keyring, const char *sig, · 108 unmodified lines | |||
| 109 | 109 | ||
| 110 | pk = asymmetric_key_public_key(key); | 110 | pk = asymmetric_key_public_key(key); |
| 111 | pks.pkey_algo = pk->pkey_algo; | 111 | pks.pkey_algo = pk->pkey_algo; |
| 112 | if (!strcmp(pk->pkey_algo, "rsa")) | 112 | if (!strcmp(pk->pkey_algo, "rsa")) { |
| 113 | pks.encoding = "pkcs1"; | 113 | pks.encoding = "pkcs1"; |
| 114 | else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) | 114 | } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) { |
| 115 | /* edcsa-nist-p192 etc. */ | 115 | /* edcsa-nist-p192 etc. */ |
| 116 | pks.encoding = "x962"; | 116 | pks.encoding = "x962"; |
| 117 | else if (!strcmp(pk->pkey_algo, "ecrdsa") || | 117 | } else if (!strcmp(pk->pkey_algo, "ecrdsa") || |
| 118 | !strcmp(pk->pkey_algo, "sm2")) | 118 | !strcmp(pk->pkey_algo, "sm2")) { |
| 119 | pks.encoding = "raw"; | 119 | pks.encoding = "raw"; |
| 120 | else | 120 | } else { |
| 121 | return -ENOPKG; | 121 | ret = -ENOPKG; |
| 122 | goto out; | ||
| 123 | } | ||
| 122 | 124 | ||
| 123 | pks.digest = (u8 *)data; | 125 | pks.digest = (u8 *)data; |
| 124 | pks.digest_size = datalen; | 126 | pks.digest_size = datalen; |
| 125 | pks.s = hdr->sig; | 127 | pks.s = hdr->sig; |
| 126 | pks.s_size = siglen; | 128 | pks.s_size = siglen; |
| 127 | ret = verify_signature(key, &pks); | 129 | ret = verify_signature(key, &pks); |
| 130 | out: | ||
| 128 | key_put(key); | 131 | key_put(key); |
| 129 | pr_debug("%s() = %d\n", __func__, ret); | 132 | pr_debug("%s() = %d\n", __func__, ret); |
| 130 | return ret; | 133 | return ret; |
| @@ -496,12 +496,12 @@ int __init ima_fs_init(void) · 495 unmodified lines | |||
| 496 | 496 | ||
| 497 | return 0; | 497 | return 0; |
| 498 | out: | 498 | out: |
| 499 | securityfs_remove(ima_policy); | ||
| 499 | securityfs_remove(violations); | 500 | securityfs_remove(violations); |
| 500 | securityfs_remove(runtime_measurements_count); | 501 | securityfs_remove(runtime_measurements_count); |
| 501 | securityfs_remove(ascii_runtime_measurements); | 502 | securityfs_remove(ascii_runtime_measurements); |
| 502 | securityfs_remove(binary_runtime_measurements); | 503 | securityfs_remove(binary_runtime_measurements); |
| 503 | securityfs_remove(ima_symlink); | 504 | securityfs_remove(ima_symlink); |
| 504 | securityfs_remove(ima_dir); | 505 | securityfs_remove(ima_dir); |
| 505 | securityfs_remove(ima_policy); | ||
| 506 | return -1; | 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 | rcu_read_lock(); | 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 | if (entry->action & MEASURE) | 1978 | if (entry->action & MEASURE) |
| 1971 | seq_puts(m, pt(Opt_measure)); | 1979 | seq_puts(m, pt(Opt_measure)); |
| 1972 | if (entry->action & DONT_MEASURE) | 1980 | if (entry->action & DONT_MEASURE) |
| @@ -29,6 +29,7 @@ static struct ima_template_desc builtin_templates[] = { · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | static LIST_HEAD(defined_templates); | 30 | static LIST_HEAD(defined_templates); |
| 31 | static DEFINE_SPINLOCK(template_list); | 31 | static DEFINE_SPINLOCK(template_list); |
| 32 | static int template_setup_done; | ||
| 32 | 33 | ||
| 33 | static const struct ima_template_field supported_fields[] = { | 34 | static const struct ima_template_field supported_fields[] = { |
| 34 | {.field_id = "d", .field_init = ima_eventdigest_init, | 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 | struct ima_template_desc *template_desc; | 102 | struct ima_template_desc *template_desc; |
| 102 | int template_len = strlen(str); | 103 | int template_len = strlen(str); |
| 103 | 104 | ||
| 104 | if (ima_template) | 105 | if (template_setup_done) |
| 105 | return 1; | 106 | return 1; |
| 106 | 107 | ||
| 107 | ima_init_template_list(); | 108 | if (!ima_template) |
| 109 | ima_init_template_list(); | ||
| 108 | 110 | ||
| 109 | /* | 111 | /* |
| 110 | * Verify that a template with the supplied name exists. | 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 | ima_template = template_desc; | 132 | ima_template = template_desc; |
| 133 | template_setup_done = 1; | ||
| 131 | return 1; | 134 | return 1; |
| 132 | } | 135 | } |
| 133 | __setup("ima_template=", ima_template_setup); | 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 | int num_templates = ARRAY_SIZE(builtin_templates); | 140 | int num_templates = ARRAY_SIZE(builtin_templates); |
| 138 | 141 | ||
| 139 | if (ima_template) | 142 | if (template_setup_done) |
| 140 | return 1; | 143 | return 1; |
| 141 | 144 | ||
| 142 | if (template_desc_init_fields(str, NULL, NULL) < 0) { | 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 | builtin_templates[num_templates - 1].fmt = str; | 151 | builtin_templates[num_templates - 1].fmt = str; |
| 149 | ima_template = builtin_templates + num_templates - 1; | 152 | ima_template = builtin_templates + num_templates - 1; |
| 153 | template_setup_done = 1; | ||
| 150 | 154 | ||
| 151 | return 1; | 155 | return 1; |
| 152 | } | 156 | } |
| @@ -45,6 +45,8 @@ void integrity_audit_message(int audit_msgno, struct inode *inode, · 44 unmodified lines | |||
| 45 | return; | 45 | return; |
| 46 | 46 | ||
| 47 | ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno); | 47 | ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno); |
| 48 | if (!ab) | ||
| 49 | return; | ||
| 48 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", | 50 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", |
| 49 | task_pid_nr(current), | 51 | task_pid_nr(current), |
| 50 | from_kuid(&init_user_ns, current_uid()), | 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 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | 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 | * snd_pcm_stream_unlock_irqrestore - Unlock the PCM stream | 189 | * snd_pcm_stream_unlock_irqrestore - Unlock the PCM stream |
| 177 | * @substream: PCM substream | 190 | * @substream: PCM substream |
| @@ -50,11 +50,11 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, int i) · 49 unmodified lines | |||
| 50 | static int | 50 | static int |
| 51 | sdw_intel_scan_controller(struct sdw_intel_acpi_info *info) | 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 | int ret, i; | 54 | int ret, i; |
| 55 | u8 count; | 55 | u8 count; |
| 56 | 56 | ||
| 57 | if (acpi_bus_get_device(info->handle, &adev)) | 57 | if (!adev) |
| 58 | return -EINVAL; | 58 | return -EINVAL; |
| 59 | 59 | ||
| 60 | /* Found controller, find links supported */ | 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 | void *cdata, void **return_value) | 119 | void *cdata, void **return_value) |
| 120 | { | 120 | { |
| 121 | struct sdw_intel_acpi_info *info = cdata; | 121 | struct sdw_intel_acpi_info *info = cdata; |
| 122 | struct acpi_device *adev; | ||
| 123 | acpi_status status; | 122 | acpi_status status; |
| 124 | u64 adr; | 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 | if (ACPI_FAILURE(status)) | 126 | if (ACPI_FAILURE(status)) |
| 128 | return AE_OK; /* keep going */ | 127 | return AE_OK; /* keep going */ |
| 129 | 128 | ||
| 130 | if (acpi_bus_get_device(handle, &adev)) { | 129 | if (!acpi_fetch_acpi_dev(handle)) { |
| 131 | pr_err("%s: Couldn't find ACPI handle\n", __func__); | 130 | pr_err("%s: Couldn't find ACPI handle\n", __func__); |
| 132 | return AE_NOT_FOUND; | 131 | return AE_NOT_FOUND; |
| 133 | } | 132 | } |
| @@ -981,7 +981,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, · 980 unmodified lines | |||
| 981 | int id = HDA_FIXUP_ID_NOT_SET; | 981 | int id = HDA_FIXUP_ID_NOT_SET; |
| 982 | const char *name = NULL; | 982 | const char *name = NULL; |
| 983 | const char *type = NULL; | 983 | const char *type = NULL; |
| 984 | int vendor, device; | 984 | unsigned int vendor, device; |
| 985 | 985 | ||
| 986 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) | 986 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
| 987 | return; | 987 | return; |
| @@ -3000,6 +3000,10 @@ void snd_hda_codec_shutdown(struct hda_codec *codec) · 2999 unmodified lines | |||
| 3000 | { | 3000 | { |
| 3001 | struct hda_pcm *cpcm; | 3001 | struct hda_pcm *cpcm; |
| 3002 | 3002 | ||
| 3003 | /* Skip the shutdown if codec is not registered */ | ||
| 3004 | if (!codec->registered) | ||
| 3005 | return; | ||
| 3006 | |||
| 3003 | list_for_each_entry(cpcm, &codec->pcm_list_head, list) | 3007 | list_for_each_entry(cpcm, &codec->pcm_list_head, list) |
| 3004 | snd_pcm_suspend_all(cpcm->pcm); | 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 | free_kctls(spec); | 91 | free_kctls(spec); |
| 92 | snd_array_free(&spec->paths); | 92 | snd_array_free(&spec->paths); |
| 93 | snd_array_free(&spec->loopback_list); | 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 | enum led_brightness), | 3928 | enum led_brightness), |
| 3923 | bool micmute) | 3929 | bool micmute) |
| 3924 | { | 3930 | { |
| 3931 | struct hda_gen_spec *spec = codec->spec; | ||
| 3925 | struct led_classdev *cdev; | 3932 | struct led_classdev *cdev; |
| 3933 | int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE; | ||
| 3934 | int err; | ||
| 3926 | 3935 | ||
| 3927 | cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); | 3936 | cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); |
| 3928 | if (!cdev) | 3937 | if (!cdev) |
| @@ -3932,10 +3941,14 @@ static int create_mute_led_cdev(struct hda_codec *codec, · 3 unmodified lines | |||
| 3932 | cdev->max_brightness = 1; | 3941 | cdev->max_brightness = 1; |
| 3933 | cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute"; | 3942 | cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute"; |
| 3934 | cdev->brightness_set_blocking = callback; | 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 | cdev->flags = LED_CORE_SUSPENDRESUME; | 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 | struct hda_jack_callback *cb); | 294 | struct hda_jack_callback *cb); |
| 295 | void (*mic_autoswitch_hook)(struct hda_codec *codec, | 295 | void (*mic_autoswitch_hook)(struct hda_codec *codec, |
| 296 | struct hda_jack_callback *cb); | 296 | struct hda_jack_callback *cb); |
| 297 | |||
| 298 | /* leds */ | ||
| 299 | struct led_classdev *led_cdevs[NUM_AUDIO_LEDS]; | ||
| 297 | }; | 300 | }; |
| 298 | 301 | ||
| 299 | /* values for add_stereo_mix_input flag */ | 302 | /* values for add_stereo_mix_input flag */ |
| @@ -98,6 +98,7 @@ struct alc_spec { · 97 unmodified lines | |||
| 98 | unsigned int gpio_mic_led_mask; | 98 | unsigned int gpio_mic_led_mask; |
| 99 | struct alc_coef_led mute_led_coef; | 99 | struct alc_coef_led mute_led_coef; |
| 100 | struct alc_coef_led mic_led_coef; | 100 | struct alc_coef_led mic_led_coef; |
| 101 | struct mutex coef_mutex; | ||
| 101 | 102 | ||
| 102 | hda_nid_t headset_mic_pin; | 103 | hda_nid_t headset_mic_pin; |
| 103 | hda_nid_t headphone_mic_pin; | 104 | hda_nid_t headphone_mic_pin; |
| @@ -137,8 +138,8 @@ struct alc_spec { · 33 unmodified lines | |||
| 137 | * COEF access helper functions | 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 | static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, |
| 141 | unsigned int coef_idx) | 142 | unsigned int coef_idx) |
| 142 | { | 143 | { |
| 143 | unsigned int val; | 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 | return val; | 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 | #define alc_read_coef_idx(codec, coef_idx) \ | 163 | #define alc_read_coef_idx(codec, coef_idx) \ |
| 151 | alc_read_coefex_idx(codec, 0x20, coef_idx) | 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, | 166 | static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, |
| 154 | unsigned int coef_idx, unsigned int coef_val) | 167 | unsigned int coef_idx, unsigned int coef_val) |
| 155 | { | 168 | { |
| 156 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); | 169 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); |
| 157 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val); | 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 | #define alc_write_coef_idx(codec, coef_idx, coef_val) \ | 183 | #define alc_write_coef_idx(codec, coef_idx, coef_val) \ |
| 161 | alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) | 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 | static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | 197 | static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, |
| 164 | unsigned int coef_idx, unsigned int mask, | 198 | unsigned int coef_idx, unsigned int mask, |
| 165 | unsigned int bits_set) | 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) | 203 | mutex_lock(&spec->coef_mutex); |
| 170 | alc_write_coefex_idx(codec, nid, coef_idx, | 204 | __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set); |
| 171 | (val & ~mask) | bits_set); | 205 | mutex_unlock(&spec->coef_mutex); |
| 172 | } | 206 | } |
| 173 | 207 | ||
| 174 | #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ | 208 | #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ |
| @@ -201,13 +235,17 @@ struct coef_fw { · 26 unmodified lines | |||
| 201 | static void alc_process_coef_fw(struct hda_codec *codec, | 235 | static void alc_process_coef_fw(struct hda_codec *codec, |
| 202 | const struct coef_fw *fw) | 236 | const struct coef_fw *fw) |
| 203 | { | 237 | { |
| 238 | struct alc_spec *spec = codec->spec; | ||
| 239 | |||
| 240 | mutex_lock(&spec->coef_mutex); | ||
| 204 | for (; fw->nid; fw++) { | 241 | for (; fw->nid; fw++) { |
| 205 | if (fw->mask == (unsigned short)-1) | 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 | else | 244 | else |
| 208 | alc_update_coefex_idx(codec, fw->nid, fw->idx, | 245 | __alc_update_coefex_idx(codec, fw->nid, fw->idx, |
| 209 | fw->mask, fw->val); | 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 | codec->spdif_status_reset = 1; | 1191 | codec->spdif_status_reset = 1; |
| 1154 | codec->forced_resume = 1; | 1192 | codec->forced_resume = 1; |
| 1155 | codec->patch_ops = alc_patch_ops; | 1193 | codec->patch_ops = alc_patch_ops; |
| 1194 | mutex_init(&spec->coef_mutex); | ||
| 1156 | 1195 | ||
| 1157 | err = alc_codec_rename_from_preset(codec); | 1196 | err = alc_codec_rename_from_preset(codec); |
| 1158 | if (err < 0) { | 1197 | if (err < 0) { |
| @@ -2125,6 +2164,7 @@ static void alc1220_fixup_gb_x570(struct hda_codec *codec, · 966 unmodified lines | |||
| 2125 | { | 2164 | { |
| 2126 | static const hda_nid_t conn1[] = { 0x0c }; | 2165 | static const hda_nid_t conn1[] = { 0x0c }; |
| 2127 | static const struct coef_fw gb_x570_coefs[] = { | 2166 | static const struct coef_fw gb_x570_coefs[] = { |
| 2167 | WRITE_COEF(0x07, 0x03c0), | ||
| 2128 | WRITE_COEF(0x1a, 0x01c1), | 2168 | WRITE_COEF(0x1a, 0x01c1), |
| 2129 | WRITE_COEF(0x1b, 0x0202), | 2169 | WRITE_COEF(0x1b, 0x0202), |
| 2130 | WRITE_COEF(0x43, 0x3005), | 2170 | WRITE_COEF(0x43, 0x3005), |
| @@ -2551,7 +2591,8 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { · 420 unmodified lines | |||
| 2551 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), | 2591 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), |
| 2552 | SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), | 2592 | SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), |
| 2553 | SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570), | 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 | SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), | 2596 | SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), |
| 2556 | SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), | 2597 | SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), |
| 2557 | SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950), | 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 | {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, | 2667 | {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, |
| 2627 | {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"}, | 2668 | {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"}, |
| 2628 | {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, | 2669 | {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, |
| 2670 | {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"}, | ||
| 2629 | {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"}, | 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 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), | 9011 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), |
| 8970 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), | 9012 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), |
| 8971 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), | 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 | SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), | 9015 | SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), |
| 8973 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 9016 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
| 8974 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), | 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 | static struct snd_soc_codec_conf rt1019_conf[] = { | 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 | .name_prefix = "Left", | 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 | .name_prefix = "Right", | 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 | struct device_node *codec_node = | 1668 | struct device_node *codec_node = |
| 1669 | of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec"); | 1669 | of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec"); |
| 1670 | if (!codec_node) | ||
| 1671 | return -ENODEV; | ||
| 1670 | 1672 | ||
| 1671 | pdev->dev.of_node = codec_node; | 1673 | pdev->dev.of_node = codec_node; |
| 1672 | 1674 | ||
| @@ -277,7 +277,7 @@ struct hdmi_codec_priv { · 276 unmodified lines | |||
| 277 | bool busy; | 277 | bool busy; |
| 278 | struct snd_soc_jack *jack; | 278 | struct snd_soc_jack *jack; |
| 279 | unsigned int jack_status; | 279 | unsigned int jack_status; |
| 280 | u8 iec_status[5]; | 280 | u8 iec_status[AES_IEC958_STATUS_SIZE]; |
| 281 | }; | 281 | }; |
| 282 | 282 | ||
| 283 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { | 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 | int reg, b2_reg; | 2688 | int reg, b2_reg; |
| 2689 | 2689 | ||
| 2690 | /* Address does not automatically update if reading */ | 2690 | /* Address does not automatically update if reading */ |
| 2691 | reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_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 + 16 * iir_idx; | 2692 | b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; |
| 2693 | 2693 | ||
| 2694 | snd_soc_component_write(component, reg, | 2694 | snd_soc_component_write(component, reg, |
| 2695 | ((band_idx * BAND_MAX + coeff_idx) * | 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 | static void set_iir_band_coeff(struct snd_soc_component *component, | 2718 | static void set_iir_band_coeff(struct snd_soc_component *component, |
| 2719 | int iir_idx, int band_idx, uint32_t value) | 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 | snd_soc_component_write(component, reg, (value & 0xFF)); | 2723 | snd_soc_component_write(component, reg, (value & 0xFF)); |
| 2724 | snd_soc_component_write(component, reg, (value >> 8) & 0xFF); | 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 | int iir_idx = ctl->iir_idx; | 2739 | int iir_idx = ctl->iir_idx; |
| 2740 | int band_idx = ctl->band_idx; | 2740 | int band_idx = ctl->band_idx; |
| 2741 | u32 coeff[BAND_MAX]; | 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 | memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); | 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 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); | 64 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
| 65 | struct max9759 *priv = snd_soc_component_get_drvdata(c); | 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 | return -EINVAL; | 69 | return -EINVAL; |
| 69 | 70 | ||
| 70 | priv->gain = ucontrol->value.integer.value[0]; | 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 | struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, | 59 | struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, |
| 60 | jd_check_work.work); | 60 | jd_check_work.work); |
| 61 | 61 | ||
| 62 | if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) | 62 | if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK) |
| 63 | & RT5682_JDH_RS_MASK) { | ||
| 64 | /* jack out */ | 63 | /* jack out */ |
| 65 | rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); | 64 | mod_delayed_work(system_power_efficient_wq, |
| 66 | 65 | &rt5682->jack_detect_work, 0); | |
| 67 | snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, | 66 | else |
| 68 | SND_JACK_HEADSET | | ||
| 69 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
| 70 | SND_JACK_BTN_2 | SND_JACK_BTN_3); | ||
| 71 | } else { | ||
| 72 | schedule_delayed_work(&rt5682->jd_check_work, 500); | 67 | schedule_delayed_work(&rt5682->jd_check_work, 500); |
| 73 | } | ||
| 74 | } | 68 | } |
| 75 | 69 | ||
| 76 | static irqreturn_t rt5682_irq(int irq, void *data) | 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 | mutex_init(&rt5682->calibrate_mutex); | 194 | mutex_init(&rt5682->calibrate_mutex); |
| 201 | mutex_init(&rt5682->jdet_mutex); | ||
| 202 | rt5682_calibrate(rt5682); | 195 | rt5682_calibrate(rt5682); |
| 203 | 196 | ||
| 204 | rt5682_apply_patch_list(rt5682, &i2c->dev); | 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 | * Returns detect status. | 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 | struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); | 927 | struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); |
| 928 | struct snd_soc_dapm_context *dapm = &component->dapm; | 928 | struct snd_soc_dapm_context *dapm = &component->dapm; |
| 929 | unsigned int val, count; | 929 | unsigned int val, count; |
| 930 | 930 | ||
| 931 | if (jack_insert) { | 931 | if (jack_insert) { |
| 932 | snd_soc_dapm_mutex_lock(dapm); | ||
| 933 | |||
| 934 | snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, | 932 | snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, |
| 935 | RT5682_PWR_VREF2 | RT5682_PWR_MB, | 933 | RT5682_PWR_VREF2 | RT5682_PWR_MB, |
| 936 | RT5682_PWR_VREF2 | RT5682_PWR_MB); | 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 | snd_soc_component_update_bits(component, RT5682_MICBIAS_2, | 979 | snd_soc_component_update_bits(component, RT5682_MICBIAS_2, |
| 982 | RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, | 980 | RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, |
| 983 | RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); | 981 | RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); |
| 984 | |||
| 985 | snd_soc_dapm_mutex_unlock(dapm); | ||
| 986 | } else { | 982 | } else { |
| 987 | rt5682_enable_push_button_irq(component, false); | 983 | rt5682_enable_push_button_irq(component, false); |
| 988 | snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, | 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 | dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type); | 1007 | dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type); |
| 1012 | return rt5682->jack_type; | 1008 | return rt5682->jack_type; |
| 1013 | } | 1009 | } |
| 1014 | EXPORT_SYMBOL_GPL(rt5682_headset_detect); | ||
| 1015 | 1010 | ||
| 1016 | static int rt5682_set_jack_detect(struct snd_soc_component *component, | 1011 | static int rt5682_set_jack_detect(struct snd_soc_component *component, |
| 1017 | struct snd_soc_jack *hs_jack, void *data) | 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 | struct rt5682_priv *rt5682 = | 1090 | struct rt5682_priv *rt5682 = |
| 1096 | container_of(work, struct rt5682_priv, jack_detect_work.work); | 1091 | container_of(work, struct rt5682_priv, jack_detect_work.work); |
| 1092 | struct snd_soc_dapm_context *dapm; | ||
| 1097 | int val, btn_type; | 1093 | int val, btn_type; |
| 1098 | 1094 | ||
| 1099 | while (!rt5682->component) | 1095 | while (!rt5682->component) |
| @@ -1102,7 +1098,9 @@ void rt5682_jack_detect_handler(struct work_struct *work) · 2 unmodified lines | |||
| 1102 | while (!rt5682->component->card->instantiated) | 1098 | while (!rt5682->component->card->instantiated) |
| 1103 | usleep_range(10000, 15000); | 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 | mutex_lock(&rt5682->calibrate_mutex); | 1104 | mutex_lock(&rt5682->calibrate_mutex); |
| 1107 | 1105 | ||
| 1108 | val = snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) | 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 | rt5682->irq_work_delay_time = 50; | 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 | snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, | 1166 | snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, |
| 1166 | SND_JACK_HEADSET | | 1167 | SND_JACK_HEADSET | |
| 1167 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | 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 | else | 1175 | else |
| 1175 | cancel_delayed_work_sync(&rt5682->jd_check_work); | 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 | EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler); | 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 | struct snd_soc_component *component = | 1525 | struct snd_soc_component *component = |
| 1528 | snd_soc_dapm_to_component(w->dapm); | 1526 | snd_soc_dapm_to_component(w->dapm); |
| 1529 | struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); | ||
| 1530 | 1527 | ||
| 1531 | switch (event) { | 1528 | switch (event) { |
| 1532 | case SND_SOC_DAPM_PRE_PMU: | 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 | RT5682_DEPOP_1, 0x60, 0x60); | 1535 | RT5682_DEPOP_1, 0x60, 0x60); |
| 1539 | snd_soc_component_update_bits(component, | 1536 | snd_soc_component_update_bits(component, |
| 1540 | RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); | 1537 | RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); |
| 1541 | |||
| 1542 | mutex_lock(&rt5682->jdet_mutex); | ||
| 1543 | |||
| 1544 | snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, | 1538 | snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, |
| 1545 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, | 1539 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, |
| 1546 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN); | 1540 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN); |
| 1547 | usleep_range(5000, 10000); | 1541 | usleep_range(5000, 10000); |
| 1548 | snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, | 1542 | snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, |
| 1549 | RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L); | 1543 | RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L); |
| 1550 | |||
| 1551 | mutex_unlock(&rt5682->jdet_mutex); | ||
| 1552 | break; | 1544 | break; |
| 1553 | 1545 | ||
| 1554 | case SND_SOC_DAPM_POST_PMD: | 1546 | case SND_SOC_DAPM_POST_PMD: |
| @@ -1463,7 +1463,6 @@ struct rt5682_priv { · 1462 unmodified lines | |||
| 1463 | 1463 | ||
| 1464 | int jack_type; | 1464 | int jack_type; |
| 1465 | int irq_work_delay_time; | 1465 | int irq_work_delay_time; |
| 1466 | struct mutex jdet_mutex; | ||
| 1467 | }; | 1466 | }; |
| 1468 | 1467 | ||
| 1469 | extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES]; | 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 | void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev); | 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 | void rt5682_jack_detect_handler(struct work_struct *work); | 1475 | void rt5682_jack_detect_handler(struct work_struct *work); |
| 1478 | 1476 | ||
| 1479 | bool rt5682_volatile_register(struct device *dev, unsigned int reg); | 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 | return 0; | 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 | return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id], | 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 | enable); | 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 | WCD938X_EAR_GAIN_MASK, | 2559 | WCD938X_EAR_GAIN_MASK, |
| 2564 | ucontrol->value.integer.value[0]); | 2560 | ucontrol->value.integer.value[0]); |
| 2565 | 2561 | ||
| 2566 | return 0; | 2562 | return 1; |
| 2567 | } | 2563 | } |
| 2568 | 2564 | ||
| 2569 | static int wcd938x_get_compander(struct snd_kcontrol *kcontrol, | 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 | struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); | 2589 | struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); |
| 2594 | struct wcd938x_sdw_priv *wcd; | 2590 | struct wcd938x_sdw_priv *wcd; |
| 2595 | int value = ucontrol->value.integer.value[0]; | 2591 | int value = ucontrol->value.integer.value[0]; |
| 2592 | int portidx; | ||
| 2596 | struct soc_mixer_control *mc; | 2593 | struct soc_mixer_control *mc; |
| 2597 | bool hphr; | 2594 | bool hphr; |
| 2598 | 2595 | ||
| @@ -2606,12 +2603,14 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, · 7 unmodified lines | |||
| 2606 | else | 2603 | else |
| 2607 | wcd938x->comp1_enable = value; | 2604 | wcd938x->comp1_enable = value; |
| 2608 | 2605 | ||
| 2606 | portidx = wcd->ch_info[mc->reg].port_num; | ||
| 2607 | |||
| 2609 | if (value) | 2608 | if (value) |
| 2610 | wcd938x_connect_port(wcd, mc->reg, true); | 2609 | wcd938x_connect_port(wcd, portidx, mc->reg, true); |
| 2611 | else | 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 | static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol, | 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 | struct wcd938x_sdw_priv *wcd; | 2881 | struct wcd938x_sdw_priv *wcd; |
| 2883 | struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; | 2882 | struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; |
| 2884 | int dai_id = mixer->shift; | 2883 | int dai_id = mixer->shift; |
| 2885 | int portidx = mixer->reg; | 2884 | int portidx, ch_idx = mixer->reg; |
| 2885 | |||
| 2886 | 2886 | ||
| 2887 | wcd = wcd938x->sdw_priv[dai_id]; | 2887 | wcd = wcd938x->sdw_priv[dai_id]; |
| 2888 | portidx = wcd->ch_info[ch_idx].port_num; | ||
| 2888 | 2889 | ||
| 2889 | ucontrol->value.integer.value[0] = wcd->port_enable[portidx]; | 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 | struct wcd938x_sdw_priv *wcd; | 2900 | struct wcd938x_sdw_priv *wcd; |
| 2900 | struct soc_mixer_control *mixer = | 2901 | struct soc_mixer_control *mixer = |
| 2901 | (struct soc_mixer_control *)kcontrol->private_value; | 2902 | (struct soc_mixer_control *)kcontrol->private_value; |
| 2902 | int portidx = mixer->reg; | 2903 | int ch_idx = mixer->reg; |
| 2904 | int portidx; | ||
| 2903 | int dai_id = mixer->shift; | 2905 | int dai_id = mixer->shift; |
| 2904 | bool enable; | 2906 | bool enable; |
| 2905 | 2907 | ||
| 2906 | wcd = wcd938x->sdw_priv[dai_id]; | 2908 | wcd = wcd938x->sdw_priv[dai_id]; |
| 2907 | 2909 | ||
| 2910 | portidx = wcd->ch_info[ch_idx].port_num; | ||
| 2908 | if (ucontrol->value.integer.value[0]) | 2911 | if (ucontrol->value.integer.value[0]) |
| 2909 | enable = true; | 2912 | enable = true; |
| 2910 | else | 2913 | else |
| @@ -2912,9 +2915,9 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, · 1 unmodified line | |||
| 2912 | 2915 | ||
| 2913 | wcd->port_enable[portidx] = enable; | 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 | dev_err(&op->dev, "platform_device_alloc() failed\n"); | 93 | dev_err(&op->dev, "platform_device_alloc() failed\n"); |
| 94 | 94 | ||
| 95 | ret = platform_device_add(pdata->codec_device); | 95 | ret = platform_device_add(pdata->codec_device); |
| 96 | if (ret) | 96 | if (ret) { |
| 97 | dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); | 97 | dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); |
| 98 | platform_device_put(pdata->codec_device); | ||
| 99 | } | ||
| 98 | 100 | ||
| 99 | ret = snd_soc_register_card(card); | 101 | ret = snd_soc_register_card(card); |
| 100 | if (ret) | 102 | if (ret) { |
| 101 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); | 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 | platform_set_drvdata(op, pdata); | 108 | platform_set_drvdata(op, pdata); |
| 104 | |||
| 105 | return ret; | 109 | return ret; |
| 110 | |||
| 106 | } | 111 | } |
| 107 | 112 | ||
| 108 | static int pcm030_fabric_remove(struct platform_device *op) | 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 | .hw_params = asoc_simple_hw_params, | 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 | static int asoc_simple_parse_dai(struct device_node *node, | 55 | static int asoc_simple_parse_dai(struct device_node *node, |
| 32 | struct snd_soc_dai_link_component *dlc, | 56 | struct snd_soc_dai_link_component *dlc, |
| 33 | int *is_single_link) | 57 | int *is_single_link) |
| @@ -289,7 +313,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, · 255 unmodified lines | |||
| 289 | if (ret < 0) | 313 | if (ret < 0) |
| 290 | goto dai_link_of_err; | 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 | if (ret < 0) | 317 | if (ret < 0) |
| 294 | goto dai_link_of_err; | 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 | config SND_SOC_MT8195_MT6359_RT1011_RT5682 | 217 | config SND_SOC_MT8195_MT6359_RT1011_RT5682 |
| 218 | tristate "ASoC Audio driver for MT8195 with MT6359 RT1011 RT5682 codec" | 218 | tristate "ASoC Audio driver for MT8195 with MT6359 RT1011 RT5682 codec" |
| 219 | depends on I2C | 219 | depends on I2C && GPIOLIB |
| 220 | depends on SND_SOC_MT8195 && MTK_PMIC_WRAP | 220 | depends on SND_SOC_MT8195 && MTK_PMIC_WRAP |
| 221 | select SND_SOC_MT6359 | 221 | select SND_SOC_MT6359 |
| 222 | select SND_SOC_RT1011 | 222 | select SND_SOC_RT1011 |
| @@ -308,8 +308,11 @@ static int q6apm_dai_close(struct snd_soc_component *component, · 307 unmodified lines | |||
| 308 | struct snd_pcm_runtime *runtime = substream->runtime; | 308 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 309 | struct q6apm_dai_rtd *prtd = runtime->private_data; | 309 | struct q6apm_dai_rtd *prtd = runtime->private_data; |
| 310 | 310 | ||
| 311 | q6apm_graph_stop(prtd->graph); | 311 | if (prtd->state) { /* only stop graph that is started */ |
| 312 | q6apm_unmap_memory_regions(prtd->graph, substream->stream); | 312 | q6apm_graph_stop(prtd->graph); |
| 313 | q6apm_unmap_memory_regions(prtd->graph, substream->stream); | ||
| 314 | } | ||
| 315 | |||
| 313 | q6apm_graph_close(prtd->graph); | 316 | q6apm_graph_close(prtd->graph); |
| 314 | prtd->graph = NULL; | 317 | prtd->graph = NULL; |
| 315 | kfree(prtd); | 318 | kfree(prtd); |
| @@ -55,16 +55,13 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine); · 54 unmodified lines | |||
| 55 | static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, | 55 | static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, |
| 56 | void *context, void **ret) | 56 | void *context, void **ret) |
| 57 | { | 57 | { |
| 58 | struct acpi_device *adev; | 58 | struct acpi_device *adev = acpi_fetch_acpi_dev(handle); |
| 59 | acpi_status status; | 59 | acpi_status status; |
| 60 | struct snd_soc_acpi_package_context *pkg_ctx = context; | 60 | struct snd_soc_acpi_package_context *pkg_ctx = context; |
| 61 | 61 | ||
| 62 | pkg_ctx->data_valid = false; | 62 | pkg_ctx->data_valid = false; |
| 63 | 63 | ||
| 64 | if (acpi_bus_get_device(handle, &adev)) | 64 | if (adev && adev->status.present && adev->status.functional) { |
| 65 | return AE_OK; | ||
| 66 | |||
| 67 | if (adev->status.present && adev->status.functional) { | ||
| 68 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 65 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
| 69 | union acpi_object *myobj = NULL; | 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 | if (sign_bit) | 316 | if (sign_bit) |
| 317 | mask = BIT(sign_bit + 1) - 1; | 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 | if (invert) | 327 | if (invert) |
| 321 | val = max - val; | 328 | val = max - val; |
| 322 | val_mask = mask << shift; | 329 | val_mask = mask << shift; |
| 323 | val = val << shift; | 330 | val = val << shift; |
| 324 | if (snd_soc_volsw_is_stereo(mc)) { | 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 | if (invert) | 340 | if (invert) |
| 327 | val2 = max - val2; | 341 | val2 = max - val2; |
| 328 | if (reg == reg2) { | 342 | if (reg == reg2) { |
| @@ -409,8 +423,15 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, · 80 unmodified lines | |||
| 409 | int err = 0; | 423 | int err = 0; |
| 410 | unsigned int val, val_mask; | 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 | val_mask = mask << shift; | 433 | val_mask = mask << shift; |
| 413 | val = (ucontrol->value.integer.value[0] + min) & mask; | 434 | val = (val + min) & mask; |
| 414 | val = val << shift; | 435 | val = val << shift; |
| 415 | 436 | ||
| 416 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | 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 | long val = ucontrol->value.integer.value[0]; | 879 | long val = ucontrol->value.integer.value[0]; |
| 859 | unsigned int i; | 880 | unsigned int i; |
| 860 | 881 | ||
| 882 | if (val < mc->min || val > mc->max) | ||
| 883 | return -EINVAL; | ||
| 861 | if (invert) | 884 | if (invert) |
| 862 | val = max - val; | 885 | val = max - val; |
| 863 | val &= mask; | 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 | snd_pcm_stream_lock_irq(snd_soc_dpcm_get_substream(rtd, stream)); | 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) \ | 49 | #define snd_soc_dpcm_stream_lock_irqsave_nested(rtd, stream, flags) \ |
| 50 | snd_pcm_stream_lock_irqsave(snd_soc_dpcm_get_substream(rtd, stream), flags) | 50 | snd_pcm_stream_lock_irqsave_nested(snd_soc_dpcm_get_substream(rtd, stream), flags) |
| 51 | 51 | ||
| 52 | static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd, | 52 | static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd, |
| 53 | int stream) | 53 | int stream) |
| @@ -1268,6 +1268,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, · 1214 unmodified lines | |||
| 1268 | void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) | 1268 | void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) |
| 1269 | { | 1269 | { |
| 1270 | struct snd_soc_dpcm *dpcm, *d; | 1270 | struct snd_soc_dpcm *dpcm, *d; |
| 1271 | LIST_HEAD(deleted_dpcms); | ||
| 1271 | 1272 | ||
| 1272 | snd_soc_dpcm_mutex_assert_held(fe); | 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 | /* BEs still alive need new FE */ | 1288 | /* BEs still alive need new FE */ |
| 1288 | dpcm_be_reparent(fe, dpcm->be, stream); | 1289 | dpcm_be_reparent(fe, dpcm->be, stream); |
| 1289 | 1290 | ||
| 1290 | dpcm_remove_debugfs_state(dpcm); | ||
| 1291 | |||
| 1292 | list_del(&dpcm->list_be); | 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 | list_del(&dpcm->list_fe); | 1299 | list_del(&dpcm->list_fe); |
| 1300 | dpcm_remove_debugfs_state(dpcm); | ||
| 1294 | kfree(dpcm); | 1301 | kfree(dpcm); |
| 1295 | } | 1302 | } |
| 1296 | snd_soc_dpcm_stream_unlock_irq(fe, stream); | ||
| 1297 | } | 1303 | } |
| 1298 | 1304 | ||
| 1299 | /* get BE for DAI widget and stream */ | 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 | be = dpcm->be; | 2100 | be = dpcm->be; |
| 2095 | be_substream = snd_soc_dpcm_get_substream(be, stream); | 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 | /* is this op for this BE ? */ | 2105 | /* is this op for this BE ? */ |
| 2100 | if (!snd_soc_dpcm_be_can_update(fe, be, stream)) | 2106 | if (!snd_soc_dpcm_be_can_update(fe, be, stream)) |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | |||
| 37 | #define XLNX_AUD_XFER_COUNT 0x28 | 37 | #define XLNX_AUD_XFER_COUNT 0x28 |
| 38 | #define XLNX_AUD_CH_STS_START 0x2C | 38 | #define XLNX_AUD_CH_STS_START 0x2C |
| 39 | #define XLNX_BYTES_PER_CH 0x44 | 39 | #define XLNX_BYTES_PER_CH 0x44 |
| 40 | #define XLNX_AUD_ALIGN_BYTES 64 | ||
| 40 | 41 | ||
| 41 | #define AUD_STS_IOC_IRQ_MASK BIT(31) | 42 | #define AUD_STS_IOC_IRQ_MASK BIT(31) |
| 42 | #define AUD_STS_CH_STS_MASK BIT(29) | 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 | snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); | 369 | snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); |
| 369 | runtime->private_data = stream_data; | 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 | err = snd_pcm_hw_constraint_step(runtime, 0, | 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 | if (err) { | 376 | if (err) { |
| 375 | dev_err(component->dev, | 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 | return err; | 398 | return err; |
| 378 | } | 399 | } |
| 379 | 400 | ||
| @@ -1527,6 +1527,10 @@ error: · 1526 unmodified lines | |||
| 1527 | usb_audio_err(chip, | 1527 | usb_audio_err(chip, |
| 1528 | "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 1528 | "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
| 1529 | UAC_GET_CUR, validx, idx, cval->val_type); | 1529 | UAC_GET_CUR, validx, idx, cval->val_type); |
| 1530 | |||
| 1531 | if (val) | ||
| 1532 | *val = 0; | ||
| 1533 | |||
| 1530 | return filter_error(cval, ret); | 1534 | return filter_error(cval, ret); |
| 1531 | } | 1535 | } |
| 1532 | 1536 | ||
| @@ -84,7 +84,7 @@ · 83 unmodified lines | |||
| 84 | * combination. | 84 | * combination. |
| 85 | */ | 85 | */ |
| 86 | { | 86 | { |
| 87 | USB_DEVICE(0x041e, 0x4095), | 87 | USB_AUDIO_DEVICE(0x041e, 0x4095), |
| 88 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | 88 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { |
| 89 | .ifnum = QUIRK_ANY_INTERFACE, | 89 | .ifnum = QUIRK_ANY_INTERFACE, |
| 90 | .type = QUIRK_COMPOSITE, | 90 | .type = QUIRK_COMPOSITE, |
| @@ -299,7 +299,9 @@ · 298 unmodified lines | |||
| 299 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ | 299 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ |
| 300 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ | 300 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ |
| 301 | #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ | 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 | #define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */ | 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 | /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ | 306 | /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ |
| 305 | #define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ | 307 | #define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ |
| @@ -1624,9 +1624,6 @@ struct kvm_enc_region { · 1623 unmodified lines | |||
| 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) | 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) |
| 1625 | #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) | 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 | struct kvm_s390_pv_sec_parm { | 1627 | struct kvm_s390_pv_sec_parm { |
| 1631 | __u64 origin; | 1628 | __u64 origin; |
| 1632 | __u64 length; | 1629 | __u64 length; |
| @@ -2048,4 +2045,7 @@ struct kvm_stats_desc { · 415 unmodified lines | |||
| 2048 | 2045 | ||
| 2049 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) | 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 | #endif /* __LINUX_KVM_H */ | 2051 | #endif /* __LINUX_KVM_H */ |
| @@ -1332,9 +1332,9 @@ union perf_mem_data_src { · 1331 unmodified lines | |||
| 1332 | 1332 | ||
| 1333 | /* hop level */ | 1333 | /* hop level */ |
| 1334 | #define PERF_MEM_HOPS_0 0x01 /* remote core, same node */ | 1334 | #define PERF_MEM_HOPS_0 0x01 /* remote core, same node */ |
| 1335 | #define PERF_MEM_HOPS_1 0x02 /* remote node, same socket */ | 1335 | #define PERF_MEM_HOPS_1 0x02 /* remote node, same socket */ |
| 1336 | #define PERF_MEM_HOPS_2 0x03 /* remote socket, same board */ | 1336 | #define PERF_MEM_HOPS_2 0x03 /* remote socket, same board */ |
| 1337 | #define PERF_MEM_HOPS_3 0x04 /* remote board */ | 1337 | #define PERF_MEM_HOPS_3 0x04 /* remote board */ |
| 1338 | /* 5-7 available */ | 1338 | /* 5-7 available */ |
| 1339 | #define PERF_MEM_HOPS_SHIFT 43 | 1339 | #define PERF_MEM_HOPS_SHIFT 43 |
| 1340 | 1340 | ||
| @@ -272,4 +272,7 @@ struct prctl_mm_map { · 271 unmodified lines | |||
| 272 | # define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1 | 272 | # define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1 |
| 273 | # define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2 | 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 | #endif /* _LINUX_PRCTL_H */ | 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 | struct snd_aes_iec958 { | 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 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ | 63 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ |
| 62 | unsigned char pad; /* nothing */ | 64 | unsigned char pad; /* nothing */ |
| 63 | unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ | 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 | #define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ | 204 | #define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ |
| 203 | #define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ | 205 | #define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ |
| 204 | #define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ | 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 | #define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) | 212 | #define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) |
| 206 | #define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) | 213 | #define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) |
| 207 | #define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) | 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 | #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ | 307 | #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ |
| 301 | #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ | 308 | #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ |
| 302 | #define SNDRV_PCM_INFO_EXPLICIT_SYNC 0x10000000 /* needs explicit sync of pointers and data */ | 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 | #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ | 311 | #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ |
| 305 | #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ | 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 | #include <internal/lib.h> | 13 | #include <internal/lib.h> |
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/math64.h> | 15 | #include <linux/math64.h> |
| 16 | #include <linux/stringify.h> | ||
| 16 | #include "internal.h" | 17 | #include "internal.h" |
| 17 | 18 | ||
| 18 | void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev, | 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 | return low | ((u64)high) << 32; | 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 | #else | 395 | #else |
| 298 | static u64 read_perf_counter(unsigned int counter __maybe_unused) { return 0; } | 396 | static u64 read_perf_counter(unsigned int counter __maybe_unused) { return 0; } |
| 299 | static u64 read_timestamp(void) { return 0; } | 397 | static u64 read_timestamp(void) { return 0; } |
| @@ -130,6 +130,9 @@ static int test_stat_user_read(int event) · 129 unmodified lines | |||
| 130 | struct perf_event_attr attr = { | 130 | struct perf_event_attr attr = { |
| 131 | .type = PERF_TYPE_HARDWARE, | 131 | .type = PERF_TYPE_HARDWARE, |
| 132 | .config = event, | 132 | .config = event, |
| 133 | #ifdef __aarch64__ | ||
| 134 | .config1 = 0x2, /* Request user access */ | ||
| 135 | #endif | ||
| 133 | }; | 136 | }; |
| 134 | int err, i; | 137 | int err, i; |
| 135 | 138 | ||
| @@ -150,7 +153,7 @@ static int test_stat_user_read(int event) · 14 unmodified lines | |||
| 150 | pc = perf_evsel__mmap_base(evsel, 0, 0); | 153 | pc = perf_evsel__mmap_base(evsel, 0, 0); |
| 151 | __T("failed to get mmapped address", pc); | 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 | __T("userspace counter access not supported", pc->cap_user_rdpmc); | 157 | __T("userspace counter access not supported", pc->cap_user_rdpmc); |
| 155 | __T("userspace counter access not enabled", pc->index); | 158 | __T("userspace counter access not enabled", pc->index); |
| 156 | __T("userspace counter width not set", pc->pmc_width >= 32); | 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 | static inline const char *call_dest_name(struct instruction *insn) | 2855 | static inline const char *call_dest_name(struct instruction *insn) |
| 2856 | { | 2856 | { |
| 2857 | static char pvname[16]; | 2857 | static char pvname[19]; |
| 2858 | struct reloc *rel; | 2858 | struct reloc *rel; |
| 2859 | int idx; | 2859 | int idx; |
| 2860 | 2860 | ||
| @@ -1115,6 +1115,7 @@ enum perf_ftrace_subcommand { · 1114 unmodified lines | |||
| 1115 | int cmd_ftrace(int argc, const char **argv) | 1115 | int cmd_ftrace(int argc, const char **argv) |
| 1116 | { | 1116 | { |
| 1117 | int ret; | 1117 | int ret; |
| 1118 | int (*cmd_func)(struct perf_ftrace *) = NULL; | ||
| 1118 | struct perf_ftrace ftrace = { | 1119 | struct perf_ftrace ftrace = { |
| 1119 | .tracer = DEFAULT_TRACER, | 1120 | .tracer = DEFAULT_TRACER, |
| 1120 | .target = { .uid = UINT_MAX, }, | 1121 | .target = { .uid = UINT_MAX, }, |
| @@ -1221,6 +1222,28 @@ int cmd_ftrace(int argc, const char **argv) · 100 unmodified lines | |||
| 1221 | goto out_delete_filters; | 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 | ret = target__validate(&ftrace.target); | 1247 | ret = target__validate(&ftrace.target); |
| 1225 | if (ret) { | 1248 | if (ret) { |
| 1226 | char errbuf[512]; | 1249 | char errbuf[512]; |
| @@ -1248,27 +1271,7 @@ int cmd_ftrace(int argc, const char **argv) · 21 unmodified lines | |||
| 1248 | goto out_delete_evlist; | 1271 | goto out_delete_evlist; |
| 1249 | } | 1272 | } |
| 1250 | 1273 | ||
| 1251 | switch (subcmd) { | 1274 | ret = cmd_func(&ftrace); |
| 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 | } | ||
| 1272 | 1275 | ||
| 1273 | out_delete_evlist: | 1276 | out_delete_evlist: |
| 1274 | evlist__delete(ftrace.evlist); | 1277 | evlist__delete(ftrace.evlist); |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ | 4 | [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ |
| 5 | 5 | ||
| 6 | printf "static const char *prctl_options[] = {\n" | 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 | egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \ | 8 | egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \ |
| 9 | sed -r "s/$regex/\2 \1/g" | \ | 9 | sed -r "s/$regex/\2 \1/g" | \ |
| 10 | sort -n | xargs printf "\t[%s] = \"%s\",\n" | 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 | memset(&objdump_process, 0, sizeof(objdump_process)); | 2036 | memset(&objdump_process, 0, sizeof(objdump_process)); |
| 2037 | objdump_process.argv = objdump_argv; | 2037 | objdump_process.argv = objdump_argv; |
| 2038 | objdump_process.out = -1; | 2038 | objdump_process.out = -1; |
| 2039 | objdump_process.err = -1; | ||
| 2039 | if (start_command(&objdump_process)) { | 2040 | if (start_command(&objdump_process)) { |
| 2040 | pr_err("Failure starting to run %s\n", command); | 2041 | pr_err("Failure starting to run %s\n", command); |
| 2041 | err = -1; | 2042 | err = -1; |
| @@ -266,7 +266,7 @@ static int bperf_cgrp__read(struct evsel *evsel) · 265 unmodified lines | |||
| 266 | idx = evsel->core.idx; | 266 | idx = evsel->core.idx; |
| 267 | err = bpf_map_lookup_elem(reading_map_fd, &idx, values); | 267 | err = bpf_map_lookup_elem(reading_map_fd, &idx, values); |
| 268 | if (err) { | 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 | idx, evsel__name(evsel), evsel->cgrp->name); | 270 | idx, evsel__name(evsel), evsel->cgrp->name); |
| 271 | goto out; | 271 | goto out; |
| 272 | } | 272 | } |
| @@ -2073,6 +2073,7 @@ static void ip__resolve_ams(struct thread *thread, · 2072 unmodified lines | |||
| 2073 | 2073 | ||
| 2074 | ams->addr = ip; | 2074 | ams->addr = ip; |
| 2075 | ams->al_addr = al.addr; | 2075 | ams->al_addr = al.addr; |
| 2076 | ams->al_level = al.level; | ||
| 2076 | ams->ms.maps = al.maps; | 2077 | ams->ms.maps = al.maps; |
| 2077 | ams->ms.sym = al.sym; | 2078 | ams->ms.sym = al.sym; |
| 2078 | ams->ms.map = al.map; | 2079 | ams->ms.map = al.map; |
| @@ -2092,6 +2093,7 @@ static void ip__resolve_data(struct thread *thread, · 13 unmodified lines | |||
| 2092 | 2093 | ||
| 2093 | ams->addr = addr; | 2094 | ams->addr = addr; |
| 2094 | ams->al_addr = al.addr; | 2095 | ams->al_addr = al.addr; |
| 2096 | ams->al_level = al.level; | ||
| 2095 | ams->ms.maps = al.maps; | 2097 | ams->ms.maps = al.maps; |
| 2096 | ams->ms.sym = al.sym; | 2098 | ams->ms.sym = al.sym; |
| 2097 | ams->ms.map = al.map; | 2099 | ams->ms.map = al.map; |
| @@ -18,6 +18,7 @@ struct addr_map_symbol { · 17 unmodified lines | |||
| 18 | struct map_symbol ms; | 18 | struct map_symbol ms; |
| 19 | u64 addr; | 19 | u64 addr; |
| 20 | u64 al_addr; | 20 | u64 al_addr; |
| 21 | char al_level; | ||
| 21 | u64 phys_addr; | 22 | u64 phys_addr; |
| 22 | u64 data_page_size; | 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 | bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX), | 52 | bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX), |
| 53 | bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP), | 53 | bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP), |
| 54 | bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES), | 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 | { .name = NULL, } | 56 | { .name = NULL, } |
| 57 | }; | 57 | }; |
| 58 | #undef bit_name | 58 | #undef bit_name |
| @@ -1503,11 +1503,12 @@ static int machines__deliver_event(struct machines *machines, · 1502 unmodified lines | |||
| 1503 | ++evlist->stats.nr_unknown_id; | 1503 | ++evlist->stats.nr_unknown_id; |
| 1504 | return 0; | 1504 | return 0; |
| 1505 | } | 1505 | } |
| 1506 | dump_sample(evsel, event, sample, perf_env__arch(machine->env)); | ||
| 1507 | if (machine == NULL) { | 1506 | if (machine == NULL) { |
| 1508 | ++evlist->stats.nr_unprocessable_samples; | 1507 | ++evlist->stats.nr_unprocessable_samples; |
| 1508 | dump_sample(evsel, event, sample, perf_env__arch(NULL)); | ||
| 1509 | return 0; | 1509 | return 0; |
| 1510 | } | 1510 | } |
| 1511 | dump_sample(evsel, event, sample, perf_env__arch(machine->env)); | ||
| 1511 | return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); | 1512 | return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); |
| 1512 | case PERF_RECORD_MMAP: | 1513 | case PERF_RECORD_MMAP: |
| 1513 | return tool->mmap(tool, event, sample, machine); | 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 | struct addr_map_symbol *from = &he->branch_info->from; | 915 | struct addr_map_symbol *from = &he->branch_info->from; |
| 916 | 916 | ||
| 917 | return _hist_entry__sym_snprintf(&from->ms, from->al_addr, | 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 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); | 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 | struct addr_map_symbol *to = &he->branch_info->to; | 928 | struct addr_map_symbol *to = &he->branch_info->to; |
| 929 | 929 | ||
| 930 | return _hist_entry__sym_snprintf(&to->ms, to->al_addr, | 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 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); | 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 | alias = list_prepare_entry(counter, &(evlist->core.entries), core.node); | 586 | alias = list_prepare_entry(counter, &(evlist->core.entries), core.node); |
| 587 | list_for_each_entry_continue (alias, &evlist->core.entries, core.node) { | 587 | list_for_each_entry_continue (alias, &evlist->core.entries, core.node) { |
| 588 | if (strcmp(evsel__name(alias), evsel__name(counter)) || | 588 | /* Merge events with the same name, etc. but on different PMUs. */ |
| 589 | alias->scale != counter->scale || | 589 | if (!strcmp(evsel__name(alias), evsel__name(counter)) && |
| 590 | alias->cgrp != counter->cgrp || | 590 | alias->scale == counter->scale && |
| 591 | strcmp(alias->unit, counter->unit) || | 591 | alias->cgrp == counter->cgrp && |
| 592 | evsel__is_clock(alias) != evsel__is_clock(counter) || | 592 | !strcmp(alias->unit, counter->unit) && |
| 593 | !strcmp(alias->pmu_name, counter->pmu_name)) | 593 | evsel__is_clock(alias) == evsel__is_clock(counter) && |
| 594 | break; | 594 | strcmp(alias->pmu_name, counter->pmu_name)) { |
| 595 | alias->merged_stat = true; | 595 | alias->merged_stat = true; |
| 596 | cb(config, alias, data, false); | 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 | perf_event__handler_t process, bool needs_mmap, | 1784 | perf_event__handler_t process, bool needs_mmap, |
| 1785 | bool data_mmap, unsigned int nr_threads_synthesize) | 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 | if (target__has_task(target)) | 1806 | if (target__has_task(target)) |
| 1788 | return perf_event__synthesize_thread_map(tool, threads, process, machine, | 1807 | return perf_event__synthesize_thread_map(tool, threads, process, machine, |
| 1789 | needs_mmap, data_mmap); | 1808 | needs_mmap, data_mmap); |
| @@ -61,7 +61,7 @@ def main(argv: Sequence[str]) -> None: · 60 unmodified lines | |||
| 61 | elif isinstance(ex, subprocess.CalledProcessError): | 61 | elif isinstance(ex, subprocess.CalledProcessError): |
| 62 | print(f'{name}: FAILED') | 62 | print(f'{name}: FAILED') |
| 63 | else: | 63 | else: |
| 64 | print('{name}: unexpected exception: {ex}') | 64 | print(f'{name}: unexpected exception: {ex}') |
| 65 | continue | 65 | continue |
| 66 | 66 | ||
| 67 | output = ex.output | 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 | int main(int argc, char *argv[]) | 127 | int main(int argc, char *argv[]) |
| 128 | { | 128 | { |
| 129 | pid_t pid; | ||
| 130 | |||
| 131 | uid_t uid = getuid(); | 129 | uid_t uid = getuid(); |
| 132 | 130 | ||
| 133 | ksft_print_header(); | 131 | ksft_print_header(); |
| @@ -29,6 +29,16 @@ · 28 unmodified lines | |||
| 29 | #define SYSFS_PATH_MAX 256 | 29 | #define SYSFS_PATH_MAX 256 |
| 30 | #define DNAME_PATH_MAX 256 | 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 | static const struct { | 42 | static const struct { |
| 33 | enum rc_proto proto; | 43 | enum rc_proto proto; |
| 34 | const char *name; | 44 | const char *name; |
| @@ -1299,6 +1299,7 @@ signal_address_tests() · 1298 unmodified lines | |||
| 1299 | pm_nl_add_endpoint $ns2 10.0.3.2 flags signal | 1299 | pm_nl_add_endpoint $ns2 10.0.3.2 flags signal |
| 1300 | pm_nl_add_endpoint $ns2 10.0.4.2 flags signal | 1300 | pm_nl_add_endpoint $ns2 10.0.4.2 flags signal |
| 1301 | run_tests $ns1 $ns2 10.0.1.1 | 1301 | run_tests $ns1 $ns2 10.0.1.1 |
| 1302 | chk_join_nr "signal addresses race test" 3 3 3 | ||
| 1302 | 1303 | ||
| 1303 | # the server will not signal the address terminating | 1304 | # the server will not signal the address terminating |
| 1304 | # the MPC subflow | 1305 | # the MPC subflow |
| @@ -44,9 +44,10 @@ static struct { · 43 unmodified lines | |||
| 44 | } ctx; | 44 | } ctx; |
| 45 | 45 | ||
| 46 | /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */ | 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 | struct perf_event_attr attr = { | 52 | struct perf_event_attr attr = { |
| 52 | .type = PERF_TYPE_BREAKPOINT, | 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 | .inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */ | 61 | .inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */ |
| 61 | .remove_on_exec = 1, /* Required by sigtrap. */ | 62 | .remove_on_exec = 1, /* Required by sigtrap. */ |
| 62 | .sigtrap = 1, /* Request synchronous SIGTRAP on event. */ | 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 | return attr; | 66 | return attr; |
| 66 | } | 67 | } |
| @@ -110,7 +111,7 @@ FIXTURE(sigtrap_threads) · 43 unmodified lines | |||
| 110 | 111 | ||
| 111 | FIXTURE_SETUP(sigtrap_threads) | 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 | struct sigaction action = {}; | 115 | struct sigaction action = {}; |
| 115 | int i; | 116 | int i; |
| 116 | 117 | ||
| @@ -165,7 +166,7 @@ TEST_F(sigtrap_threads, enable_event) · 48 unmodified lines | |||
| 165 | EXPECT_EQ(ctx.tids_want_signal, 0); | 166 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 166 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 167 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 167 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | 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 | /* Check enabled for parent. */ | 171 | /* Check enabled for parent. */ |
| 171 | ctx.iterate_on = 0; | 172 | ctx.iterate_on = 0; |
| @@ -175,7 +176,7 @@ TEST_F(sigtrap_threads, enable_event) · 3 unmodified lines | |||
| 175 | /* Test that modification propagates to all inherited events. */ | 176 | /* Test that modification propagates to all inherited events. */ |
| 176 | TEST_F(sigtrap_threads, modify_and_enable_event) | 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 | EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0); | 181 | EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0); |
| 181 | run_test_threads(_metadata, self); | 182 | run_test_threads(_metadata, self); |
| @@ -184,7 +185,7 @@ TEST_F(sigtrap_threads, modify_and_enable_event) · 2 unmodified lines | |||
| 184 | EXPECT_EQ(ctx.tids_want_signal, 0); | 185 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 185 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 186 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 186 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | 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 | /* Check enabled for parent. */ | 190 | /* Check enabled for parent. */ |
| 190 | ctx.iterate_on = 0; | 191 | ctx.iterate_on = 0; |
| @@ -204,7 +205,7 @@ TEST_F(sigtrap_threads, signal_stress) · 13 unmodified lines | |||
| 204 | EXPECT_EQ(ctx.tids_want_signal, 0); | 205 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 205 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 206 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 206 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | 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 | TEST_HARNESS_MAIN | 211 | TEST_HARNESS_MAIN |
| @@ -68,7 +68,7 @@ · 67 unmodified lines | |||
| 68 | #define PIDFD_SKIP 3 | 68 | #define PIDFD_SKIP 3 |
| 69 | #define PIDFD_XFAIL 4 | 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 | int status, ret; | 73 | int status, ret; |
| 74 | 74 | ||
| @@ -78,13 +78,20 @@ again: · 3 unmodified lines | |||
| 78 | if (errno == EINTR) | 78 | if (errno == EINTR) |
| 79 | goto again; | 79 | goto again; |
| 80 | 80 | ||
| 81 | ksft_print_msg("waitpid returned -1, errno=%d\n", errno); | ||
| 81 | return -1; | 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 | return -1; | 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 | static inline int sys_pidfd_open(pid_t pid, unsigned int flags) | 97 | static inline int sys_pidfd_open(pid_t pid, unsigned int flags) |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <string.h> | 12 | #include <string.h> |
| 13 | #include <syscall.h> | 13 | #include <syscall.h> |
| 14 | #include <sys/wait.h> | 14 | #include <sys/wait.h> |
| 15 | #include <sys/mman.h> | ||
| 15 | 16 | ||
| 16 | #include "pidfd.h" | 17 | #include "pidfd.h" |
| 17 | #include "../kselftest.h" | 18 | #include "../kselftest.h" |
| @@ -80,7 +81,10 @@ static inline int error_check(struct error *err, const char *test_name) · 62 unmodified lines | |||
| 80 | return err->code; | 81 | return err->code; |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 84 | #define CHILD_STACK_SIZE 8192 | ||
| 85 | |||
| 83 | struct child { | 86 | struct child { |
| 87 | char *stack; | ||
| 84 | pid_t pid; | 88 | pid_t pid; |
| 85 | int fd; | 89 | int fd; |
| 86 | }; | 90 | }; |
| @@ -89,17 +93,22 @@ static struct child clone_newns(int (*fn)(void *), void *args, · 2 unmodified lines | |||
| 89 | struct error *err) | 93 | struct error *err) |
| 90 | { | 94 | { |
| 91 | static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD; | 95 | static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD; |
| 92 | size_t stack_size = 1024; | ||
| 93 | char *stack[1024] = { 0 }; | ||
| 94 | struct child ret; | 96 | struct child ret; |
| 95 | 97 | ||
| 96 | if (!(flags & CLONE_NEWUSER) && geteuid() != 0) | 98 | if (!(flags & CLONE_NEWUSER) && geteuid() != 0) |
| 97 | flags |= CLONE_NEWUSER; | 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 | #ifdef __ia64__ | 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 | #else | 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 | #endif | 112 | #endif |
| 104 | 113 | ||
| 105 | if (ret.pid < 0) { | 114 | if (ret.pid < 0) { |
| @@ -129,6 +138,11 @@ static inline int child_join(struct child *child, struct error *err) · 23 unmodified lines | |||
| 129 | else if (r > 0) | 138 | else if (r > 0) |
| 130 | error_set(err, r, "child %d reported: %d", child->pid, r); | 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 | return r; | 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 | int pid, pidfd = 0; | 442 | int pid, pidfd = 0; |
| 443 | int status, ret; | 443 | int status, ret; |
| 444 | pthread_t t1; | ||
| 445 | time_t prog_start = time(NULL); | 444 | time_t prog_start = time(NULL); |
| 446 | const char *test_name = "pidfd_poll check for premature notification on child thread exec"; | 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 | *child_exit_secs = time(NULL); | 500 | *child_exit_secs = time(NULL); |
| 502 | syscall(SYS_exit, 0); | 501 | syscall(SYS_exit, 0); |
| 502 | /* Never reached, but appeases compiler thinking we should return. */ | ||
| 503 | exit(0); | ||
| 503 | } | 504 | } |
| 504 | 505 | ||
| 505 | static void test_pidfd_poll_leader_exit(int use_waitpid) | 506 | static void test_pidfd_poll_leader_exit(int use_waitpid) |
| 506 | { | 507 | { |
| 507 | int pid, pidfd = 0; | 508 | int pid, pidfd = 0; |
| 508 | int status, ret; | 509 | int status, ret = 0; |
| 509 | time_t prog_start = time(NULL); | ||
| 510 | const char *test_name = "pidfd_poll check for premature notification on non-empty" | 510 | const char *test_name = "pidfd_poll check for premature notification on non-empty" |
| 511 | "group leader exit"; | 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 | TEST(wait_simple) | 40 | TEST(wait_simple) |
| 41 | { | 41 | { |
| 42 | int pidfd = -1, status = 0; | 42 | int pidfd = -1; |
| 43 | pid_t parent_tid = -1; | 43 | pid_t parent_tid = -1; |
| 44 | struct clone_args args = { | 44 | struct clone_args args = { |
| 45 | .parent_tid = ptr_to_u64(&parent_tid), | 45 | .parent_tid = ptr_to_u64(&parent_tid), |
| @@ -47,7 +47,6 @@ TEST(wait_simple) · 1 unmodified line | |||
| 47 | .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, | 47 | .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, |
| 48 | .exit_signal = SIGCHLD, | 48 | .exit_signal = SIGCHLD, |
| 49 | }; | 49 | }; |
| 50 | int ret; | ||
| 51 | pid_t pid; | 50 | pid_t pid; |
| 52 | siginfo_t info = { | 51 | siginfo_t info = { |
| 53 | .si_signo = 0, | 52 | .si_signo = 0, |
| @@ -88,7 +87,7 @@ TEST(wait_simple) · 34 unmodified lines | |||
| 88 | 87 | ||
| 89 | TEST(wait_states) | 88 | TEST(wait_states) |
| 90 | { | 89 | { |
| 91 | int pidfd = -1, status = 0; | 90 | int pidfd = -1; |
| 92 | pid_t parent_tid = -1; | 91 | pid_t parent_tid = -1; |
| 93 | struct clone_args args = { | 92 | struct clone_args args = { |
| 94 | .parent_tid = ptr_to_u64(&parent_tid), | 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 | static int userfaultfd_stress(void) | 1417 | static int userfaultfd_stress(void) |
| 1418 | { | 1418 | { |
| 1419 | void *area; | 1419 | void *area; |
| 1420 | char *tmp_area; | ||
| 1420 | unsigned long nr; | 1421 | unsigned long nr; |
| 1421 | struct uffdio_register uffdio_register; | 1422 | struct uffdio_register uffdio_register; |
| 1422 | struct uffd_stats uffd_stats[nr_cpus]; | 1423 | struct uffd_stats uffd_stats[nr_cpus]; |
| @@ -1527,9 +1528,13 @@ static int userfaultfd_stress(void) · 104 unmodified lines | |||
| 1527 | count_verify[nr], nr); | 1528 | count_verify[nr], nr); |
| 1528 | 1529 | ||
| 1529 | /* prepare next bounce */ | 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 | uffd_stats_report(uffd_stats, nr_cpus); | 1539 | uffd_stats_report(uffd_stats, nr_cpus); |
| 1535 | } | 1540 | } |