net/devlink/leftover.c / net/core/devlink.c: 565b4824c39f ("devlink: change port event netdev notifier from per-net to global") f05bd8ebeb69 ("devlink: move code to a dedicated directory") 687125b5799c ("devlink: split out core code") https://lore.kernel.org/all/20230208094657.379f2b1a@canb.auug.org.au/
Unified · Split
| @@ -130,6 +130,7 @@ Domen Puncer <domen@coderock.org> · 129 unmodified lines | |||
| 130 | Douglas Gilbert <dougg@torque.net> | 130 | Douglas Gilbert <dougg@torque.net> |
| 131 | Ed L. Cashin <ecashin@coraid.com> | 131 | Ed L. Cashin <ecashin@coraid.com> |
| 132 | Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com> | 132 | Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com> |
| 133 | Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com> | ||
| 133 | Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 134 | Evgeniy Polyakov <johnpol@2ka.mipt.ru> |
| 134 | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> <ezequiel@collabora.com> | 135 | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> <ezequiel@collabora.com> |
| 135 | Felipe W Damasio <felipewd@terra.com.br> | 136 | Felipe W Damasio <felipewd@terra.com.br> |
| @@ -1245,13 +1245,17 @@ PAGE_SIZE multiple when read back. · 1244 unmodified lines | |||
| 1245 | This is a simple interface to trigger memory reclaim in the | 1245 | This is a simple interface to trigger memory reclaim in the |
| 1246 | target cgroup. | 1246 | target cgroup. |
| 1247 | 1247 | ||
| 1248 | This file accepts a string which contains the number of bytes to | 1248 | This file accepts a single key, the number of bytes to reclaim. |
| 1249 | reclaim. | 1249 | No nested keys are currently supported. |
| 1250 | 1250 | ||
| 1251 | Example:: | 1251 | Example:: |
| 1252 | 1252 | ||
| 1253 | echo "1G" > memory.reclaim | 1253 | echo "1G" > memory.reclaim |
| 1254 | 1254 | ||
| 1255 | The interface can be later extended with nested keys to | ||
| 1256 | configure the reclaim behavior. For example, specify the | ||
| 1257 | type of memory to reclaim from (anon, file, ..). | ||
| 1258 | |||
| 1255 | Please note that the kernel can over or under reclaim from | 1259 | Please note that the kernel can over or under reclaim from |
| 1256 | the target cgroup. If less bytes are reclaimed than the | 1260 | the target cgroup. If less bytes are reclaimed than the |
| 1257 | specified amount, -EAGAIN is returned. | 1261 | specified amount, -EAGAIN is returned. |
| @@ -1263,13 +1267,6 @@ PAGE_SIZE multiple when read back. · 5 unmodified lines | |||
| 1263 | This means that the networking layer will not adapt based on | 1267 | This means that the networking layer will not adapt based on |
| 1264 | reclaim induced by memory.reclaim. | 1268 | reclaim induced by memory.reclaim. |
| 1265 | 1269 | ||
| 1266 | This file also allows the user to specify the nodes to reclaim from, | ||
| 1267 | via the 'nodes=' key, for example:: | ||
| 1268 | |||
| 1269 | echo "1G nodes=0,1" > memory.reclaim | ||
| 1270 | |||
| 1271 | The above instructs the kernel to reclaim memory from nodes 0,1. | ||
| 1272 | |||
| 1273 | memory.peak | 1270 | memory.peak |
| 1274 | A read-only single value file which exists on non-root | 1271 | A read-only single value file which exists on non-root |
| 1275 | cgroups. | 1272 | cgroups. |
| @@ -2,3 +2,8 @@ · 1 unmodified line | |||
| 2 | *.example.dts | 2 | *.example.dts |
| 3 | /processed-schema*.yaml | 3 | /processed-schema*.yaml |
| 4 | /processed-schema*.json | 4 | /processed-schema*.json |
| 5 | |||
| 6 | # | ||
| 7 | # We don't want to ignore the following even if they are dot-files | ||
| 8 | # | ||
| 9 | !.yamllint | ||
| @@ -108,7 +108,7 @@ properties: · 107 unmodified lines | |||
| 108 | 108 | ||
| 109 | msi-controller: | 109 | msi-controller: |
| 110 | description: | 110 | description: |
| 111 | Only present if the Message Based Interrupt functionnality is | 111 | Only present if the Message Based Interrupt functionality is |
| 112 | being exposed by the HW, and the mbi-ranges property present. | 112 | being exposed by the HW, and the mbi-ranges property present. |
| 113 | 113 | ||
| 114 | mbi-ranges: | 114 | mbi-ranges: |
| @@ -40,6 +40,8 @@ properties: · 39 unmodified lines | |||
| 40 | description: | 40 | description: |
| 41 | Indicates that the setting of RTC time is allowed by the host CPU. | 41 | Indicates that the setting of RTC time is allowed by the host CPU. |
| 42 | 42 | ||
| 43 | wakeup-source: true | ||
| 44 | |||
| 43 | required: | 45 | required: |
| 44 | - compatible | 46 | - compatible |
| 45 | - reg | 47 | - reg |
| @@ -16,5 +16,5 @@ Contents · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | Support | 17 | Support |
| 18 | ======= | 18 | ======= |
| 19 | If you got any problem, contact Wangxun support team via support@trustnetic.com | 19 | If you got any problem, contact Wangxun support team via nic-support@net-swift.com |
| 20 | and Cc: netdev. | 20 | and Cc: netdev. |
| @@ -8070,9 +8070,13 @@ considering the state as complete. VMM needs to ensure that the dirty · 8069 unmodified lines | |||
| 8070 | state is final and avoid missing dirty pages from another ioctl ordered | 8070 | state is final and avoid missing dirty pages from another ioctl ordered |
| 8071 | after the bitmap collection. | 8071 | after the bitmap collection. |
| 8072 | 8072 | ||
| 8073 | NOTE: One example of using the backup bitmap is saving arm64 vgic/its | 8073 | NOTE: Multiple examples of using the backup bitmap: (1) save vgic/its |
| 8074 | tables through KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} command on | 8074 | tables through command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} on |
| 8075 | KVM device "kvm-arm-vgic-its" when dirty ring is enabled. | 8075 | KVM device "kvm-arm-vgic-its". (2) restore vgic/its tables through |
| 8076 | command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_RESTORE_TABLES} on KVM device | ||
| 8077 | "kvm-arm-vgic-its". VGICv3 LPI pending status is restored. (3) save | ||
| 8078 | vgic3 pending table through KVM_DEV_ARM_VGIC_{GRP_CTRL, SAVE_PENDING_TABLES} | ||
| 8079 | command on KVM device "kvm-arm-vgic-v3". | ||
| 8076 | 8080 | ||
| 8077 | 8.30 KVM_CAP_XEN_HVM | 8081 | 8.30 KVM_CAP_XEN_HVM |
| 8078 | -------------------- | 8082 | -------------------- |
| @@ -15679,7 +15679,7 @@ OPENRISC ARCHITECTURE · 15678 unmodified lines | |||
| 15679 | M: Jonas Bonn <jonas@southpole.se> | 15679 | M: Jonas Bonn <jonas@southpole.se> |
| 15680 | M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> | 15680 | M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> |
| 15681 | M: Stafford Horne <shorne@gmail.com> | 15681 | M: Stafford Horne <shorne@gmail.com> |
| 15682 | L: openrisc@lists.librecores.org | 15682 | L: linux-openrisc@vger.kernel.org |
| 15683 | S: Maintained | 15683 | S: Maintained |
| 15684 | W: http://openrisc.io | 15684 | W: http://openrisc.io |
| 15685 | T: git https://github.com/openrisc/linux.git | 15685 | T: git https://github.com/openrisc/linux.git |
| @@ -21752,6 +21752,7 @@ F: include/uapi/linux/uvcvideo.h · 6066 unmodified lines | |||
| 21752 | 21752 | ||
| 21753 | USB WEBCAM GADGET | 21753 | USB WEBCAM GADGET |
| 21754 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 21754 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 21755 | M: Daniel Scally <dan.scally@ideasonboard.com> | ||
| 21755 | L: linux-usb@vger.kernel.org | 21756 | L: linux-usb@vger.kernel.org |
| 21756 | S: Maintained | 21757 | S: Maintained |
| 21757 | F: drivers/usb/gadget/function/*uvc* | 21758 | F: drivers/usb/gadget/function/*uvc* |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 2 | 3 | PATCHLEVEL = 2 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc6 | 5 | EXTRAVERSION = -rc7 |
| 6 | NAME = Hurr durr I'ma ninja sloth | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -2187,7 +2187,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, · 2186 unmodified lines | |||
| 2187 | ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | | 2187 | ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | |
| 2188 | ite->collection->collection_id; | 2188 | ite->collection->collection_id; |
| 2189 | val = cpu_to_le64(val); | 2189 | val = cpu_to_le64(val); |
| 2190 | return kvm_write_guest_lock(kvm, gpa, &val, ite_esz); | 2190 | return vgic_write_guest_lock(kvm, gpa, &val, ite_esz); |
| 2191 | } | 2191 | } |
| 2192 | 2192 | ||
| 2193 | /** | 2193 | /** |
| @@ -2339,7 +2339,7 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, · 145 unmodified lines | |||
| 2339 | (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | | 2339 | (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | |
| 2340 | (dev->num_eventid_bits - 1)); | 2340 | (dev->num_eventid_bits - 1)); |
| 2341 | val = cpu_to_le64(val); | 2341 | val = cpu_to_le64(val); |
| 2342 | return kvm_write_guest_lock(kvm, ptr, &val, dte_esz); | 2342 | return vgic_write_guest_lock(kvm, ptr, &val, dte_esz); |
| 2343 | } | 2343 | } |
| 2344 | 2344 | ||
| 2345 | /** | 2345 | /** |
| @@ -2526,7 +2526,7 @@ static int vgic_its_save_cte(struct vgic_its *its, · 180 unmodified lines | |||
| 2526 | ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | | 2526 | ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | |
| 2527 | collection->collection_id); | 2527 | collection->collection_id); |
| 2528 | val = cpu_to_le64(val); | 2528 | val = cpu_to_le64(val); |
| 2529 | return kvm_write_guest_lock(its->dev->kvm, gpa, &val, esz); | 2529 | return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz); |
| 2530 | } | 2530 | } |
| 2531 | 2531 | ||
| 2532 | /* | 2532 | /* |
| @@ -2607,7 +2607,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its) · 74 unmodified lines | |||
| 2607 | */ | 2607 | */ |
| 2608 | val = 0; | 2608 | val = 0; |
| 2609 | BUG_ON(cte_esz > sizeof(val)); | 2609 | BUG_ON(cte_esz > sizeof(val)); |
| 2610 | ret = kvm_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz); | 2610 | ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz); |
| 2611 | return ret; | 2611 | return ret; |
| 2612 | } | 2612 | } |
| 2613 | 2613 | ||
| @@ -2743,7 +2743,6 @@ static int vgic_its_has_attr(struct kvm_device *dev, · 129 unmodified lines | |||
| 2743 | static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) | 2743 | static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) |
| 2744 | { | 2744 | { |
| 2745 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 2745 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| 2746 | struct vgic_dist *dist = &kvm->arch.vgic; | ||
| 2747 | int ret = 0; | 2746 | int ret = 0; |
| 2748 | 2747 | ||
| 2749 | if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */ | 2748 | if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */ |
| @@ -2763,9 +2762,7 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) · 13 unmodified lines | |||
| 2763 | vgic_its_reset(kvm, its); | 2762 | vgic_its_reset(kvm, its); |
| 2764 | break; | 2763 | break; |
| 2765 | case KVM_DEV_ARM_ITS_SAVE_TABLES: | 2764 | case KVM_DEV_ARM_ITS_SAVE_TABLES: |
| 2766 | dist->save_its_tables_in_progress = true; | ||
| 2767 | ret = abi->save_tables(its); | 2765 | ret = abi->save_tables(its); |
| 2768 | dist->save_its_tables_in_progress = false; | ||
| 2769 | break; | 2766 | break; |
| 2770 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: | 2767 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: |
| 2771 | ret = abi->restore_tables(its); | 2768 | ret = abi->restore_tables(its); |
| @@ -2792,7 +2789,7 @@ bool kvm_arch_allow_write_without_running_vcpu(struct kvm *kvm) · 20 unmodified lines | |||
| 2792 | { | 2789 | { |
| 2793 | struct vgic_dist *dist = &kvm->arch.vgic; | 2790 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 2794 | 2791 | ||
| 2795 | return dist->save_its_tables_in_progress; | 2792 | return dist->table_write_in_progress; |
| 2796 | } | 2793 | } |
| 2797 | 2794 | ||
| 2798 | static int vgic_its_set_attr(struct kvm_device *dev, | 2795 | static int vgic_its_set_attr(struct kvm_device *dev, |
| @@ -339,7 +339,7 @@ retry: · 338 unmodified lines | |||
| 339 | if (status) { | 339 | if (status) { |
| 340 | /* clear consumed data */ | 340 | /* clear consumed data */ |
| 341 | val &= ~(1 << bit_nr); | 341 | val &= ~(1 << bit_nr); |
| 342 | ret = kvm_write_guest_lock(kvm, ptr, &val, 1); | 342 | ret = vgic_write_guest_lock(kvm, ptr, &val, 1); |
| 343 | if (ret) | 343 | if (ret) |
| 344 | return ret; | 344 | return ret; |
| 345 | } | 345 | } |
| @@ -434,7 +434,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) · 88 unmodified lines | |||
| 434 | else | 434 | else |
| 435 | val &= ~(1 << bit_nr); | 435 | val &= ~(1 << bit_nr); |
| 436 | 436 | ||
| 437 | ret = kvm_write_guest_lock(kvm, ptr, &val, 1); | 437 | ret = vgic_write_guest_lock(kvm, ptr, &val, 1); |
| 438 | if (ret) | 438 | if (ret) |
| 439 | goto out; | 439 | goto out; |
| 440 | } | 440 | } |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #define __KVM_ARM_VGIC_NEW_H__ | 6 | #define __KVM_ARM_VGIC_NEW_H__ |
| 7 | 7 | ||
| 8 | #include <linux/irqchip/arm-gic-common.h> | 8 | #include <linux/irqchip/arm-gic-common.h> |
| 9 | #include <asm/kvm_mmu.h> | ||
| 9 | 10 | ||
| 10 | #define PRODUCT_ID_KVM 0x4b /* ASCII code K */ | 11 | #define PRODUCT_ID_KVM 0x4b /* ASCII code K */ |
| 11 | #define IMPLEMENTER_ARM 0x43b | 12 | #define IMPLEMENTER_ARM 0x43b |
| @@ -131,6 +132,19 @@ static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq) · 119 unmodified lines | |||
| 131 | return vgic_irq_get_lr_count(irq) > 1; | 132 | return vgic_irq_get_lr_count(irq) > 1; |
| 132 | } | 133 | } |
| 133 | 134 | ||
| 135 | static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa, | ||
| 136 | const void *data, unsigned long len) | ||
| 137 | { | ||
| 138 | struct vgic_dist *dist = &kvm->arch.vgic; | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | dist->table_write_in_progress = true; | ||
| 142 | ret = kvm_write_guest_lock(kvm, gpa, data, len); | ||
| 143 | dist->table_write_in_progress = false; | ||
| 144 | |||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 134 | /* | 148 | /* |
| 135 | * This struct provides an intermediate representation of the fields contained | 149 | * This struct provides an intermediate representation of the fields contained |
| 136 | * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC | 150 | * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC |
| @@ -170,6 +170,9 @@ ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, u · 169 unmodified lines | |||
| 170 | asmlinkage long | 170 | asmlinkage long |
| 171 | ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *tp) | 171 | ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *tp) |
| 172 | { | 172 | { |
| 173 | struct timespec64 rtn_tp; | ||
| 174 | s64 tick_ns; | ||
| 175 | |||
| 173 | /* | 176 | /* |
| 174 | * ia64's clock_gettime() syscall is implemented as a vdso call | 177 | * ia64's clock_gettime() syscall is implemented as a vdso call |
| 175 | * fsys_clock_gettime(). Currently it handles only | 178 | * fsys_clock_gettime(). Currently it handles only |
| @@ -185,8 +188,8 @@ ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user * · 9 unmodified lines | |||
| 185 | switch (which_clock) { | 188 | switch (which_clock) { |
| 186 | case CLOCK_REALTIME: | 189 | case CLOCK_REALTIME: |
| 187 | case CLOCK_MONOTONIC: | 190 | case CLOCK_MONOTONIC: |
| 188 | s64 tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq); | 191 | tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq); |
| 189 | struct timespec64 rtn_tp = ns_to_timespec64(tick_ns); | 192 | rtn_tp = ns_to_timespec64(tick_ns); |
| 190 | return put_timespec64(&rtn_tp, tp); | 193 | return put_timespec64(&rtn_tp, tp); |
| 191 | } | 194 | } |
| 192 | 195 | ||
| @@ -1303,7 +1303,7 @@ static char iodc_dbuf[4096] __page_aligned_bss; · 1302 unmodified lines | |||
| 1303 | */ | 1303 | */ |
| 1304 | int pdc_iodc_print(const unsigned char *str, unsigned count) | 1304 | int pdc_iodc_print(const unsigned char *str, unsigned count) |
| 1305 | { | 1305 | { |
| 1306 | unsigned int i; | 1306 | unsigned int i, found = 0; |
| 1307 | unsigned long flags; | 1307 | unsigned long flags; |
| 1308 | 1308 | ||
| 1309 | count = min_t(unsigned int, count, sizeof(iodc_dbuf)); | 1309 | count = min_t(unsigned int, count, sizeof(iodc_dbuf)); |
| @@ -1315,6 +1315,7 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) · 5 unmodified lines | |||
| 1315 | iodc_dbuf[i+0] = '\r'; | 1315 | iodc_dbuf[i+0] = '\r'; |
| 1316 | iodc_dbuf[i+1] = '\n'; | 1316 | iodc_dbuf[i+1] = '\n'; |
| 1317 | i += 2; | 1317 | i += 2; |
| 1318 | found = 1; | ||
| 1318 | goto print; | 1319 | goto print; |
| 1319 | default: | 1320 | default: |
| 1320 | iodc_dbuf[i] = str[i]; | 1321 | iodc_dbuf[i] = str[i]; |
| @@ -1330,7 +1331,7 @@ print: · 9 unmodified lines | |||
| 1330 | __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0); | 1331 | __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0); |
| 1331 | spin_unlock_irqrestore(&pdc_lock, flags); | 1332 | spin_unlock_irqrestore(&pdc_lock, flags); |
| 1332 | 1333 | ||
| 1333 | return i; | 1334 | return i - found; |
| 1334 | } | 1335 | } |
| 1335 | 1336 | ||
| 1336 | #if !defined(BOOTLOADER) | 1337 | #if !defined(BOOTLOADER) |
| @@ -126,6 +126,12 @@ long arch_ptrace(struct task_struct *child, long request, · 125 unmodified lines | |||
| 126 | unsigned long tmp; | 126 | unsigned long tmp; |
| 127 | long ret = -EIO; | 127 | long ret = -EIO; |
| 128 | 128 | ||
| 129 | unsigned long user_regs_struct_size = sizeof(struct user_regs_struct); | ||
| 130 | #ifdef CONFIG_64BIT | ||
| 131 | if (is_compat_task()) | ||
| 132 | user_regs_struct_size /= 2; | ||
| 133 | #endif | ||
| 134 | |||
| 129 | switch (request) { | 135 | switch (request) { |
| 130 | 136 | ||
| 131 | /* Read the word at location addr in the USER area. For ptraced | 137 | /* Read the word at location addr in the USER area. For ptraced |
| @@ -166,7 +172,7 @@ long arch_ptrace(struct task_struct *child, long request, · 34 unmodified lines | |||
| 166 | addr >= sizeof(struct pt_regs)) | 172 | addr >= sizeof(struct pt_regs)) |
| 167 | break; | 173 | break; |
| 168 | if (addr == PT_IAOQ0 || addr == PT_IAOQ1) { | 174 | if (addr == PT_IAOQ0 || addr == PT_IAOQ1) { |
| 169 | data |= 3; /* ensure userspace privilege */ | 175 | data |= PRIV_USER; /* ensure userspace privilege */ |
| 170 | } | 176 | } |
| 171 | if ((addr >= PT_GR1 && addr <= PT_GR31) || | 177 | if ((addr >= PT_GR1 && addr <= PT_GR31) || |
| 172 | addr == PT_IAOQ0 || addr == PT_IAOQ1 || | 178 | addr == PT_IAOQ0 || addr == PT_IAOQ1 || |
| @@ -181,14 +187,14 @@ long arch_ptrace(struct task_struct *child, long request, · 8 unmodified lines | |||
| 181 | return copy_regset_to_user(child, | 187 | return copy_regset_to_user(child, |
| 182 | task_user_regset_view(current), | 188 | task_user_regset_view(current), |
| 183 | REGSET_GENERAL, | 189 | REGSET_GENERAL, |
| 184 | 0, sizeof(struct user_regs_struct), | 190 | 0, user_regs_struct_size, |
| 185 | datap); | 191 | datap); |
| 186 | 192 | ||
| 187 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ | 193 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
| 188 | return copy_regset_from_user(child, | 194 | return copy_regset_from_user(child, |
| 189 | task_user_regset_view(current), | 195 | task_user_regset_view(current), |
| 190 | REGSET_GENERAL, | 196 | REGSET_GENERAL, |
| 191 | 0, sizeof(struct user_regs_struct), | 197 | 0, user_regs_struct_size, |
| 192 | datap); | 198 | datap); |
| 193 | 199 | ||
| 194 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | 200 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ |
| @@ -285,7 +291,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, · 90 unmodified lines | |||
| 285 | if (addr >= sizeof(struct pt_regs)) | 291 | if (addr >= sizeof(struct pt_regs)) |
| 286 | break; | 292 | break; |
| 287 | if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) { | 293 | if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) { |
| 288 | data |= 3; /* ensure userspace privilege */ | 294 | data |= PRIV_USER; /* ensure userspace privilege */ |
| 289 | } | 295 | } |
| 290 | if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { | 296 | if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { |
| 291 | /* Special case, fp regs are 64 bits anyway */ | 297 | /* Special case, fp regs are 64 bits anyway */ |
| @@ -302,6 +308,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, · 10 unmodified lines | |||
| 302 | } | 308 | } |
| 303 | } | 309 | } |
| 304 | break; | 310 | break; |
| 311 | case PTRACE_GETREGS: | ||
| 312 | case PTRACE_SETREGS: | ||
| 313 | case PTRACE_GETFPREGS: | ||
| 314 | case PTRACE_SETFPREGS: | ||
| 315 | return arch_ptrace(child, request, addr, data); | ||
| 305 | 316 | ||
| 306 | default: | 317 | default: |
| 307 | ret = compat_ptrace_request(child, request, addr, data); | 318 | ret = compat_ptrace_request(child, request, addr, data); |
| @@ -484,7 +495,7 @@ static void set_reg(struct pt_regs *regs, int num, unsigned long val) · 176 unmodified lines | |||
| 484 | case RI(iaoq[0]): | 495 | case RI(iaoq[0]): |
| 485 | case RI(iaoq[1]): | 496 | case RI(iaoq[1]): |
| 486 | /* set 2 lowest bits to ensure userspace privilege: */ | 497 | /* set 2 lowest bits to ensure userspace privilege: */ |
| 487 | regs->iaoq[num - RI(iaoq[0])] = val | 3; | 498 | regs->iaoq[num - RI(iaoq[0])] = val | PRIV_USER; |
| 488 | return; | 499 | return; |
| 489 | case RI(sar): regs->sar = val; | 500 | case RI(sar): regs->sar = val; |
| 490 | return; | 501 | return; |
| @@ -97,6 +97,8 @@ static inline void tlb_flush(struct mmu_gather *tlb) · 96 unmodified lines | |||
| 97 | { | 97 | { |
| 98 | if (radix_enabled()) | 98 | if (radix_enabled()) |
| 99 | radix__tlb_flush(tlb); | 99 | radix__tlb_flush(tlb); |
| 100 | |||
| 101 | return hash__tlb_flush(tlb); | ||
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | #ifdef CONFIG_SMP | 104 | #ifdef CONFIG_SMP |
| @@ -173,6 +173,15 @@ static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask) · 172 unmodified lines | |||
| 173 | return flags; | 173 | return flags; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static inline notrace unsigned long irq_soft_mask_andc_return(unsigned long mask) | ||
| 177 | { | ||
| 178 | unsigned long flags = irq_soft_mask_return(); | ||
| 179 | |||
| 180 | irq_soft_mask_set(flags & ~mask); | ||
| 181 | |||
| 182 | return flags; | ||
| 183 | } | ||
| 184 | |||
| 176 | static inline unsigned long arch_local_save_flags(void) | 185 | static inline unsigned long arch_local_save_flags(void) |
| 177 | { | 186 | { |
| 178 | return irq_soft_mask_return(); | 187 | return irq_soft_mask_return(); |
| @@ -192,7 +201,7 @@ static inline void arch_local_irq_enable(void) · 13 unmodified lines | |||
| 192 | 201 | ||
| 193 | static inline unsigned long arch_local_irq_save(void) | 202 | static inline unsigned long arch_local_irq_save(void) |
| 194 | { | 203 | { |
| 195 | return irq_soft_mask_set_return(IRQS_DISABLED); | 204 | return irq_soft_mask_or_return(IRQS_DISABLED); |
| 196 | } | 205 | } |
| 197 | 206 | ||
| 198 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | 207 | static inline bool arch_irqs_disabled_flags(unsigned long flags) |
| @@ -331,10 +340,11 @@ bool power_pmu_wants_prompt_pmi(void); · 132 unmodified lines | |||
| 331 | * is a different soft-masked interrupt pending that requires hard | 340 | * is a different soft-masked interrupt pending that requires hard |
| 332 | * masking. | 341 | * masking. |
| 333 | */ | 342 | */ |
| 334 | static inline bool should_hard_irq_enable(void) | 343 | static inline bool should_hard_irq_enable(struct pt_regs *regs) |
| 335 | { | 344 | { |
| 336 | if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) { | 345 | if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) { |
| 337 | WARN_ON(irq_soft_mask_return() == IRQS_ENABLED); | 346 | WARN_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED); |
| 347 | WARN_ON(!(get_paca()->irq_happened & PACA_IRQ_HARD_DIS)); | ||
| 338 | WARN_ON(mfmsr() & MSR_EE); | 348 | WARN_ON(mfmsr() & MSR_EE); |
| 339 | } | 349 | } |
| 340 | 350 | ||
| @@ -347,8 +357,17 @@ static inline bool should_hard_irq_enable(void) · 6 unmodified lines | |||
| 347 | * | 357 | * |
| 348 | * TODO: Add test for 64e | 358 | * TODO: Add test for 64e |
| 349 | */ | 359 | */ |
| 350 | if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !power_pmu_wants_prompt_pmi()) | 360 | if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) { |
| 351 | return false; | 361 | if (!power_pmu_wants_prompt_pmi()) |
| 362 | return false; | ||
| 363 | /* | ||
| 364 | * If PMIs are disabled then IRQs should be disabled as well, | ||
| 365 | * so we shouldn't see this condition, check for it just in | ||
| 366 | * case because we are about to enable PMIs. | ||
| 367 | */ | ||
| 368 | if (WARN_ON_ONCE(regs->softe & IRQS_PMI_DISABLED)) | ||
| 369 | return false; | ||
| 370 | } | ||
| 352 | 371 | ||
| 353 | if (get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK) | 372 | if (get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK) |
| 354 | return false; | 373 | return false; |
| @@ -358,18 +377,16 @@ static inline bool should_hard_irq_enable(void) · 3 unmodified lines | |||
| 358 | 377 | ||
| 359 | /* | 378 | /* |
| 360 | * Do the hard enabling, only call this if should_hard_irq_enable is true. | 379 | * Do the hard enabling, only call this if should_hard_irq_enable is true. |
| 380 | * This allows PMI interrupts to profile irq handlers. | ||
| 361 | */ | 381 | */ |
| 362 | static inline void do_hard_irq_enable(void) | 382 | static inline void do_hard_irq_enable(void) |
| 363 | { | 383 | { |
| 364 | if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) { | ||
| 365 | WARN_ON(irq_soft_mask_return() == IRQS_ENABLED); | ||
| 366 | WARN_ON(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK); | ||
| 367 | WARN_ON(mfmsr() & MSR_EE); | ||
| 368 | } | ||
| 369 | /* | 384 | /* |
| 370 | * This allows PMI interrupts (and watchdog soft-NMIs) through. | 385 | * Asynch interrupts come in with IRQS_ALL_DISABLED, |
| 371 | * There is no other reason to enable this way. | 386 | * PACA_IRQ_HARD_DIS, and MSR[EE]=0. |
| 372 | */ | 387 | */ |
| 388 | if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) | ||
| 389 | irq_soft_mask_andc_return(IRQS_PMI_DISABLED); | ||
| 373 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; | 390 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; |
| 374 | __hard_irq_enable(); | 391 | __hard_irq_enable(); |
| 375 | } | 392 | } |
| @@ -452,7 +469,7 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs) · 76 unmodified lines | |||
| 452 | return !(regs->msr & MSR_EE); | 469 | return !(regs->msr & MSR_EE); |
| 453 | } | 470 | } |
| 454 | 471 | ||
| 455 | static __always_inline bool should_hard_irq_enable(void) | 472 | static __always_inline bool should_hard_irq_enable(struct pt_regs *regs) |
| 456 | { | 473 | { |
| 457 | return false; | 474 | return false; |
| 458 | } | 475 | } |
| @@ -27,7 +27,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(doorbell_exception) · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | ppc_msgsync(); | 28 | ppc_msgsync(); |
| 29 | 29 | ||
| 30 | if (should_hard_irq_enable()) | 30 | if (should_hard_irq_enable(regs)) |
| 31 | do_hard_irq_enable(); | 31 | do_hard_irq_enable(); |
| 32 | 32 | ||
| 33 | kvmppc_clear_host_ipi(smp_processor_id()); | 33 | kvmppc_clear_host_ipi(smp_processor_id()); |
| @@ -864,7 +864,7 @@ _GLOBAL(load_up_spe) · 863 unmodified lines | |||
| 864 | * SPE unavailable trap from kernel - print a message, but let | 864 | * SPE unavailable trap from kernel - print a message, but let |
| 865 | * the task use SPE in the kernel until it returns to user mode. | 865 | * the task use SPE in the kernel until it returns to user mode. |
| 866 | */ | 866 | */ |
| 867 | KernelSPE: | 867 | SYM_FUNC_START_LOCAL(KernelSPE) |
| 868 | lwz r3,_MSR(r1) | 868 | lwz r3,_MSR(r1) |
| 869 | oris r3,r3,MSR_SPE@h | 869 | oris r3,r3,MSR_SPE@h |
| 870 | stw r3,_MSR(r1) /* enable use of SPE after return */ | 870 | stw r3,_MSR(r1) /* enable use of SPE after return */ |
| @@ -881,6 +881,7 @@ KernelSPE: · 10 unmodified lines | |||
| 881 | #endif | 881 | #endif |
| 882 | .align 4,0 | 882 | .align 4,0 |
| 883 | 883 | ||
| 884 | SYM_FUNC_END(KernelSPE) | ||
| 884 | #endif /* CONFIG_SPE */ | 885 | #endif /* CONFIG_SPE */ |
| 885 | 886 | ||
| 886 | /* | 887 | /* |
| @@ -238,7 +238,7 @@ static void __do_irq(struct pt_regs *regs, unsigned long oldsp) · 237 unmodified lines | |||
| 238 | irq = static_call(ppc_get_irq)(); | 238 | irq = static_call(ppc_get_irq)(); |
| 239 | 239 | ||
| 240 | /* We can hard enable interrupts now to allow perf interrupts */ | 240 | /* We can hard enable interrupts now to allow perf interrupts */ |
| 241 | if (should_hard_irq_enable()) | 241 | if (should_hard_irq_enable(regs)) |
| 242 | do_hard_irq_enable(); | 242 | do_hard_irq_enable(); |
| 243 | 243 | ||
| 244 | /* And finally process it */ | 244 | /* And finally process it */ |
| @@ -515,7 +515,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt) · 514 unmodified lines | |||
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | /* Conditionally hard-enable interrupts. */ | 517 | /* Conditionally hard-enable interrupts. */ |
| 518 | if (should_hard_irq_enable()) { | 518 | if (should_hard_irq_enable(regs)) { |
| 519 | /* | 519 | /* |
| 520 | * Ensure a positive value is written to the decrementer, or | 520 | * Ensure a positive value is written to the decrementer, or |
| 521 | * else some CPUs will continue to take decrementer exceptions. | 521 | * else some CPUs will continue to take decrementer exceptions. |
| @@ -989,10 +989,13 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image) · 988 unmodified lines | |||
| 989 | * linux,drconf-usable-memory properties. Get an approximate on the | 989 | * linux,drconf-usable-memory properties. Get an approximate on the |
| 990 | * number of usable memory entries and use for FDT size estimation. | 990 | * number of usable memory entries and use for FDT size estimation. |
| 991 | */ | 991 | */ |
| 992 | usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) + | 992 | if (drmem_lmb_size()) { |
| 993 | (2 * (resource_size(&crashk_res) / drmem_lmb_size()))); | 993 | usm_entries = ((memory_hotplug_max() / drmem_lmb_size()) + |
| 994 | 994 | (2 * (resource_size(&crashk_res) / drmem_lmb_size()))); | |
| 995 | extra_size = (unsigned int)(usm_entries * sizeof(u64)); | 995 | extra_size = (unsigned int)(usm_entries * sizeof(u64)); |
| 996 | } else { | ||
| 997 | extra_size = 0; | ||
| 998 | } | ||
| 996 | 999 | ||
| 997 | /* | 1000 | /* |
| 998 | * Get the number of CPU nodes in the current DT. This allows to | 1001 | * Get the number of CPU nodes in the current DT. This allows to |
| @@ -912,16 +912,15 @@ static int kvmppc_handle_debug(struct kvm_vcpu *vcpu) · 911 unmodified lines | |||
| 912 | 912 | ||
| 913 | static void kvmppc_fill_pt_regs(struct pt_regs *regs) | 913 | static void kvmppc_fill_pt_regs(struct pt_regs *regs) |
| 914 | { | 914 | { |
| 915 | ulong r1, ip, msr, lr; | 915 | ulong r1, msr, lr; |
| 916 | 916 | ||
| 917 | asm("mr %0, 1" : "=r"(r1)); | 917 | asm("mr %0, 1" : "=r"(r1)); |
| 918 | asm("mflr %0" : "=r"(lr)); | 918 | asm("mflr %0" : "=r"(lr)); |
| 919 | asm("mfmsr %0" : "=r"(msr)); | 919 | asm("mfmsr %0" : "=r"(msr)); |
| 920 | asm("bl 1f; 1: mflr %0" : "=r"(ip)); | ||
| 921 | 920 | ||
| 922 | memset(regs, 0, sizeof(*regs)); | 921 | memset(regs, 0, sizeof(*regs)); |
| 923 | regs->gpr[1] = r1; | 922 | regs->gpr[1] = r1; |
| 924 | regs->nip = ip; | 923 | regs->nip = _THIS_IP_; |
| 925 | regs->msr = msr; | 924 | regs->msr = msr; |
| 926 | regs->link = lr; | 925 | regs->link = lr; |
| 927 | } | 926 | } |
| @@ -234,6 +234,14 @@ void radix__mark_rodata_ro(void) · 233 unmodified lines | |||
| 234 | end = (unsigned long)__end_rodata; | 234 | end = (unsigned long)__end_rodata; |
| 235 | 235 | ||
| 236 | radix__change_memory_range(start, end, _PAGE_WRITE); | 236 | radix__change_memory_range(start, end, _PAGE_WRITE); |
| 237 | |||
| 238 | for (start = PAGE_OFFSET; start < (unsigned long)_stext; start += PAGE_SIZE) { | ||
| 239 | end = start + PAGE_SIZE; | ||
| 240 | if (overlaps_interrupt_vector_text(start, end)) | ||
| 241 | radix__change_memory_range(start, end, _PAGE_WRITE); | ||
| 242 | else | ||
| 243 | break; | ||
| 244 | } | ||
| 237 | } | 245 | } |
| 238 | 246 | ||
| 239 | void radix__mark_initmem_nx(void) | 247 | void radix__mark_initmem_nx(void) |
| @@ -262,6 +270,22 @@ print_mapping(unsigned long start, unsigned long end, unsigned long size, bool e · 22 unmodified lines | |||
| 262 | static unsigned long next_boundary(unsigned long addr, unsigned long end) | 270 | static unsigned long next_boundary(unsigned long addr, unsigned long end) |
| 263 | { | 271 | { |
| 264 | #ifdef CONFIG_STRICT_KERNEL_RWX | 272 | #ifdef CONFIG_STRICT_KERNEL_RWX |
| 273 | unsigned long stext_phys; | ||
| 274 | |||
| 275 | stext_phys = __pa_symbol(_stext); | ||
| 276 | |||
| 277 | // Relocatable kernel running at non-zero real address | ||
| 278 | if (stext_phys != 0) { | ||
| 279 | // The end of interrupts code at zero is a rodata boundary | ||
| 280 | unsigned long end_intr = __pa_symbol(__end_interrupts) - stext_phys; | ||
| 281 | if (addr < end_intr) | ||
| 282 | return end_intr; | ||
| 283 | |||
| 284 | // Start of relocated kernel text is a rodata boundary | ||
| 285 | if (addr < stext_phys) | ||
| 286 | return stext_phys; | ||
| 287 | } | ||
| 288 | |||
| 265 | if (addr < __pa_symbol(__srwx_boundary)) | 289 | if (addr < __pa_symbol(__srwx_boundary)) |
| 266 | return __pa_symbol(__srwx_boundary); | 290 | return __pa_symbol(__srwx_boundary); |
| 267 | #endif | 291 | #endif |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | |||
| 22 | * Used to avoid races in counting the nest-pmu units during hotplug | 22 | * Used to avoid races in counting the nest-pmu units during hotplug |
| 23 | * register and unregister | 23 | * register and unregister |
| 24 | */ | 24 | */ |
| 25 | static DEFINE_SPINLOCK(nest_init_lock); | 25 | static DEFINE_MUTEX(nest_init_lock); |
| 26 | static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc); | 26 | static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc); |
| 27 | static struct imc_pmu **per_nest_pmu_arr; | 27 | static struct imc_pmu **per_nest_pmu_arr; |
| 28 | static cpumask_t nest_imc_cpumask; | 28 | static cpumask_t nest_imc_cpumask; |
| @@ -1629,7 +1629,7 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr) · 1600 unmodified lines | |||
| 1629 | static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) | 1629 | static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) |
| 1630 | { | 1630 | { |
| 1631 | if (pmu_ptr->domain == IMC_DOMAIN_NEST) { | 1631 | if (pmu_ptr->domain == IMC_DOMAIN_NEST) { |
| 1632 | spin_lock(&nest_init_lock); | 1632 | mutex_lock(&nest_init_lock); |
| 1633 | if (nest_pmus == 1) { | 1633 | if (nest_pmus == 1) { |
| 1634 | cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE); | 1634 | cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE); |
| 1635 | kfree(nest_imc_refc); | 1635 | kfree(nest_imc_refc); |
| @@ -1639,7 +1639,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) · 3 unmodified lines | |||
| 1639 | 1639 | ||
| 1640 | if (nest_pmus > 0) | 1640 | if (nest_pmus > 0) |
| 1641 | nest_pmus--; | 1641 | nest_pmus--; |
| 1642 | spin_unlock(&nest_init_lock); | 1642 | mutex_unlock(&nest_init_lock); |
| 1643 | } | 1643 | } |
| 1644 | 1644 | ||
| 1645 | /* Free core_imc memory */ | 1645 | /* Free core_imc memory */ |
| @@ -1796,11 +1796,11 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id · 150 unmodified lines | |||
| 1796 | * rest. To handle the cpuhotplug callback unregister, we track | 1796 | * rest. To handle the cpuhotplug callback unregister, we track |
| 1797 | * the number of nest pmus in "nest_pmus". | 1797 | * the number of nest pmus in "nest_pmus". |
| 1798 | */ | 1798 | */ |
| 1799 | spin_lock(&nest_init_lock); | 1799 | mutex_lock(&nest_init_lock); |
| 1800 | if (nest_pmus == 0) { | 1800 | if (nest_pmus == 0) { |
| 1801 | ret = init_nest_pmu_ref(); | 1801 | ret = init_nest_pmu_ref(); |
| 1802 | if (ret) { | 1802 | if (ret) { |
| 1803 | spin_unlock(&nest_init_lock); | 1803 | mutex_unlock(&nest_init_lock); |
| 1804 | kfree(per_nest_pmu_arr); | 1804 | kfree(per_nest_pmu_arr); |
| 1805 | per_nest_pmu_arr = NULL; | 1805 | per_nest_pmu_arr = NULL; |
| 1806 | goto err_free_mem; | 1806 | goto err_free_mem; |
| @@ -1808,7 +1808,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id · 1 unmodified line | |||
| 1808 | /* Register for cpu hotplug notification. */ | 1808 | /* Register for cpu hotplug notification. */ |
| 1809 | ret = nest_pmu_cpumask_init(); | 1809 | ret = nest_pmu_cpumask_init(); |
| 1810 | if (ret) { | 1810 | if (ret) { |
| 1811 | spin_unlock(&nest_init_lock); | 1811 | mutex_unlock(&nest_init_lock); |
| 1812 | kfree(nest_imc_refc); | 1812 | kfree(nest_imc_refc); |
| 1813 | kfree(per_nest_pmu_arr); | 1813 | kfree(per_nest_pmu_arr); |
| 1814 | per_nest_pmu_arr = NULL; | 1814 | per_nest_pmu_arr = NULL; |
| @@ -1816,7 +1816,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id · 1 unmodified line | |||
| 1816 | } | 1816 | } |
| 1817 | } | 1817 | } |
| 1818 | nest_pmus++; | 1818 | nest_pmus++; |
| 1819 | spin_unlock(&nest_init_lock); | 1819 | mutex_unlock(&nest_init_lock); |
| 1820 | break; | 1820 | break; |
| 1821 | case IMC_DOMAIN_CORE: | 1821 | case IMC_DOMAIN_CORE: |
| 1822 | ret = core_imc_pmu_cpumask_init(); | 1822 | ret = core_imc_pmu_cpumask_init(); |
| @@ -80,6 +80,9 @@ ifeq ($(CONFIG_PERF_EVENTS),y) · 79 unmodified lines | |||
| 80 | KBUILD_CFLAGS += -fno-omit-frame-pointer | 80 | KBUILD_CFLAGS += -fno-omit-frame-pointer |
| 81 | endif | 81 | endif |
| 82 | 82 | ||
| 83 | # Avoid generating .eh_frame sections. | ||
| 84 | KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables | ||
| 85 | |||
| 83 | KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) | 86 | KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) |
| 84 | KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax) | 87 | KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax) |
| 85 | 88 | ||
| @@ -70,7 +70,6 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX); · 69 unmodified lines | |||
| 70 | */ | 70 | */ |
| 71 | enum riscv_isa_ext_key { | 71 | enum riscv_isa_ext_key { |
| 72 | RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */ | 72 | RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */ |
| 73 | RISCV_ISA_EXT_KEY_ZIHINTPAUSE, | ||
| 74 | RISCV_ISA_EXT_KEY_SVINVAL, | 73 | RISCV_ISA_EXT_KEY_SVINVAL, |
| 75 | RISCV_ISA_EXT_KEY_MAX, | 74 | RISCV_ISA_EXT_KEY_MAX, |
| 76 | }; | 75 | }; |
| @@ -91,8 +90,6 @@ static __always_inline int riscv_isa_ext2key(int num) · 14 unmodified lines | |||
| 91 | return RISCV_ISA_EXT_KEY_FPU; | 90 | return RISCV_ISA_EXT_KEY_FPU; |
| 92 | case RISCV_ISA_EXT_d: | 91 | case RISCV_ISA_EXT_d: |
| 93 | return RISCV_ISA_EXT_KEY_FPU; | 92 | return RISCV_ISA_EXT_KEY_FPU; |
| 94 | case RISCV_ISA_EXT_ZIHINTPAUSE: | ||
| 95 | return RISCV_ISA_EXT_KEY_ZIHINTPAUSE; | ||
| 96 | case RISCV_ISA_EXT_SVINVAL: | 93 | case RISCV_ISA_EXT_SVINVAL: |
| 97 | return RISCV_ISA_EXT_KEY_SVINVAL; | 94 | return RISCV_ISA_EXT_KEY_SVINVAL; |
| 98 | default: | 95 | default: |
| @@ -4,30 +4,26 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #ifndef __ASSEMBLY__ | 5 | #ifndef __ASSEMBLY__ |
| 6 | 6 | ||
| 7 | #include <linux/jump_label.h> | ||
| 8 | #include <asm/barrier.h> | 7 | #include <asm/barrier.h> |
| 9 | #include <asm/hwcap.h> | ||
| 10 | 8 | ||
| 11 | static inline void cpu_relax(void) | 9 | static inline void cpu_relax(void) |
| 12 | { | 10 | { |
| 13 | if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) { | ||
| 14 | #ifdef __riscv_muldiv | 11 | #ifdef __riscv_muldiv |
| 15 | int dummy; | 12 | int dummy; |
| 16 | /* In lieu of a halt instruction, induce a long-latency stall. */ | 13 | /* In lieu of a halt instruction, induce a long-latency stall. */ |
| 17 | __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); | 14 | __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); |
| 18 | #endif | 15 | #endif |
| 19 | } else { | 16 | |
| 20 | /* | 17 | #ifdef __riscv_zihintpause |
| 21 | * Reduce instruction retirement. | 18 | /* |
| 22 | * This assumes the PC changes. | 19 | * Reduce instruction retirement. |
| 23 | */ | 20 | * This assumes the PC changes. |
| 24 | #ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE | 21 | */ |
| 25 | __asm__ __volatile__ ("pause"); | 22 | __asm__ __volatile__ ("pause"); |
| 26 | #else | 23 | #else |
| 27 | /* Encoding of the pause instruction */ | 24 | /* Encoding of the pause instruction */ |
| 28 | __asm__ __volatile__ (".4byte 0x100000F"); | 25 | __asm__ __volatile__ (".4byte 0x100000F"); |
| 29 | #endif | 26 | #endif |
| 30 | } | ||
| 31 | barrier(); | 27 | barrier(); |
| 32 | } | 28 | } |
| 33 | 29 | ||
| @@ -48,6 +48,21 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) · 47 unmodified lines | |||
| 48 | post_kprobe_handler(p, kcb, regs); | 48 | post_kprobe_handler(p, kcb, regs); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static bool __kprobes arch_check_kprobe(struct kprobe *p) | ||
| 52 | { | ||
| 53 | unsigned long tmp = (unsigned long)p->addr - p->offset; | ||
| 54 | unsigned long addr = (unsigned long)p->addr; | ||
| 55 | |||
| 56 | while (tmp <= addr) { | ||
| 57 | if (tmp == addr) | ||
| 58 | return true; | ||
| 59 | |||
| 60 | tmp += GET_INSN_LENGTH(*(u16 *)tmp); | ||
| 61 | } | ||
| 62 | |||
| 63 | return false; | ||
| 64 | } | ||
| 65 | |||
| 51 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 66 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
| 52 | { | 67 | { |
| 53 | unsigned long probe_addr = (unsigned long)p->addr; | 68 | unsigned long probe_addr = (unsigned long)p->addr; |
| @@ -55,6 +70,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) · 1 unmodified line | |||
| 55 | if (probe_addr & 0x1) | 70 | if (probe_addr & 0x1) |
| 56 | return -EILSEQ; | 71 | return -EILSEQ; |
| 57 | 72 | ||
| 73 | if (!arch_check_kprobe(p)) | ||
| 74 | return -EILSEQ; | ||
| 75 | |||
| 58 | /* copy instruction */ | 76 | /* copy instruction */ |
| 59 | p->opcode = *p->addr; | 77 | p->opcode = *p->addr; |
| 60 | 78 | ||
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * Written by Niibe Yutaka and Paul Mundt | 4 | * Written by Niibe Yutaka and Paul Mundt |
| 5 | */ | 5 | */ |
| 6 | OUTPUT_ARCH(sh) | 6 | OUTPUT_ARCH(sh) |
| 7 | #define RUNTIME_DISCARD_EXIT | ||
| 7 | #include <asm/thread_info.h> | 8 | #include <asm/thread_info.h> |
| 8 | #include <asm/cache.h> | 9 | #include <asm/cache.h> |
| 9 | #include <asm/vmlinux.lds.h> | 10 | #include <asm/vmlinux.lds.h> |
| @@ -39,7 +39,20 @@ static __always_inline unsigned long native_get_debugreg(int regno) · 38 unmodified lines | |||
| 39 | asm("mov %%db6, %0" :"=r" (val)); | 39 | asm("mov %%db6, %0" :"=r" (val)); |
| 40 | break; | 40 | break; |
| 41 | case 7: | 41 | case 7: |
| 42 | asm("mov %%db7, %0" :"=r" (val)); | 42 | /* |
| 43 | * Apply __FORCE_ORDER to DR7 reads to forbid re-ordering them | ||
| 44 | * with other code. | ||
| 45 | * | ||
| 46 | * This is needed because a DR7 access can cause a #VC exception | ||
| 47 | * when running under SEV-ES. Taking a #VC exception is not a | ||
| 48 | * safe thing to do just anywhere in the entry code and | ||
| 49 | * re-ordering might place the access into an unsafe location. | ||
| 50 | * | ||
| 51 | * This happened in the NMI handler, where the DR7 read was | ||
| 52 | * re-ordered to happen before the call to sev_es_ist_enter(), | ||
| 53 | * causing stack recursion. | ||
| 54 | */ | ||
| 55 | asm volatile("mov %%db7, %0" : "=r" (val) : __FORCE_ORDER); | ||
| 43 | break; | 56 | break; |
| 44 | default: | 57 | default: |
| 45 | BUG(); | 58 | BUG(); |
| @@ -66,7 +79,16 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value) · 20 unmodified lines | |||
| 66 | asm("mov %0, %%db6" ::"r" (value)); | 79 | asm("mov %0, %%db6" ::"r" (value)); |
| 67 | break; | 80 | break; |
| 68 | case 7: | 81 | case 7: |
| 69 | asm("mov %0, %%db7" ::"r" (value)); | 82 | /* |
| 83 | * Apply __FORCE_ORDER to DR7 writes to forbid re-ordering them | ||
| 84 | * with other code. | ||
| 85 | * | ||
| 86 | * While is didn't happen with a DR7 write (see the DR7 read | ||
| 87 | * comment above which explains where it happened), add the | ||
| 88 | * __FORCE_ORDER here too to avoid similar problems in the | ||
| 89 | * future. | ||
| 90 | */ | ||
| 91 | asm volatile("mov %0, %%db7" ::"r" (value), __FORCE_ORDER); | ||
| 70 | break; | 92 | break; |
| 71 | default: | 93 | default: |
| 72 | BUG(); | 94 | BUG(); |
| @@ -769,8 +769,8 @@ static void __bfq_bic_change_cgroup(struct bfq_data *bfqd, · 768 unmodified lines | |||
| 769 | * request from the old cgroup. | 769 | * request from the old cgroup. |
| 770 | */ | 770 | */ |
| 771 | bfq_put_cooperator(sync_bfqq); | 771 | bfq_put_cooperator(sync_bfqq); |
| 772 | bfq_release_process_ref(bfqd, sync_bfqq); | ||
| 773 | bic_set_bfqq(bic, NULL, true); | 772 | bic_set_bfqq(bic, NULL, true); |
| 773 | bfq_release_process_ref(bfqd, sync_bfqq); | ||
| 774 | } | 774 | } |
| 775 | } | 775 | } |
| 776 | } | 776 | } |
| @@ -5425,9 +5425,11 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio) · 5424 unmodified lines | |||
| 5425 | 5425 | ||
| 5426 | bfqq = bic_to_bfqq(bic, false); | 5426 | bfqq = bic_to_bfqq(bic, false); |
| 5427 | if (bfqq) { | 5427 | if (bfqq) { |
| 5428 | bfq_release_process_ref(bfqd, bfqq); | 5428 | struct bfq_queue *old_bfqq = bfqq; |
| 5429 | |||
| 5429 | bfqq = bfq_get_queue(bfqd, bio, false, bic, true); | 5430 | bfqq = bfq_get_queue(bfqd, bio, false, bic, true); |
| 5430 | bic_set_bfqq(bic, bfqq, false); | 5431 | bic_set_bfqq(bic, bfqq, false); |
| 5432 | bfq_release_process_ref(bfqd, old_bfqq); | ||
| 5431 | } | 5433 | } |
| 5432 | 5434 | ||
| 5433 | bfqq = bic_to_bfqq(bic, true); | 5435 | bfqq = bic_to_bfqq(bic, true); |
| @@ -2001,6 +2001,10 @@ void blk_cgroup_bio_start(struct bio *bio) · 2000 unmodified lines | |||
| 2001 | struct blkg_iostat_set *bis; | 2001 | struct blkg_iostat_set *bis; |
| 2002 | unsigned long flags; | 2002 | unsigned long flags; |
| 2003 | 2003 | ||
| 2004 | /* Root-level stats are sourced from system-wide IO stats */ | ||
| 2005 | if (!cgroup_parent(blkcg->css.cgroup)) | ||
| 2006 | return; | ||
| 2007 | |||
| 2004 | cpu = get_cpu(); | 2008 | cpu = get_cpu(); |
| 2005 | bis = per_cpu_ptr(bio->bi_blkg->iostat_cpu, cpu); | 2009 | bis = per_cpu_ptr(bio->bi_blkg->iostat_cpu, cpu); |
| 2006 | flags = u64_stats_update_begin_irqsave(&bis->sync); | 2010 | flags = u64_stats_update_begin_irqsave(&bis->sync); |
| @@ -4069,8 +4069,9 @@ EXPORT_SYMBOL(blk_mq_init_queue); · 4068 unmodified lines | |||
| 4069 | * blk_mq_destroy_queue - shutdown a request queue | 4069 | * blk_mq_destroy_queue - shutdown a request queue |
| 4070 | * @q: request queue to shutdown | 4070 | * @q: request queue to shutdown |
| 4071 | * | 4071 | * |
| 4072 | * This shuts down a request queue allocated by blk_mq_init_queue() and drops | 4072 | * This shuts down a request queue allocated by blk_mq_init_queue(). All future |
| 4073 | * the initial reference. All future requests will failed with -ENODEV. | 4073 | * requests will be failed with -ENODEV. The caller is responsible for dropping |
| 4074 | * the reference from blk_mq_init_queue() by calling blk_put_queue(). | ||
| 4074 | * | 4075 | * |
| 4075 | * Context: can sleep | 4076 | * Context: can sleep |
| 4076 | */ | 4077 | */ |
| @@ -23,8 +23,8 @@ $(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE · 22 unmodified lines | |||
| 23 | targets += blacklist_hash_list | 23 | targets += blacklist_hash_list |
| 24 | 24 | ||
| 25 | quiet_cmd_extract_certs = CERT $@ | 25 | quiet_cmd_extract_certs = CERT $@ |
| 26 | cmd_extract_certs = $(obj)/extract-cert $(extract-cert-in) $@ | 26 | cmd_extract_certs = $(obj)/extract-cert "$(extract-cert-in)" $@ |
| 27 | extract-cert-in = $(or $(filter-out $(obj)/extract-cert, $(real-prereqs)),"") | 27 | extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs)) |
| 28 | 28 | ||
| 29 | $(obj)/system_certificates.o: $(obj)/x509_certificate_list | 29 | $(obj)/system_certificates.o: $(obj)/x509_certificate_list |
| 30 | 30 | ||
| @@ -3109,7 +3109,7 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) · 3108 unmodified lines | |||
| 3109 | */ | 3109 | */ |
| 3110 | if (spd > 1) | 3110 | if (spd > 1) |
| 3111 | mask &= (1 << (spd - 1)) - 1; | 3111 | mask &= (1 << (spd - 1)) - 1; |
| 3112 | else | 3112 | else if (link->sata_spd) |
| 3113 | return -EINVAL; | 3113 | return -EINVAL; |
| 3114 | 3114 | ||
| 3115 | /* were we already at the bottom? */ | 3115 | /* were we already at the bottom? */ |
| @@ -137,7 +137,7 @@ struct ublk_device { · 136 unmodified lines | |||
| 137 | 137 | ||
| 138 | char *__queues; | 138 | char *__queues; |
| 139 | 139 | ||
| 140 | unsigned short queue_size; | 140 | unsigned int queue_size; |
| 141 | struct ublksrv_ctrl_dev_info dev_info; | 141 | struct ublksrv_ctrl_dev_info dev_info; |
| 142 | 142 | ||
| 143 | struct blk_mq_tag_set tag_set; | 143 | struct blk_mq_tag_set tag_set; |
| @@ -167,7 +167,7 @@ struct dma_fence *dma_fence_allocate_private_stub(void) · 166 unmodified lines | |||
| 167 | 0, 0); | 167 | 0, 0); |
| 168 | 168 | ||
| 169 | set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, | 169 | set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, |
| 170 | &dma_fence_stub.flags); | 170 | &fence->flags); |
| 171 | 171 | ||
| 172 | dma_fence_signal(fence); | 172 | dma_fence_signal(fence); |
| 173 | 173 | ||
| @@ -1007,6 +1007,8 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size) · 1006 unmodified lines | |||
| 1007 | /* first try to find a slot in an existing linked list entry */ | 1007 | /* first try to find a slot in an existing linked list entry */ |
| 1008 | for (prsv = efi_memreserve_root->next; prsv; ) { | 1008 | for (prsv = efi_memreserve_root->next; prsv; ) { |
| 1009 | rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB); | 1009 | rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB); |
| 1010 | if (!rsv) | ||
| 1011 | return -ENOMEM; | ||
| 1010 | index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size); | 1012 | index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size); |
| 1011 | if (index < rsv->size) { | 1013 | if (index < rsv->size) { |
| 1012 | rsv->entry[index].base = addr; | 1014 | rsv->entry[index].base = addr; |
| @@ -33,7 +33,7 @@ int __init efi_memattr_init(void) · 32 unmodified lines | |||
| 33 | return -ENOMEM; | 33 | return -ENOMEM; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | if (tbl->version > 1) { | 36 | if (tbl->version > 2) { |
| 37 | pr_warn("Unexpected EFI Memory Attributes table version %d\n", | 37 | pr_warn("Unexpected EFI Memory Attributes table version %d\n", |
| 38 | tbl->version); | 38 | tbl->version); |
| 39 | goto unmap; | 39 | goto unmap; |
| @@ -574,20 +574,27 @@ static int m10bmc_sec_probe(struct platform_device *pdev) · 573 unmodified lines | |||
| 574 | len = scnprintf(buf, SEC_UPDATE_LEN_MAX, "secure-update%d", | 574 | len = scnprintf(buf, SEC_UPDATE_LEN_MAX, "secure-update%d", |
| 575 | sec->fw_name_id); | 575 | sec->fw_name_id); |
| 576 | sec->fw_name = kmemdup_nul(buf, len, GFP_KERNEL); | 576 | sec->fw_name = kmemdup_nul(buf, len, GFP_KERNEL); |
| 577 | if (!sec->fw_name) | 577 | if (!sec->fw_name) { |
| 578 | return -ENOMEM; | 578 | ret = -ENOMEM; |
| 579 | goto fw_name_fail; | ||
| 580 | } | ||
| 579 | 581 | ||
| 580 | fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name, | 582 | fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name, |
| 581 | &m10bmc_ops, sec); | 583 | &m10bmc_ops, sec); |
| 582 | if (IS_ERR(fwl)) { | 584 | if (IS_ERR(fwl)) { |
| 583 | dev_err(sec->dev, "Firmware Upload driver failed to start\n"); | 585 | dev_err(sec->dev, "Firmware Upload driver failed to start\n"); |
| 584 | kfree(sec->fw_name); | 586 | ret = PTR_ERR(fwl); |
| 585 | xa_erase(&fw_upload_xa, sec->fw_name_id); | 587 | goto fw_uploader_fail; |
| 586 | return PTR_ERR(fwl); | ||
| 587 | } | 588 | } |
| 588 | 589 | ||
| 589 | sec->fwl = fwl; | 590 | sec->fwl = fwl; |
| 590 | return 0; | 591 | return 0; |
| 592 | |||
| 593 | fw_uploader_fail: | ||
| 594 | kfree(sec->fw_name); | ||
| 595 | fw_name_fail: | ||
| 596 | xa_erase(&fw_upload_xa, sec->fw_name_id); | ||
| 597 | return ret; | ||
| 591 | } | 598 | } |
| 592 | 599 | ||
| 593 | static int m10bmc_sec_remove(struct platform_device *pdev) | 600 | static int m10bmc_sec_remove(struct platform_device *pdev) |
| @@ -213,9 +213,9 @@ static int s10_ops_write_init(struct fpga_manager *mgr, · 212 unmodified lines | |||
| 213 | /* Allocate buffers from the service layer's pool. */ | 213 | /* Allocate buffers from the service layer's pool. */ |
| 214 | for (i = 0; i < NUM_SVC_BUFS; i++) { | 214 | for (i = 0; i < NUM_SVC_BUFS; i++) { |
| 215 | kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE); | 215 | kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE); |
| 216 | if (!kbuf) { | 216 | if (IS_ERR(kbuf)) { |
| 217 | s10_free_buffers(mgr); | 217 | s10_free_buffers(mgr); |
| 218 | ret = -ENOMEM; | 218 | ret = PTR_ERR(kbuf); |
| 219 | goto init_done; | 219 | goto init_done; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| @@ -790,8 +790,8 @@ static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, · 789 unmodified lines | |||
| 790 | * zero here */ | 790 | * zero here */ |
| 791 | WARN_ON(simd != 0); | 791 | WARN_ON(simd != 0); |
| 792 | 792 | ||
| 793 | /* type 2 wave data */ | 793 | /* type 3 wave data */ |
| 794 | dst[(*no_fields)++] = 2; | 794 | dst[(*no_fields)++] = 3; |
| 795 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_STATUS); | 795 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_STATUS); |
| 796 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_LO); | 796 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_LO); |
| 797 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_HI); | 797 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_HI); |
| @@ -337,7 +337,13 @@ const struct nbio_hdp_flush_reg nbio_v4_3_hdp_flush_reg = { · 336 unmodified lines | |||
| 337 | 337 | ||
| 338 | static void nbio_v4_3_init_registers(struct amdgpu_device *adev) | 338 | static void nbio_v4_3_init_registers(struct amdgpu_device *adev) |
| 339 | { | 339 | { |
| 340 | return; | 340 | if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(4, 3, 0)) { |
| 341 | uint32_t data; | ||
| 342 | |||
| 343 | data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2); | ||
| 344 | data &= ~RCC_DEV0_EPF2_STRAP2__STRAP_NO_SOFT_RESET_DEV0_F2_MASK; | ||
| 345 | WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2, data); | ||
| 346 | } | ||
| 341 | } | 347 | } |
| 342 | 348 | ||
| 343 | static u32 nbio_v4_3_get_rom_offset(struct amdgpu_device *adev) | 349 | static u32 nbio_v4_3_get_rom_offset(struct amdgpu_device *adev) |
| @@ -640,7 +640,8 @@ static int soc21_common_early_init(void *handle) · 639 unmodified lines | |||
| 640 | AMD_CG_SUPPORT_GFX_CGCG | | 640 | AMD_CG_SUPPORT_GFX_CGCG | |
| 641 | AMD_CG_SUPPORT_GFX_CGLS | | 641 | AMD_CG_SUPPORT_GFX_CGLS | |
| 642 | AMD_CG_SUPPORT_REPEATER_FGCG | | 642 | AMD_CG_SUPPORT_REPEATER_FGCG | |
| 643 | AMD_CG_SUPPORT_GFX_MGCG; | 643 | AMD_CG_SUPPORT_GFX_MGCG | |
| 644 | AMD_CG_SUPPORT_HDP_SD; | ||
| 644 | adev->pg_flags = AMD_PG_SUPPORT_VCN | | 645 | adev->pg_flags = AMD_PG_SUPPORT_VCN | |
| 645 | AMD_PG_SUPPORT_VCN_DPG | | 646 | AMD_PG_SUPPORT_VCN_DPG | |
| 646 | AMD_PG_SUPPORT_JPEG; | 647 | AMD_PG_SUPPORT_JPEG; |
| @@ -4501,6 +4501,17 @@ DEVICE_ATTR_WO(s3_debug); · 4500 unmodified lines | |||
| 4501 | static int dm_early_init(void *handle) | 4501 | static int dm_early_init(void *handle) |
| 4502 | { | 4502 | { |
| 4503 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 4503 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 4504 | struct amdgpu_mode_info *mode_info = &adev->mode_info; | ||
| 4505 | struct atom_context *ctx = mode_info->atom_context; | ||
| 4506 | int index = GetIndexIntoMasterTable(DATA, Object_Header); | ||
| 4507 | u16 data_offset; | ||
| 4508 | |||
| 4509 | /* if there is no object header, skip DM */ | ||
| 4510 | if (!amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { | ||
| 4511 | adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK; | ||
| 4512 | dev_info(adev->dev, "No object header, skipping DM\n"); | ||
| 4513 | return -ENOENT; | ||
| 4514 | } | ||
| 4504 | 4515 | ||
| 4505 | switch (adev->asic_type) { | 4516 | switch (adev->asic_type) { |
| 4506 | #if defined(CONFIG_DRM_AMD_DC_SI) | 4517 | #if defined(CONFIG_DRM_AMD_DC_SI) |
| @@ -874,8 +874,9 @@ static const struct dc_plane_cap plane_cap = { · 873 unmodified lines | |||
| 874 | }, | 874 | }, |
| 875 | 875 | ||
| 876 | // 6:1 downscaling ratio: 1000/6 = 166.666 | 876 | // 6:1 downscaling ratio: 1000/6 = 166.666 |
| 877 | // 4:1 downscaling ratio for ARGB888 to prevent underflow during P010 playback: 1000/4 = 250 | ||
| 877 | .max_downscale_factor = { | 878 | .max_downscale_factor = { |
| 878 | .argb8888 = 167, | 879 | .argb8888 = 250, |
| 879 | .nv12 = 167, | 880 | .nv12 = 167, |
| 880 | .fp16 = 167 | 881 | .fp16 = 167 |
| 881 | }, | 882 | }, |
| @@ -1763,7 +1764,7 @@ static bool dcn314_resource_construct( · 881 unmodified lines | |||
| 1763 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; | 1764 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; |
| 1764 | pool->base.pipe_count = pool->base.res_cap->num_timing_generator; | 1765 | pool->base.pipe_count = pool->base.res_cap->num_timing_generator; |
| 1765 | pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; | 1766 | pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; |
| 1766 | dc->caps.max_downscale_ratio = 600; | 1767 | dc->caps.max_downscale_ratio = 400; |
| 1767 | dc->caps.i2c_speed_in_khz = 100; | 1768 | dc->caps.i2c_speed_in_khz = 100; |
| 1768 | dc->caps.i2c_speed_in_khz_hdcp = 100; | 1769 | dc->caps.i2c_speed_in_khz_hdcp = 100; |
| 1769 | dc->caps.max_cursor_size = 256; | 1770 | dc->caps.max_cursor_size = 256; |
| @@ -94,7 +94,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { · 93 unmodified lines | |||
| 94 | .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, | 94 | .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, |
| 95 | .calc_vupdate_position = dcn10_calc_vupdate_position, | 95 | .calc_vupdate_position = dcn10_calc_vupdate_position, |
| 96 | .apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations, | 96 | .apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations, |
| 97 | .does_plane_fit_in_mall = dcn30_does_plane_fit_in_mall, | 97 | .does_plane_fit_in_mall = NULL, |
| 98 | .set_backlight_level = dcn21_set_backlight_level, | 98 | .set_backlight_level = dcn21_set_backlight_level, |
| 99 | .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, | 99 | .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, |
| 100 | .hardware_release = dcn30_hardware_release, | 100 | .hardware_release = dcn30_hardware_release, |
| @@ -3183,7 +3183,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman · 3182 unmodified lines | |||
| 3183 | } else { | 3183 | } else { |
| 3184 | v->MIN_DST_Y_NEXT_START[k] = v->VTotal[k] - v->VFrontPorch[k] + v->VTotal[k] - v->VActive[k] - v->VStartup[k]; | 3184 | v->MIN_DST_Y_NEXT_START[k] = v->VTotal[k] - v->VFrontPorch[k] + v->VTotal[k] - v->VActive[k] - v->VStartup[k]; |
| 3185 | } | 3185 | } |
| 3186 | v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / (double)v->HTotal[k] / v->PixelClock[k], 1.0) / 4.0; | 3186 | v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / ((double)v->HTotal[k] / v->PixelClock[k]), 1.0) / 4.0; |
| 3187 | if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k]) | 3187 | if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k]) |
| 3188 | <= (isInterlaceTiming ? | 3188 | <= (isInterlaceTiming ? |
| 3189 | dml_floor((v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]) / 2.0, 1.0) : | 3189 | dml_floor((v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]) / 2.0, 1.0) : |
| @@ -532,6 +532,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, · 531 unmodified lines | |||
| 532 | if (dmub->hw_funcs.reset) | 532 | if (dmub->hw_funcs.reset) |
| 533 | dmub->hw_funcs.reset(dmub); | 533 | dmub->hw_funcs.reset(dmub); |
| 534 | 534 | ||
| 535 | /* reset the cache of the last wptr as well now that hw is reset */ | ||
| 536 | dmub->inbox1_last_wptr = 0; | ||
| 537 | |||
| 535 | cw0.offset.quad_part = inst_fb->gpu_addr; | 538 | cw0.offset.quad_part = inst_fb->gpu_addr; |
| 536 | cw0.region.base = DMUB_CW0_BASE; | 539 | cw0.region.base = DMUB_CW0_BASE; |
| 537 | cw0.region.top = cw0.region.base + inst_fb->size - 1; | 540 | cw0.region.top = cw0.region.base + inst_fb->size - 1; |
| @@ -649,6 +652,15 @@ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub) · 111 unmodified lines | |||
| 649 | if (dmub->hw_funcs.reset) | 652 | if (dmub->hw_funcs.reset) |
| 650 | dmub->hw_funcs.reset(dmub); | 653 | dmub->hw_funcs.reset(dmub); |
| 651 | 654 | ||
| 655 | /* mailboxes have been reset in hw, so reset the sw state as well */ | ||
| 656 | dmub->inbox1_last_wptr = 0; | ||
| 657 | dmub->inbox1_rb.wrpt = 0; | ||
| 658 | dmub->inbox1_rb.rptr = 0; | ||
| 659 | dmub->outbox0_rb.wrpt = 0; | ||
| 660 | dmub->outbox0_rb.rptr = 0; | ||
| 661 | dmub->outbox1_rb.wrpt = 0; | ||
| 662 | dmub->outbox1_rb.rptr = 0; | ||
| 663 | |||
| 652 | dmub->hw_init = false; | 664 | dmub->hw_init = false; |
| 653 | 665 | ||
| 654 | return DMUB_STATUS_OK; | 666 | return DMUB_STATUS_OK; |
| @@ -2007,14 +2007,16 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ · 2006 unmodified lines | |||
| 2007 | gc_ver == IP_VERSION(10, 3, 0) || | 2007 | gc_ver == IP_VERSION(10, 3, 0) || |
| 2008 | gc_ver == IP_VERSION(10, 1, 2) || | 2008 | gc_ver == IP_VERSION(10, 1, 2) || |
| 2009 | gc_ver == IP_VERSION(11, 0, 0) || | 2009 | gc_ver == IP_VERSION(11, 0, 0) || |
| 2010 | gc_ver == IP_VERSION(11, 0, 2))) | 2010 | gc_ver == IP_VERSION(11, 0, 2) || |
| 2011 | gc_ver == IP_VERSION(11, 0, 3))) | ||
| 2011 | *states = ATTR_STATE_UNSUPPORTED; | 2012 | *states = ATTR_STATE_UNSUPPORTED; |
| 2012 | } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { | 2013 | } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { |
| 2013 | if (!(gc_ver == IP_VERSION(10, 3, 1) || | 2014 | if (!(gc_ver == IP_VERSION(10, 3, 1) || |
| 2014 | gc_ver == IP_VERSION(10, 3, 0) || | 2015 | gc_ver == IP_VERSION(10, 3, 0) || |
| 2015 | gc_ver == IP_VERSION(10, 1, 2) || | 2016 | gc_ver == IP_VERSION(10, 1, 2) || |
| 2016 | gc_ver == IP_VERSION(11, 0, 0) || | 2017 | gc_ver == IP_VERSION(11, 0, 0) || |
| 2017 | gc_ver == IP_VERSION(11, 0, 2))) | 2018 | gc_ver == IP_VERSION(11, 0, 2) || |
| 2019 | gc_ver == IP_VERSION(11, 0, 3))) | ||
| 2018 | *states = ATTR_STATE_UNSUPPORTED; | 2020 | *states = ATTR_STATE_UNSUPPORTED; |
| 2019 | } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { | 2021 | } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { |
| 2020 | if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) | 2022 | if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) |
| @@ -1499,6 +1499,20 @@ static int smu_disable_dpms(struct smu_context *smu) · 1498 unmodified lines | |||
| 1499 | } | 1499 | } |
| 1500 | } | 1500 | } |
| 1501 | 1501 | ||
| 1502 | /* | ||
| 1503 | * For SMU 13.0.4/11, PMFW will handle the features disablement properly | ||
| 1504 | * for gpu reset case. Driver involvement is unnecessary. | ||
| 1505 | */ | ||
| 1506 | if (amdgpu_in_reset(adev)) { | ||
| 1507 | switch (adev->ip_versions[MP1_HWIP][0]) { | ||
| 1508 | case IP_VERSION(13, 0, 4): | ||
| 1509 | case IP_VERSION(13, 0, 11): | ||
| 1510 | return 0; | ||
| 1511 | default: | ||
| 1512 | break; | ||
| 1513 | } | ||
| 1514 | } | ||
| 1515 | |||
| 1502 | /* | 1516 | /* |
| 1503 | * For gpu reset, runpm and hibernation through BACO, | 1517 | * For gpu reset, runpm and hibernation through BACO, |
| 1504 | * BACO feature has to be kept enabled. | 1518 | * BACO feature has to be kept enabled. |
| @@ -1319,7 +1319,7 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = { · 1318 unmodified lines | |||
| 1319 | { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 }, | 1319 | { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 }, |
| 1320 | { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 }, | 1320 | { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 }, |
| 1321 | { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 }, | 1321 | { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 }, |
| 1322 | { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 }, | 1322 | { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 }, |
| 1323 | 1323 | ||
| 1324 | { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 }, | 1324 | { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 }, |
| 1325 | { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 }, | 1325 | { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 }, |
| @@ -1861,11 +1861,19 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv, · 1860 unmodified lines | |||
| 1861 | vm = ctx->vm; | 1861 | vm = ctx->vm; |
| 1862 | GEM_BUG_ON(!vm); | 1862 | GEM_BUG_ON(!vm); |
| 1863 | 1863 | ||
| 1864 | /* | ||
| 1865 | * Get a reference for the allocated handle. Once the handle is | ||
| 1866 | * visible in the vm_xa table, userspace could try to close it | ||
| 1867 | * from under our feet, so we need to hold the extra reference | ||
| 1868 | * first. | ||
| 1869 | */ | ||
| 1870 | i915_vm_get(vm); | ||
| 1871 | |||
| 1864 | err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL); | 1872 | err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL); |
| 1865 | if (err) | 1873 | if (err) { |
| 1874 | i915_vm_put(vm); | ||
| 1866 | return err; | 1875 | return err; |
| 1867 | 1876 | } | |
| 1868 | i915_vm_get(vm); | ||
| 1869 | 1877 | ||
| 1870 | GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ | 1878 | GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ |
| 1871 | args->value = id; | 1879 | args->value = id; |
| @@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, · 304 unmodified lines | |||
| 305 | spin_unlock(&obj->vma.lock); | 305 | spin_unlock(&obj->vma.lock); |
| 306 | 306 | ||
| 307 | obj->tiling_and_stride = tiling | stride; | 307 | obj->tiling_and_stride = tiling | stride; |
| 308 | i915_gem_object_unlock(obj); | ||
| 309 | |||
| 310 | /* Force the fence to be reacquired for GTT access */ | ||
| 311 | i915_gem_object_release_mmap_gtt(obj); | ||
| 312 | 308 | ||
| 313 | /* Try to preallocate memory required to save swizzling on put-pages */ | 309 | /* Try to preallocate memory required to save swizzling on put-pages */ |
| 314 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | 310 | if (i915_gem_object_needs_bit17_swizzle(obj)) { |
| @@ -321,6 +317,11 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, · 6 unmodified lines | |||
| 321 | obj->bit_17 = NULL; | 317 | obj->bit_17 = NULL; |
| 322 | } | 318 | } |
| 323 | 319 | ||
| 320 | i915_gem_object_unlock(obj); | ||
| 321 | |||
| 322 | /* Force the fence to be reacquired for GTT access */ | ||
| 323 | i915_gem_object_release_mmap_gtt(obj); | ||
| 324 | |||
| 324 | return 0; | 325 | return 0; |
| 325 | } | 326 | } |
| 326 | 327 | ||
| @@ -528,7 +528,7 @@ retry: · 527 unmodified lines | |||
| 528 | return rq; | 528 | return rq; |
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | struct i915_request *intel_context_find_active_request(struct intel_context *ce) | 531 | struct i915_request *intel_context_get_active_request(struct intel_context *ce) |
| 532 | { | 532 | { |
| 533 | struct intel_context *parent = intel_context_to_parent(ce); | 533 | struct intel_context *parent = intel_context_to_parent(ce); |
| 534 | struct i915_request *rq, *active = NULL; | 534 | struct i915_request *rq, *active = NULL; |
| @@ -552,6 +552,8 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce) · 17 unmodified lines | |||
| 552 | 552 | ||
| 553 | active = rq; | 553 | active = rq; |
| 554 | } | 554 | } |
| 555 | if (active) | ||
| 556 | active = i915_request_get_rcu(active); | ||
| 555 | spin_unlock_irqrestore(&parent->guc_state.lock, flags); | 557 | spin_unlock_irqrestore(&parent->guc_state.lock, flags); |
| 556 | 558 | ||
| 557 | return active; | 559 | return active; |
| @@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce, · 267 unmodified lines | |||
| 268 | 268 | ||
| 269 | struct i915_request *intel_context_create_request(struct intel_context *ce); | 269 | struct i915_request *intel_context_create_request(struct intel_context *ce); |
| 270 | 270 | ||
| 271 | struct i915_request * | 271 | struct i915_request *intel_context_get_active_request(struct intel_context *ce); |
| 272 | intel_context_find_active_request(struct intel_context *ce); | ||
| 273 | 272 | ||
| 274 | static inline bool intel_context_is_barrier(const struct intel_context *ce) | 273 | static inline bool intel_context_is_barrier(const struct intel_context *ce) |
| 275 | { | 274 | { |
| @@ -248,8 +248,8 @@ void intel_engine_dump_active_requests(struct list_head *requests, · 247 unmodified lines | |||
| 248 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, | 248 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, |
| 249 | ktime_t *now); | 249 | ktime_t *now); |
| 250 | 250 | ||
| 251 | struct i915_request * | 251 | void intel_engine_get_hung_entity(struct intel_engine_cs *engine, |
| 252 | intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine); | 252 | struct intel_context **ce, struct i915_request **rq); |
| 253 | 253 | ||
| 254 | u32 intel_engine_context_size(struct intel_gt *gt, u8 class); | 254 | u32 intel_engine_context_size(struct intel_gt *gt, u8 class); |
| 255 | struct intel_context * | 255 | struct intel_context * |
| @@ -2094,17 +2094,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq) · 2093 unmodified lines | |||
| 2094 | } | 2094 | } |
| 2095 | } | 2095 | } |
| 2096 | 2096 | ||
| 2097 | static unsigned long list_count(struct list_head *list) | ||
| 2098 | { | ||
| 2099 | struct list_head *pos; | ||
| 2100 | unsigned long count = 0; | ||
| 2101 | |||
| 2102 | list_for_each(pos, list) | ||
| 2103 | count++; | ||
| 2104 | |||
| 2105 | return count; | ||
| 2106 | } | ||
| 2107 | |||
| 2108 | static unsigned long read_ul(void *p, size_t x) | 2097 | static unsigned long read_ul(void *p, size_t x) |
| 2109 | { | 2098 | { |
| 2110 | return *(unsigned long *)(p + x); | 2099 | return *(unsigned long *)(p + x); |
| @@ -2196,11 +2185,11 @@ void intel_engine_dump_active_requests(struct list_head *requests, · 85 unmodified lines | |||
| 2196 | } | 2185 | } |
| 2197 | } | 2186 | } |
| 2198 | 2187 | ||
| 2199 | static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m) | 2188 | static void engine_dump_active_requests(struct intel_engine_cs *engine, |
| 2189 | struct drm_printer *m) | ||
| 2200 | { | 2190 | { |
| 2191 | struct intel_context *hung_ce = NULL; | ||
| 2201 | struct i915_request *hung_rq = NULL; | 2192 | struct i915_request *hung_rq = NULL; |
| 2202 | struct intel_context *ce; | ||
| 2203 | bool guc; | ||
| 2204 | 2193 | ||
| 2205 | /* | 2194 | /* |
| 2206 | * No need for an engine->irq_seqno_barrier() before the seqno reads. | 2195 | * No need for an engine->irq_seqno_barrier() before the seqno reads. |
| @@ -2209,27 +2198,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d · 2 unmodified lines | |||
| 2209 | * But the intention here is just to report an instantaneous snapshot | 2198 | * But the intention here is just to report an instantaneous snapshot |
| 2210 | * so that's fine. | 2199 | * so that's fine. |
| 2211 | */ | 2200 | */ |
| 2212 | lockdep_assert_held(&engine->sched_engine->lock); | 2201 | intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq); |
| 2213 | 2202 | ||
| 2214 | drm_printf(m, "\tRequests:\n"); | 2203 | drm_printf(m, "\tRequests:\n"); |
| 2215 | 2204 | ||
| 2216 | guc = intel_uc_uses_guc_submission(&engine->gt->uc); | ||
| 2217 | if (guc) { | ||
| 2218 | ce = intel_engine_get_hung_context(engine); | ||
| 2219 | if (ce) | ||
| 2220 | hung_rq = intel_context_find_active_request(ce); | ||
| 2221 | } else { | ||
| 2222 | hung_rq = intel_engine_execlist_find_hung_request(engine); | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | if (hung_rq) | 2205 | if (hung_rq) |
| 2226 | engine_dump_request(hung_rq, m, "\t\thung"); | 2206 | engine_dump_request(hung_rq, m, "\t\thung"); |
| 2207 | else if (hung_ce) | ||
| 2208 | drm_printf(m, "\t\tGot hung ce but no hung rq!\n"); | ||
| 2227 | 2209 | ||
| 2228 | if (guc) | 2210 | if (intel_uc_uses_guc_submission(&engine->gt->uc)) |
| 2229 | intel_guc_dump_active_requests(engine, hung_rq, m); | 2211 | intel_guc_dump_active_requests(engine, hung_rq, m); |
| 2230 | else | 2212 | else |
| 2231 | intel_engine_dump_active_requests(&engine->sched_engine->requests, | 2213 | intel_execlists_dump_active_requests(engine, hung_rq, m); |
| 2232 | hung_rq, m); | 2214 | |
| 2215 | if (hung_rq) | ||
| 2216 | i915_request_put(hung_rq); | ||
| 2233 | } | 2217 | } |
| 2234 | 2218 | ||
| 2235 | void intel_engine_dump(struct intel_engine_cs *engine, | 2219 | void intel_engine_dump(struct intel_engine_cs *engine, |
| @@ -2239,7 +2223,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 3 unmodified lines | |||
| 2239 | struct i915_gpu_error * const error = &engine->i915->gpu_error; | 2223 | struct i915_gpu_error * const error = &engine->i915->gpu_error; |
| 2240 | struct i915_request *rq; | 2224 | struct i915_request *rq; |
| 2241 | intel_wakeref_t wakeref; | 2225 | intel_wakeref_t wakeref; |
| 2242 | unsigned long flags; | ||
| 2243 | ktime_t dummy; | 2226 | ktime_t dummy; |
| 2244 | 2227 | ||
| 2245 | if (header) { | 2228 | if (header) { |
| @@ -2276,13 +2259,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 30 unmodified lines | |||
| 2276 | i915_reset_count(error)); | 2259 | i915_reset_count(error)); |
| 2277 | print_properties(engine, m); | 2260 | print_properties(engine, m); |
| 2278 | 2261 | ||
| 2279 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 2280 | engine_dump_active_requests(engine, m); | 2262 | engine_dump_active_requests(engine, m); |
| 2281 | 2263 | ||
| 2282 | drm_printf(m, "\tOn hold?: %lu\n", | ||
| 2283 | list_count(&engine->sched_engine->hold)); | ||
| 2284 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 2285 | |||
| 2286 | drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); | 2264 | drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); |
| 2287 | wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); | 2265 | wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); |
| 2288 | if (wakeref) { | 2266 | if (wakeref) { |
| @@ -2328,8 +2306,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings, · 39 unmodified lines | |||
| 2328 | return siblings[0]->cops->create_virtual(siblings, count, flags); | 2306 | return siblings[0]->cops->create_virtual(siblings, count, flags); |
| 2329 | } | 2307 | } |
| 2330 | 2308 | ||
| 2331 | struct i915_request * | 2309 | static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine) |
| 2332 | intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) | ||
| 2333 | { | 2310 | { |
| 2334 | struct i915_request *request, *active = NULL; | 2311 | struct i915_request *request, *active = NULL; |
| 2335 | 2312 | ||
| @@ -2381,6 +2358,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) · 45 unmodified lines | |||
| 2381 | return active; | 2358 | return active; |
| 2382 | } | 2359 | } |
| 2383 | 2360 | ||
| 2361 | void intel_engine_get_hung_entity(struct intel_engine_cs *engine, | ||
| 2362 | struct intel_context **ce, struct i915_request **rq) | ||
| 2363 | { | ||
| 2364 | unsigned long flags; | ||
| 2365 | |||
| 2366 | *ce = intel_engine_get_hung_context(engine); | ||
| 2367 | if (*ce) { | ||
| 2368 | intel_engine_clear_hung_context(engine); | ||
| 2369 | |||
| 2370 | *rq = intel_context_get_active_request(*ce); | ||
| 2371 | return; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* | ||
| 2375 | * Getting here with GuC enabled means it is a forced error capture | ||
| 2376 | * with no actual hang. So, no need to attempt the execlist search. | ||
| 2377 | */ | ||
| 2378 | if (intel_uc_uses_guc_submission(&engine->gt->uc)) | ||
| 2379 | return; | ||
| 2380 | |||
| 2381 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 2382 | *rq = engine_execlist_find_hung_request(engine); | ||
| 2383 | if (*rq) | ||
| 2384 | *rq = i915_request_get_rcu(*rq); | ||
| 2385 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 2386 | } | ||
| 2387 | |||
| 2384 | void xehp_enable_ccs_engines(struct intel_engine_cs *engine) | 2388 | void xehp_enable_ccs_engines(struct intel_engine_cs *engine) |
| 2385 | { | 2389 | { |
| 2386 | /* | 2390 | /* |
| @@ -4148,6 +4148,33 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, · 4147 unmodified lines | |||
| 4148 | spin_unlock_irqrestore(&sched_engine->lock, flags); | 4148 | spin_unlock_irqrestore(&sched_engine->lock, flags); |
| 4149 | } | 4149 | } |
| 4150 | 4150 | ||
| 4151 | static unsigned long list_count(struct list_head *list) | ||
| 4152 | { | ||
| 4153 | struct list_head *pos; | ||
| 4154 | unsigned long count = 0; | ||
| 4155 | |||
| 4156 | list_for_each(pos, list) | ||
| 4157 | count++; | ||
| 4158 | |||
| 4159 | return count; | ||
| 4160 | } | ||
| 4161 | |||
| 4162 | void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, | ||
| 4163 | struct i915_request *hung_rq, | ||
| 4164 | struct drm_printer *m) | ||
| 4165 | { | ||
| 4166 | unsigned long flags; | ||
| 4167 | |||
| 4168 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 4169 | |||
| 4170 | intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); | ||
| 4171 | |||
| 4172 | drm_printf(m, "\tOn hold?: %lu\n", | ||
| 4173 | list_count(&engine->sched_engine->hold)); | ||
| 4174 | |||
| 4175 | spin_unlock_irqrestore(&engine->sched_engine->lock, flags); | ||
| 4176 | } | ||
| 4177 | |||
| 4151 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 4178 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
| 4152 | #include "selftest_execlists.c" | 4179 | #include "selftest_execlists.c" |
| 4153 | #endif | 4180 | #endif |
| @@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, · 31 unmodified lines | |||
| 32 | int indent), | 32 | int indent), |
| 33 | unsigned int max); | 33 | unsigned int max); |
| 34 | 34 | ||
| 35 | void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, | ||
| 36 | struct i915_request *hung_rq, | ||
| 37 | struct drm_printer *m); | ||
| 38 | |||
| 35 | bool | 39 | bool |
| 36 | intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine); | 40 | intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine); |
| 37 | 41 | ||
| @@ -1702,7 +1702,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st · 1701 unmodified lines | |||
| 1702 | goto next_context; | 1702 | goto next_context; |
| 1703 | 1703 | ||
| 1704 | guilty = false; | 1704 | guilty = false; |
| 1705 | rq = intel_context_find_active_request(ce); | 1705 | rq = intel_context_get_active_request(ce); |
| 1706 | if (!rq) { | 1706 | if (!rq) { |
| 1707 | head = ce->ring->tail; | 1707 | head = ce->ring->tail; |
| 1708 | goto out_replay; | 1708 | goto out_replay; |
| @@ -1715,6 +1715,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st · 6 unmodified lines | |||
| 1715 | head = intel_ring_wrap(ce->ring, rq->head); | 1715 | head = intel_ring_wrap(ce->ring, rq->head); |
| 1716 | 1716 | ||
| 1717 | __i915_request_reset(rq, guilty); | 1717 | __i915_request_reset(rq, guilty); |
| 1718 | i915_request_put(rq); | ||
| 1718 | out_replay: | 1719 | out_replay: |
| 1719 | guc_reset_state(ce, head, guilty); | 1720 | guc_reset_state(ce, head, guilty); |
| 1720 | next_context: | 1721 | next_context: |
| @@ -4817,6 +4818,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 3096 unmodified lines | |||
| 4817 | 4818 | ||
| 4818 | xa_lock_irqsave(&guc->context_lookup, flags); | 4819 | xa_lock_irqsave(&guc->context_lookup, flags); |
| 4819 | xa_for_each(&guc->context_lookup, index, ce) { | 4820 | xa_for_each(&guc->context_lookup, index, ce) { |
| 4821 | bool found; | ||
| 4822 | |||
| 4820 | if (!kref_get_unless_zero(&ce->ref)) | 4823 | if (!kref_get_unless_zero(&ce->ref)) |
| 4821 | continue; | 4824 | continue; |
| 4822 | 4825 | ||
| @@ -4833,10 +4836,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 10 unmodified lines | |||
| 4833 | goto next; | 4836 | goto next; |
| 4834 | } | 4837 | } |
| 4835 | 4838 | ||
| 4839 | found = false; | ||
| 4840 | spin_lock(&ce->guc_state.lock); | ||
| 4836 | list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { | 4841 | list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { |
| 4837 | if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) | 4842 | if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) |
| 4838 | continue; | 4843 | continue; |
| 4839 | 4844 | ||
| 4845 | found = true; | ||
| 4846 | break; | ||
| 4847 | } | ||
| 4848 | spin_unlock(&ce->guc_state.lock); | ||
| 4849 | |||
| 4850 | if (found) { | ||
| 4840 | intel_engine_set_hung_context(engine, ce); | 4851 | intel_engine_set_hung_context(engine, ce); |
| 4841 | 4852 | ||
| 4842 | /* Can only cope with one hang at a time... */ | 4853 | /* Can only cope with one hang at a time... */ |
| @@ -4844,6 +4855,7 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 1 unmodified line | |||
| 4844 | xa_lock(&guc->context_lookup); | 4855 | xa_lock(&guc->context_lookup); |
| 4845 | goto done; | 4856 | goto done; |
| 4846 | } | 4857 | } |
| 4858 | |||
| 4847 | next: | 4859 | next: |
| 4848 | intel_context_put(ce); | 4860 | intel_context_put(ce); |
| 4849 | xa_lock(&guc->context_lookup); | 4861 | xa_lock(&guc->context_lookup); |
| @@ -1596,43 +1596,20 @@ capture_engine(struct intel_engine_cs *engine, · 1595 unmodified lines | |||
| 1596 | { | 1596 | { |
| 1597 | struct intel_engine_capture_vma *capture = NULL; | 1597 | struct intel_engine_capture_vma *capture = NULL; |
| 1598 | struct intel_engine_coredump *ee; | 1598 | struct intel_engine_coredump *ee; |
| 1599 | struct intel_context *ce; | 1599 | struct intel_context *ce = NULL; |
| 1600 | struct i915_request *rq = NULL; | 1600 | struct i915_request *rq = NULL; |
| 1601 | unsigned long flags; | ||
| 1602 | 1601 | ||
| 1603 | ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); | 1602 | ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); |
| 1604 | if (!ee) | 1603 | if (!ee) |
| 1605 | return NULL; | 1604 | return NULL; |
| 1606 | 1605 | ||
| 1607 | ce = intel_engine_get_hung_context(engine); | 1606 | intel_engine_get_hung_entity(engine, &ce, &rq); |
| 1608 | if (ce) { | 1607 | if (!rq || !i915_request_started(rq)) |
| 1609 | intel_engine_clear_hung_context(engine); | ||
| 1610 | rq = intel_context_find_active_request(ce); | ||
| 1611 | if (!rq || !i915_request_started(rq)) | ||
| 1612 | goto no_request_capture; | ||
| 1613 | } else { | ||
| 1614 | /* | ||
| 1615 | * Getting here with GuC enabled means it is a forced error capture | ||
| 1616 | * with no actual hang. So, no need to attempt the execlist search. | ||
| 1617 | */ | ||
| 1618 | if (!intel_uc_uses_guc_submission(&engine->gt->uc)) { | ||
| 1619 | spin_lock_irqsave(&engine->sched_engine->lock, flags); | ||
| 1620 | rq = intel_engine_execlist_find_hung_request(engine); | ||
| 1621 | spin_unlock_irqrestore(&engine->sched_engine->lock, | ||
| 1622 | flags); | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | if (rq) | ||
| 1626 | rq = i915_request_get_rcu(rq); | ||
| 1627 | |||
| 1628 | if (!rq) | ||
| 1629 | goto no_request_capture; | 1608 | goto no_request_capture; |
| 1630 | 1609 | ||
| 1631 | capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); | 1610 | capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); |
| 1632 | if (!capture) { | 1611 | if (!capture) |
| 1633 | i915_request_put(rq); | ||
| 1634 | goto no_request_capture; | 1612 | goto no_request_capture; |
| 1635 | } | ||
| 1636 | if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) | 1613 | if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) |
| 1637 | intel_guc_capture_get_matching_node(engine->gt, ee, ce); | 1614 | intel_guc_capture_get_matching_node(engine->gt, ee, ce); |
| 1638 | 1615 | ||
| @@ -1642,6 +1619,8 @@ capture_engine(struct intel_engine_cs *engine, · 3 unmodified lines | |||
| 1642 | return ee; | 1619 | return ee; |
| 1643 | 1620 | ||
| 1644 | no_request_capture: | 1621 | no_request_capture: |
| 1622 | if (rq) | ||
| 1623 | i915_request_put(rq); | ||
| 1645 | kfree(ee); | 1624 | kfree(ee); |
| 1646 | return NULL; | 1625 | return NULL; |
| 1647 | } | 1626 | } |
| @@ -97,6 +97,7 @@ int gp100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n · 96 unmodified lines | |||
| 97 | int gp102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | 97 | int gp102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 98 | int gp10b_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | 98 | int gp10b_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 99 | int gv100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | 99 | int gv100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 100 | int tu102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | ||
| 100 | int ga100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | 101 | int ga100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 101 | int ga102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); | 102 | int ga102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 102 | 103 | ||
| @@ -151,6 +151,9 @@ nvkm_firmware_mem_page(struct nvkm_memory *memory) · 150 unmodified lines | |||
| 151 | static enum nvkm_memory_target | 151 | static enum nvkm_memory_target |
| 152 | nvkm_firmware_mem_target(struct nvkm_memory *memory) | 152 | nvkm_firmware_mem_target(struct nvkm_memory *memory) |
| 153 | { | 153 | { |
| 154 | if (nvkm_firmware_mem(memory)->device->func->tegra) | ||
| 155 | return NVKM_MEM_TARGET_NCOH; | ||
| 156 | |||
| 154 | return NVKM_MEM_TARGET_HOST; | 157 | return NVKM_MEM_TARGET_HOST; |
| 155 | } | 158 | } |
| 156 | 159 | ||
| @@ -2405,7 +2405,7 @@ nv162_chipset = { · 2404 unmodified lines | |||
| 2405 | .bus = { 0x00000001, gf100_bus_new }, | 2405 | .bus = { 0x00000001, gf100_bus_new }, |
| 2406 | .devinit = { 0x00000001, tu102_devinit_new }, | 2406 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2407 | .fault = { 0x00000001, tu102_fault_new }, | 2407 | .fault = { 0x00000001, tu102_fault_new }, |
| 2408 | .fb = { 0x00000001, gv100_fb_new }, | 2408 | .fb = { 0x00000001, tu102_fb_new }, |
| 2409 | .fuse = { 0x00000001, gm107_fuse_new }, | 2409 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2410 | .gpio = { 0x00000001, gk104_gpio_new }, | 2410 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2411 | .gsp = { 0x00000001, gv100_gsp_new }, | 2411 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2440,7 +2440,7 @@ nv164_chipset = { · 28 unmodified lines | |||
| 2440 | .bus = { 0x00000001, gf100_bus_new }, | 2440 | .bus = { 0x00000001, gf100_bus_new }, |
| 2441 | .devinit = { 0x00000001, tu102_devinit_new }, | 2441 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2442 | .fault = { 0x00000001, tu102_fault_new }, | 2442 | .fault = { 0x00000001, tu102_fault_new }, |
| 2443 | .fb = { 0x00000001, gv100_fb_new }, | 2443 | .fb = { 0x00000001, tu102_fb_new }, |
| 2444 | .fuse = { 0x00000001, gm107_fuse_new }, | 2444 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2445 | .gpio = { 0x00000001, gk104_gpio_new }, | 2445 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2446 | .gsp = { 0x00000001, gv100_gsp_new }, | 2446 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2475,7 +2475,7 @@ nv166_chipset = { · 28 unmodified lines | |||
| 2475 | .bus = { 0x00000001, gf100_bus_new }, | 2475 | .bus = { 0x00000001, gf100_bus_new }, |
| 2476 | .devinit = { 0x00000001, tu102_devinit_new }, | 2476 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2477 | .fault = { 0x00000001, tu102_fault_new }, | 2477 | .fault = { 0x00000001, tu102_fault_new }, |
| 2478 | .fb = { 0x00000001, gv100_fb_new }, | 2478 | .fb = { 0x00000001, tu102_fb_new }, |
| 2479 | .fuse = { 0x00000001, gm107_fuse_new }, | 2479 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2480 | .gpio = { 0x00000001, gk104_gpio_new }, | 2480 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2481 | .gsp = { 0x00000001, gv100_gsp_new }, | 2481 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2510,7 +2510,7 @@ nv167_chipset = { · 28 unmodified lines | |||
| 2510 | .bus = { 0x00000001, gf100_bus_new }, | 2510 | .bus = { 0x00000001, gf100_bus_new }, |
| 2511 | .devinit = { 0x00000001, tu102_devinit_new }, | 2511 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2512 | .fault = { 0x00000001, tu102_fault_new }, | 2512 | .fault = { 0x00000001, tu102_fault_new }, |
| 2513 | .fb = { 0x00000001, gv100_fb_new }, | 2513 | .fb = { 0x00000001, tu102_fb_new }, |
| 2514 | .fuse = { 0x00000001, gm107_fuse_new }, | 2514 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2515 | .gpio = { 0x00000001, gk104_gpio_new }, | 2515 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2516 | .gsp = { 0x00000001, gv100_gsp_new }, | 2516 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2545,7 +2545,7 @@ nv168_chipset = { · 28 unmodified lines | |||
| 2545 | .bus = { 0x00000001, gf100_bus_new }, | 2545 | .bus = { 0x00000001, gf100_bus_new }, |
| 2546 | .devinit = { 0x00000001, tu102_devinit_new }, | 2546 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2547 | .fault = { 0x00000001, tu102_fault_new }, | 2547 | .fault = { 0x00000001, tu102_fault_new }, |
| 2548 | .fb = { 0x00000001, gv100_fb_new }, | 2548 | .fb = { 0x00000001, tu102_fb_new }, |
| 2549 | .fuse = { 0x00000001, gm107_fuse_new }, | 2549 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2550 | .gpio = { 0x00000001, gk104_gpio_new }, | 2550 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2551 | .gsp = { 0x00000001, gv100_gsp_new }, | 2551 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -48,6 +48,16 @@ gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int l · 47 unmodified lines | |||
| 48 | img += 4; | 48 | img += 4; |
| 49 | len -= 4; | 49 | len -= 4; |
| 50 | } | 50 | } |
| 51 | |||
| 52 | /* Sigh. Tegra PMU FW's init message... */ | ||
| 53 | if (len) { | ||
| 54 | u32 data = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); | ||
| 55 | |||
| 56 | while (len--) { | ||
| 57 | *(u8 *)img++ = data & 0xff; | ||
| 58 | data >>= 8; | ||
| 59 | } | ||
| 60 | } | ||
| 51 | } | 61 | } |
| 52 | 62 | ||
| 53 | static void | 63 | static void |
| @@ -64,6 +74,8 @@ gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int l · 10 unmodified lines | |||
| 64 | img += 4; | 74 | img += 4; |
| 65 | len -= 4; | 75 | len -= 4; |
| 66 | } | 76 | } |
| 77 | |||
| 78 | WARN_ON(len); | ||
| 67 | } | 79 | } |
| 68 | 80 | ||
| 69 | static void | 81 | static void |
| @@ -74,7 +86,7 @@ gm200_flcn_pio_dmem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 d · 4 unmodified lines | |||
| 74 | 86 | ||
| 75 | const struct nvkm_falcon_func_pio | 87 | const struct nvkm_falcon_func_pio |
| 76 | gm200_flcn_dmem_pio = { | 88 | gm200_flcn_dmem_pio = { |
| 77 | .min = 4, | 89 | .min = 1, |
| 78 | .max = 0x100, | 90 | .max = 0x100, |
| 79 | .wr_init = gm200_flcn_pio_dmem_wr_init, | 91 | .wr_init = gm200_flcn_pio_dmem_wr_init, |
| 80 | .wr = gm200_flcn_pio_dmem_wr, | 92 | .wr = gm200_flcn_pio_dmem_wr, |
| @@ -65,10 +65,33 @@ tu102_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) · 64 unmodified lines | |||
| 65 | return ret; | 65 | return ret; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static int | ||
| 69 | tu102_devinit_wait(struct nvkm_device *device) | ||
| 70 | { | ||
| 71 | unsigned timeout = 50 + 2000; | ||
| 72 | |||
| 73 | do { | ||
| 74 | if (nvkm_rd32(device, 0x118128) & 0x00000001) { | ||
| 75 | if ((nvkm_rd32(device, 0x118234) & 0x000000ff) == 0xff) | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | usleep_range(1000, 2000); | ||
| 80 | } while (timeout--); | ||
| 81 | |||
| 82 | return -ETIMEDOUT; | ||
| 83 | } | ||
| 84 | |||
| 68 | int | 85 | int |
| 69 | tu102_devinit_post(struct nvkm_devinit *base, bool post) | 86 | tu102_devinit_post(struct nvkm_devinit *base, bool post) |
| 70 | { | 87 | { |
| 71 | struct nv50_devinit *init = nv50_devinit(base); | 88 | struct nv50_devinit *init = nv50_devinit(base); |
| 89 | int ret; | ||
| 90 | |||
| 91 | ret = tu102_devinit_wait(init->base.subdev.device); | ||
| 92 | if (ret) | ||
| 93 | return ret; | ||
| 94 | |||
| 72 | gm200_devinit_preos(init, post); | 95 | gm200_devinit_preos(init, post); |
| 73 | return 0; | 96 | return 0; |
| 74 | } | 97 | } |
| @@ -32,6 +32,7 @@ nvkm-y += nvkm/subdev/fb/gp100.o · 31 unmodified lines | |||
| 32 | nvkm-y += nvkm/subdev/fb/gp102.o | 32 | nvkm-y += nvkm/subdev/fb/gp102.o |
| 33 | nvkm-y += nvkm/subdev/fb/gp10b.o | 33 | nvkm-y += nvkm/subdev/fb/gp10b.o |
| 34 | nvkm-y += nvkm/subdev/fb/gv100.o | 34 | nvkm-y += nvkm/subdev/fb/gv100.o |
| 35 | nvkm-y += nvkm/subdev/fb/tu102.o | ||
| 35 | nvkm-y += nvkm/subdev/fb/ga100.o | 36 | nvkm-y += nvkm/subdev/fb/ga100.o |
| 36 | nvkm-y += nvkm/subdev/fb/ga102.o | 37 | nvkm-y += nvkm/subdev/fb/ga102.o |
| 37 | 38 | ||
| @@ -40,12 +40,6 @@ ga102_fb_vpr_scrub(struct nvkm_fb *fb) · 39 unmodified lines | |||
| 40 | return ret; | 40 | return ret; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static bool | ||
| 44 | ga102_fb_vpr_scrub_required(struct nvkm_fb *fb) | ||
| 45 | { | ||
| 46 | return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | static const struct nvkm_fb_func | 43 | static const struct nvkm_fb_func |
| 50 | ga102_fb = { | 44 | ga102_fb = { |
| 51 | .dtor = gf100_fb_dtor, | 45 | .dtor = gf100_fb_dtor, |
| @@ -56,7 +50,7 @@ ga102_fb = { · 4 unmodified lines | |||
| 56 | .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, | 50 | .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, |
| 57 | .ram_new = ga102_ram_new, | 51 | .ram_new = ga102_ram_new, |
| 58 | .default_bigpage = 16, | 52 | .default_bigpage = 16, |
| 59 | .vpr.scrub_required = ga102_fb_vpr_scrub_required, | 53 | .vpr.scrub_required = tu102_fb_vpr_scrub_required, |
| 60 | .vpr.scrub = ga102_fb_vpr_scrub, | 54 | .vpr.scrub = ga102_fb_vpr_scrub, |
| 61 | }; | 55 | }; |
| 62 | 56 | ||
| @@ -49,8 +49,3 @@ gv100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s · 48 unmodified lines | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); | 51 | MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); |
| 52 | MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin"); | ||
| 53 | MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin"); | ||
| 54 | MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin"); | ||
| 55 | MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin"); | ||
| 56 | MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin"); | ||
| @@ -89,4 +89,6 @@ bool gp102_fb_vpr_scrub_required(struct nvkm_fb *); · 88 unmodified lines | |||
| 89 | int gp102_fb_vpr_scrub(struct nvkm_fb *); | 89 | int gp102_fb_vpr_scrub(struct nvkm_fb *); |
| 90 | 90 | ||
| 91 | int gv100_fb_init_page(struct nvkm_fb *); | 91 | int gv100_fb_init_page(struct nvkm_fb *); |
| 92 | |||
| 93 | bool tu102_fb_vpr_scrub_required(struct nvkm_fb *); | ||
| 92 | #endif | 94 | #endif |
| @@ -0,0 +1,55 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2018 Red Hat Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | */ | ||
| 22 | #include "gf100.h" | ||
| 23 | #include "ram.h" | ||
| 24 | |||
| 25 | bool | ||
| 26 | tu102_fb_vpr_scrub_required(struct nvkm_fb *fb) | ||
| 27 | { | ||
| 28 | return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | static const struct nvkm_fb_func | ||
| 32 | tu102_fb = { | ||
| 33 | .dtor = gf100_fb_dtor, | ||
| 34 | .oneinit = gf100_fb_oneinit, | ||
| 35 | .init = gm200_fb_init, | ||
| 36 | .init_page = gv100_fb_init_page, | ||
| 37 | .init_unkn = gp100_fb_init_unkn, | ||
| 38 | .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, | ||
| 39 | .vpr.scrub_required = tu102_fb_vpr_scrub_required, | ||
| 40 | .vpr.scrub = gp102_fb_vpr_scrub, | ||
| 41 | .ram_new = gp100_ram_new, | ||
| 42 | .default_bigpage = 16, | ||
| 43 | }; | ||
| 44 | |||
| 45 | int | ||
| 46 | tu102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) | ||
| 47 | { | ||
| 48 | return gp102_fb_new_(&tu102_fb, device, type, inst, pfb); | ||
| 49 | } | ||
| 50 | |||
| 51 | MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin"); | ||
| 52 | MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin"); | ||
| 53 | MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin"); | ||
| 54 | MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin"); | ||
| 55 | MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin"); | ||
| @@ -225,7 +225,7 @@ gm20b_pmu_init(struct nvkm_pmu *pmu) · 224 unmodified lines | |||
| 225 | 225 | ||
| 226 | pmu->initmsg_received = false; | 226 | pmu->initmsg_received = false; |
| 227 | 227 | ||
| 228 | nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0); | 228 | nvkm_falcon_pio_wr(falcon, (u8 *)&args, 0, 0, DMEM, addr_args, sizeof(args), 0, false); |
| 229 | nvkm_falcon_start(falcon); | 229 | nvkm_falcon_start(falcon); |
| 230 | return 0; | 230 | return 0; |
| 231 | } | 231 | } |
| @@ -1193,14 +1193,11 @@ static int boe_panel_enter_sleep_mode(struct boe_panel *boe) · 1192 unmodified lines | |||
| 1193 | return 0; | 1193 | return 0; |
| 1194 | } | 1194 | } |
| 1195 | 1195 | ||
| 1196 | static int boe_panel_unprepare(struct drm_panel *panel) | 1196 | static int boe_panel_disable(struct drm_panel *panel) |
| 1197 | { | 1197 | { |
| 1198 | struct boe_panel *boe = to_boe_panel(panel); | 1198 | struct boe_panel *boe = to_boe_panel(panel); |
| 1199 | int ret; | 1199 | int ret; |
| 1200 | 1200 | ||
| 1201 | if (!boe->prepared) | ||
| 1202 | return 0; | ||
| 1203 | |||
| 1204 | ret = boe_panel_enter_sleep_mode(boe); | 1201 | ret = boe_panel_enter_sleep_mode(boe); |
| 1205 | if (ret < 0) { | 1202 | if (ret < 0) { |
| 1206 | dev_err(panel->dev, "failed to set panel off: %d\n", ret); | 1203 | dev_err(panel->dev, "failed to set panel off: %d\n", ret); |
| @@ -1209,6 +1206,16 @@ static int boe_panel_unprepare(struct drm_panel *panel) · 2 unmodified lines | |||
| 1209 | 1206 | ||
| 1210 | msleep(150); | 1207 | msleep(150); |
| 1211 | 1208 | ||
| 1209 | return 0; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static int boe_panel_unprepare(struct drm_panel *panel) | ||
| 1213 | { | ||
| 1214 | struct boe_panel *boe = to_boe_panel(panel); | ||
| 1215 | |||
| 1216 | if (!boe->prepared) | ||
| 1217 | return 0; | ||
| 1218 | |||
| 1212 | if (boe->desc->discharge_on_disable) { | 1219 | if (boe->desc->discharge_on_disable) { |
| 1213 | regulator_disable(boe->avee); | 1220 | regulator_disable(boe->avee); |
| 1214 | regulator_disable(boe->avdd); | 1221 | regulator_disable(boe->avdd); |
| @@ -1528,6 +1535,7 @@ static enum drm_panel_orientation boe_panel_get_orientation(struct drm_panel *pa · 313 unmodified lines | |||
| 1528 | } | 1535 | } |
| 1529 | 1536 | ||
| 1530 | static const struct drm_panel_funcs boe_panel_funcs = { | 1537 | static const struct drm_panel_funcs boe_panel_funcs = { |
| 1538 | .disable = boe_panel_disable, | ||
| 1531 | .unprepare = boe_panel_unprepare, | 1539 | .unprepare = boe_panel_unprepare, |
| 1532 | .prepare = boe_panel_prepare, | 1540 | .prepare = boe_panel_prepare, |
| 1533 | .enable = boe_panel_enable, | 1541 | .enable = boe_panel_enable, |
| @@ -656,18 +656,8 @@ static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = { · 655 unmodified lines | |||
| 656 | .atomic_check = drm_crtc_helper_atomic_check, | 656 | .atomic_check = drm_crtc_helper_atomic_check, |
| 657 | }; | 657 | }; |
| 658 | 658 | ||
| 659 | static void ssd130x_crtc_reset(struct drm_crtc *crtc) | ||
| 660 | { | ||
| 661 | struct drm_device *drm = crtc->dev; | ||
| 662 | struct ssd130x_device *ssd130x = drm_to_ssd130x(drm); | ||
| 663 | |||
| 664 | ssd130x_init(ssd130x); | ||
| 665 | |||
| 666 | drm_atomic_helper_crtc_reset(crtc); | ||
| 667 | } | ||
| 668 | |||
| 669 | static const struct drm_crtc_funcs ssd130x_crtc_funcs = { | 659 | static const struct drm_crtc_funcs ssd130x_crtc_funcs = { |
| 670 | .reset = ssd130x_crtc_reset, | 660 | .reset = drm_atomic_helper_crtc_reset, |
| 671 | .destroy = drm_crtc_cleanup, | 661 | .destroy = drm_crtc_cleanup, |
| 672 | .set_config = drm_atomic_helper_set_config, | 662 | .set_config = drm_atomic_helper_set_config, |
| 673 | .page_flip = drm_atomic_helper_page_flip, | 663 | .page_flip = drm_atomic_helper_page_flip, |
| @@ -686,6 +676,12 @@ static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder, · 12 unmodified lines | |||
| 686 | if (ret) | 676 | if (ret) |
| 687 | return; | 677 | return; |
| 688 | 678 | ||
| 679 | ret = ssd130x_init(ssd130x); | ||
| 680 | if (ret) { | ||
| 681 | ssd130x_power_off(ssd130x); | ||
| 682 | return; | ||
| 683 | } | ||
| 684 | |||
| 689 | ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON); | 685 | ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON); |
| 690 | 686 | ||
| 691 | backlight_enable(ssd130x->bl_dev); | 687 | backlight_enable(ssd130x->bl_dev); |
| @@ -3018,7 +3018,8 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) · 3017 unmodified lines | |||
| 3018 | } | 3018 | } |
| 3019 | 3019 | ||
| 3020 | vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, | 3020 | vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, |
| 3021 | vc4_hdmi, "vc4", | 3021 | vc4_hdmi, |
| 3022 | vc4_hdmi->variant->card_name, | ||
| 3022 | CEC_CAP_DEFAULTS | | 3023 | CEC_CAP_DEFAULTS | |
| 3023 | CEC_CAP_CONNECTOR_INFO, 1); | 3024 | CEC_CAP_CONNECTOR_INFO, 1); |
| 3024 | ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); | 3025 | ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); |
| @@ -227,6 +227,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) · 226 unmodified lines | |||
| 227 | cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]); | 227 | cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]); |
| 228 | if (cl_data->num_hid_devices == 0) | 228 | if (cl_data->num_hid_devices == 0) |
| 229 | return -ENODEV; | 229 | return -ENODEV; |
| 230 | cl_data->is_any_sensor_enabled = false; | ||
| 230 | 231 | ||
| 231 | INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); | 232 | INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); |
| 232 | INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); | 233 | INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); |
| @@ -287,6 +288,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) · 54 unmodified lines | |||
| 287 | status = amd_sfh_wait_for_response | 288 | status = amd_sfh_wait_for_response |
| 288 | (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); | 289 | (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); |
| 289 | if (status == SENSOR_ENABLED) { | 290 | if (status == SENSOR_ENABLED) { |
| 291 | cl_data->is_any_sensor_enabled = true; | ||
| 290 | cl_data->sensor_sts[i] = SENSOR_ENABLED; | 292 | cl_data->sensor_sts[i] = SENSOR_ENABLED; |
| 291 | rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); | 293 | rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); |
| 292 | if (rc) { | 294 | if (rc) { |
| @@ -301,19 +303,26 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) · 8 unmodified lines | |||
| 301 | cl_data->sensor_sts[i]); | 303 | cl_data->sensor_sts[i]); |
| 302 | goto cleanup; | 304 | goto cleanup; |
| 303 | } | 305 | } |
| 306 | } else { | ||
| 307 | cl_data->sensor_sts[i] = SENSOR_DISABLED; | ||
| 308 | dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", | ||
| 309 | cl_data->sensor_idx[i], | ||
| 310 | get_sensor_name(cl_data->sensor_idx[i]), | ||
| 311 | cl_data->sensor_sts[i]); | ||
| 304 | } | 312 | } |
| 305 | dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", | 313 | dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", |
| 306 | cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), | 314 | cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), |
| 307 | cl_data->sensor_sts[i]); | 315 | cl_data->sensor_sts[i]); |
| 308 | } | 316 | } |
| 309 | if (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0) { | 317 | if (!cl_data->is_any_sensor_enabled || |
| 318 | (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { | ||
| 310 | amd_sfh_hid_client_deinit(privdata); | 319 | amd_sfh_hid_client_deinit(privdata); |
| 311 | for (i = 0; i < cl_data->num_hid_devices; i++) { | 320 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 312 | devm_kfree(dev, cl_data->feature_report[i]); | 321 | devm_kfree(dev, cl_data->feature_report[i]); |
| 313 | devm_kfree(dev, in_data->input_report[i]); | 322 | devm_kfree(dev, in_data->input_report[i]); |
| 314 | devm_kfree(dev, cl_data->report_descr[i]); | 323 | devm_kfree(dev, cl_data->report_descr[i]); |
| 315 | } | 324 | } |
| 316 | dev_warn(dev, "Failed to discover, sensors not enabled\n"); | 325 | dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); |
| 317 | return -EOPNOTSUPP; | 326 | return -EOPNOTSUPP; |
| 318 | } | 327 | } |
| 319 | schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); | 328 | schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); |
| @@ -32,6 +32,7 @@ struct amd_input_data { · 31 unmodified lines | |||
| 32 | struct amdtp_cl_data { | 32 | struct amdtp_cl_data { |
| 33 | u8 init_done; | 33 | u8 init_done; |
| 34 | u32 cur_hid_dev; | 34 | u32 cur_hid_dev; |
| 35 | bool is_any_sensor_enabled; | ||
| 35 | u32 hid_dev_count; | 36 | u32 hid_dev_count; |
| 36 | u32 num_hid_devices; | 37 | u32 num_hid_devices; |
| 37 | struct device_info *hid_devices; | 38 | struct device_info *hid_devices; |
| @@ -1202,6 +1202,7 @@ int hid_open_report(struct hid_device *device) · 1201 unmodified lines | |||
| 1202 | __u8 *end; | 1202 | __u8 *end; |
| 1203 | __u8 *next; | 1203 | __u8 *next; |
| 1204 | int ret; | 1204 | int ret; |
| 1205 | int i; | ||
| 1205 | static int (*dispatch_type[])(struct hid_parser *parser, | 1206 | static int (*dispatch_type[])(struct hid_parser *parser, |
| 1206 | struct hid_item *item) = { | 1207 | struct hid_item *item) = { |
| 1207 | hid_parser_main, | 1208 | hid_parser_main, |
| @@ -1252,6 +1253,8 @@ int hid_open_report(struct hid_device *device) · 44 unmodified lines | |||
| 1252 | goto err; | 1253 | goto err; |
| 1253 | } | 1254 | } |
| 1254 | device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; | 1255 | device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; |
| 1256 | for (i = 0; i < HID_DEFAULT_NUM_COLLECTIONS; i++) | ||
| 1257 | device->collection[i].parent_idx = -1; | ||
| 1255 | 1258 | ||
| 1256 | ret = -EINVAL; | 1259 | ret = -EINVAL; |
| 1257 | while ((next = fetch_item(start, end, &item)) != NULL) { | 1260 | while ((next = fetch_item(start, end, &item)) != NULL) { |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> | 12 | * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> |
| 13 | * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com> | 13 | * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com> |
| 14 | * Copyright (c) 2020 YOSHIOKA Takuma <lo48576@hard-wi.red> | 14 | * Copyright (c) 2020 YOSHIOKA Takuma <lo48576@hard-wi.red> |
| 15 | * Copyright (c) 2022 Takahiro Fujii <fujii@xaxxi.net> | ||
| 15 | */ | 16 | */ |
| 16 | 17 | ||
| 17 | /* | 18 | /* |
| @@ -89,7 +90,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 71 unmodified lines | |||
| 89 | case USB_DEVICE_ID_ELECOM_M_DT1URBK: | 90 | case USB_DEVICE_ID_ELECOM_M_DT1URBK: |
| 90 | case USB_DEVICE_ID_ELECOM_M_DT1DRBK: | 91 | case USB_DEVICE_ID_ELECOM_M_DT1DRBK: |
| 91 | case USB_DEVICE_ID_ELECOM_M_HT1URBK: | 92 | case USB_DEVICE_ID_ELECOM_M_HT1URBK: |
| 92 | case USB_DEVICE_ID_ELECOM_M_HT1DRBK: | 93 | case USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D: |
| 93 | /* | 94 | /* |
| 94 | * Report descriptor format: | 95 | * Report descriptor format: |
| 95 | * 12: button bit count | 96 | * 12: button bit count |
| @@ -99,6 +100,16 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 3 unmodified lines | |||
| 99 | */ | 100 | */ |
| 100 | mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); | 101 | mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); |
| 101 | break; | 102 | break; |
| 103 | case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C: | ||
| 104 | /* | ||
| 105 | * Report descriptor format: | ||
| 106 | * 22: button bit count | ||
| 107 | * 30: padding bit count | ||
| 108 | * 24: button report size | ||
| 109 | * 16: button usage maximum | ||
| 110 | */ | ||
| 111 | mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16, 8); | ||
| 112 | break; | ||
| 102 | } | 113 | } |
| 103 | return rdesc; | 114 | return rdesc; |
| 104 | } | 115 | } |
| @@ -112,7 +123,8 @@ static const struct hid_device_id elecom_devices[] = { · 7 unmodified lines | |||
| 112 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, | 123 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, |
| 113 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, | 124 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, |
| 114 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, | 125 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, |
| 115 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) }, | 126 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, |
| 127 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, | ||
| 116 | { } | 128 | { } |
| 117 | }; | 129 | }; |
| 118 | MODULE_DEVICE_TABLE(hid, elecom_devices); | 130 | MODULE_DEVICE_TABLE(hid, elecom_devices); |
| @@ -413,6 +413,8 @@ · 412 unmodified lines | |||
| 413 | #define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF | 413 | #define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF |
| 414 | #define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9 | 414 | #define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9 |
| 415 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 | 415 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 |
| 416 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG 0x29DF | ||
| 417 | #define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8 | ||
| 416 | #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 | 418 | #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 |
| 417 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 | 419 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 |
| 418 | #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A | 420 | #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A |
| @@ -428,7 +430,8 @@ · 9 unmodified lines | |||
| 428 | #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe | 430 | #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe |
| 429 | #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff | 431 | #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff |
| 430 | #define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c | 432 | #define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c |
| 431 | #define USB_DEVICE_ID_ELECOM_M_HT1DRBK 0x010d | 433 | #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D 0x010d |
| 434 | #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C 0x011c | ||
| 432 | 435 | ||
| 433 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 | 436 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 |
| 434 | #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 | 437 | #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 |
| @@ -370,6 +370,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 369 unmodified lines | |||
| 370 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, | 370 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 371 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), | 371 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), |
| 372 | HID_BATTERY_QUIRK_IGNORE }, | 372 | HID_BATTERY_QUIRK_IGNORE }, |
| 373 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN), | ||
| 374 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 373 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), | 375 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), |
| 374 | HID_BATTERY_QUIRK_IGNORE }, | 376 | HID_BATTERY_QUIRK_IGNORE }, |
| 375 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), | 377 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), |
| @@ -384,6 +386,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 8 unmodified lines | |||
| 384 | HID_BATTERY_QUIRK_IGNORE }, | 386 | HID_BATTERY_QUIRK_IGNORE }, |
| 385 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), | 387 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), |
| 386 | HID_BATTERY_QUIRK_IGNORE }, | 388 | HID_BATTERY_QUIRK_IGNORE }, |
| 389 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG), | ||
| 390 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 387 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), | 391 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), |
| 388 | HID_BATTERY_QUIRK_IGNORE }, | 392 | HID_BATTERY_QUIRK_IGNORE }, |
| 389 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), | 393 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), |
| @@ -3978,7 +3978,8 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 3977 unmodified lines | |||
| 3978 | } | 3978 | } |
| 3979 | 3979 | ||
| 3980 | hidpp_initialize_battery(hidpp); | 3980 | hidpp_initialize_battery(hidpp); |
| 3981 | hidpp_initialize_hires_scroll(hidpp); | 3981 | if (!hid_is_usb(hidpp->hid_dev)) |
| 3982 | hidpp_initialize_hires_scroll(hidpp); | ||
| 3982 | 3983 | ||
| 3983 | /* forward current battery state */ | 3984 | /* forward current battery state */ |
| 3984 | if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { | 3985 | if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { |
| @@ -393,7 +393,8 @@ static const struct hid_device_id hid_have_special_driver[] = { · 392 unmodified lines | |||
| 393 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, | 393 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, |
| 394 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, | 394 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, |
| 395 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, | 395 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, |
| 396 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) }, | 396 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, |
| 397 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, | ||
| 397 | #endif | 398 | #endif |
| 398 | #if IS_ENABLED(CONFIG_HID_ELO) | 399 | #if IS_ENABLED(CONFIG_HID_ELO) |
| 399 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, | 400 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, |
| @@ -1963,7 +1963,7 @@ static void hv_balloon_debugfs_init(struct hv_dynmem_device *b) · 1962 unmodified lines | |||
| 1963 | 1963 | ||
| 1964 | static void hv_balloon_debugfs_exit(struct hv_dynmem_device *b) | 1964 | static void hv_balloon_debugfs_exit(struct hv_dynmem_device *b) |
| 1965 | { | 1965 | { |
| 1966 | debugfs_remove(debugfs_lookup("hv-balloon", NULL)); | 1966 | debugfs_lookup_and_remove("hv-balloon", NULL); |
| 1967 | } | 1967 | } |
| 1968 | 1968 | ||
| 1969 | #else | 1969 | #else |
| @@ -280,6 +280,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, · 279 unmodified lines | |||
| 280 | hid_sensor_convert_timestamp( | 280 | hid_sensor_convert_timestamp( |
| 281 | &accel_state->common_attributes, | 281 | &accel_state->common_attributes, |
| 282 | *(int64_t *)raw_data); | 282 | *(int64_t *)raw_data); |
| 283 | ret = 0; | ||
| 283 | break; | 284 | break; |
| 284 | default: | 285 | default: |
| 285 | break; | 286 | break; |
| @@ -298,8 +298,10 @@ static int berlin2_adc_probe(struct platform_device *pdev) · 297 unmodified lines | |||
| 298 | int ret; | 298 | int ret; |
| 299 | 299 | ||
| 300 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); | 300 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); |
| 301 | if (!indio_dev) | 301 | if (!indio_dev) { |
| 302 | of_node_put(parent_np); | ||
| 302 | return -ENOMEM; | 303 | return -ENOMEM; |
| 304 | } | ||
| 303 | 305 | ||
| 304 | priv = iio_priv(indio_dev); | 306 | priv = iio_priv(indio_dev); |
| 305 | 307 | ||
| @@ -86,6 +86,8 @@ · 85 unmodified lines | |||
| 86 | 86 | ||
| 87 | #define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100) | 87 | #define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100) |
| 88 | 88 | ||
| 89 | #define IMX8QXP_ADC_MAX_FIFO_SIZE 16 | ||
| 90 | |||
| 89 | struct imx8qxp_adc { | 91 | struct imx8qxp_adc { |
| 90 | struct device *dev; | 92 | struct device *dev; |
| 91 | void __iomem *regs; | 93 | void __iomem *regs; |
| @@ -95,6 +97,7 @@ struct imx8qxp_adc { · 3 unmodified lines | |||
| 95 | /* Serialise ADC channel reads */ | 97 | /* Serialise ADC channel reads */ |
| 96 | struct mutex lock; | 98 | struct mutex lock; |
| 97 | struct completion completion; | 99 | struct completion completion; |
| 100 | u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE]; | ||
| 98 | }; | 101 | }; |
| 99 | 102 | ||
| 100 | #define IMX8QXP_ADC_CHAN(_idx) { \ | 103 | #define IMX8QXP_ADC_CHAN(_idx) { \ |
| @@ -238,8 +241,7 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev, · 137 unmodified lines | |||
| 238 | return ret; | 241 | return ret; |
| 239 | } | 242 | } |
| 240 | 243 | ||
| 241 | *val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK, | 244 | *val = adc->fifo[0]; |
| 242 | readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO)); | ||
| 243 | 245 | ||
| 244 | mutex_unlock(&adc->lock); | 246 | mutex_unlock(&adc->lock); |
| 245 | return IIO_VAL_INT; | 247 | return IIO_VAL_INT; |
| @@ -265,10 +267,15 @@ static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id) · 19 unmodified lines | |||
| 265 | { | 267 | { |
| 266 | struct imx8qxp_adc *adc = dev_id; | 268 | struct imx8qxp_adc *adc = dev_id; |
| 267 | u32 fifo_count; | 269 | u32 fifo_count; |
| 270 | int i; | ||
| 268 | 271 | ||
| 269 | fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK, | 272 | fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK, |
| 270 | readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL)); | 273 | readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL)); |
| 271 | 274 | ||
| 275 | for (i = 0; i < fifo_count; i++) | ||
| 276 | adc->fifo[i] = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK, | ||
| 277 | readl_relaxed(adc->regs + IMX8QXP_ADR_ADC_RESFIFO)); | ||
| 278 | |||
| 272 | if (fifo_count) | 279 | if (fifo_count) |
| 273 | complete(&adc->completion); | 280 | complete(&adc->completion); |
| 274 | 281 | ||
| @@ -1520,6 +1520,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = { · 1519 unmodified lines | |||
| 1520 | }, | 1520 | }, |
| 1521 | {} | 1521 | {} |
| 1522 | }; | 1522 | }; |
| 1523 | MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match); | ||
| 1523 | 1524 | ||
| 1524 | static int stm32_dfsdm_adc_probe(struct platform_device *pdev) | 1525 | static int stm32_dfsdm_adc_probe(struct platform_device *pdev) |
| 1525 | { | 1526 | { |
| @@ -57,6 +57,18 @@ · 56 unmodified lines | |||
| 57 | #define TWL6030_GPADCS BIT(1) | 57 | #define TWL6030_GPADCS BIT(1) |
| 58 | #define TWL6030_GPADCR BIT(0) | 58 | #define TWL6030_GPADCR BIT(0) |
| 59 | 59 | ||
| 60 | #define USB_VBUS_CTRL_SET 0x04 | ||
| 61 | #define USB_ID_CTRL_SET 0x06 | ||
| 62 | |||
| 63 | #define TWL6030_MISC1 0xE4 | ||
| 64 | #define VBUS_MEAS 0x01 | ||
| 65 | #define ID_MEAS 0x01 | ||
| 66 | |||
| 67 | #define VAC_MEAS 0x04 | ||
| 68 | #define VBAT_MEAS 0x02 | ||
| 69 | #define BB_MEAS 0x01 | ||
| 70 | |||
| 71 | |||
| 60 | /** | 72 | /** |
| 61 | * struct twl6030_chnl_calib - channel calibration | 73 | * struct twl6030_chnl_calib - channel calibration |
| 62 | * @gain: slope coefficient for ideal curve | 74 | * @gain: slope coefficient for ideal curve |
| @@ -927,6 +939,26 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) · 864 unmodified lines | |||
| 927 | return ret; | 939 | return ret; |
| 928 | } | 940 | } |
| 929 | 941 | ||
| 942 | ret = twl_i2c_write_u8(TWL_MODULE_USB, VBUS_MEAS, USB_VBUS_CTRL_SET); | ||
| 943 | if (ret < 0) { | ||
| 944 | dev_err(dev, "failed to wire up inputs\n"); | ||
| 945 | return ret; | ||
| 946 | } | ||
| 947 | |||
| 948 | ret = twl_i2c_write_u8(TWL_MODULE_USB, ID_MEAS, USB_ID_CTRL_SET); | ||
| 949 | if (ret < 0) { | ||
| 950 | dev_err(dev, "failed to wire up inputs\n"); | ||
| 951 | return ret; | ||
| 952 | } | ||
| 953 | |||
| 954 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, | ||
| 955 | VBAT_MEAS | BB_MEAS | VAC_MEAS, | ||
| 956 | TWL6030_MISC1); | ||
| 957 | if (ret < 0) { | ||
| 958 | dev_err(dev, "failed to wire up inputs\n"); | ||
| 959 | return ret; | ||
| 960 | } | ||
| 961 | |||
| 930 | indio_dev->name = DRIVER_NAME; | 962 | indio_dev->name = DRIVER_NAME; |
| 931 | indio_dev->info = &twl6030_gpadc_iio_info; | 963 | indio_dev->info = &twl6030_gpadc_iio_info; |
| 932 | indio_dev->modes = INDIO_DIRECT_MODE; | 964 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -1329,7 +1329,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev) · 1328 unmodified lines | |||
| 1329 | 1329 | ||
| 1330 | dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL); | 1330 | dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL); |
| 1331 | if (!dev_channels) | 1331 | if (!dev_channels) |
| 1332 | ret = -ENOMEM; | 1332 | return -ENOMEM; |
| 1333 | 1333 | ||
| 1334 | indio_dev->channels = dev_channels; | 1334 | indio_dev->channels = dev_channels; |
| 1335 | indio_dev->num_channels = num_channels; | 1335 | indio_dev->num_channels = num_channels; |
| @@ -231,6 +231,7 @@ static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev, · 230 unmodified lines | |||
| 231 | gyro_state->timestamp = | 231 | gyro_state->timestamp = |
| 232 | hid_sensor_convert_timestamp(&gyro_state->common_attributes, | 232 | hid_sensor_convert_timestamp(&gyro_state->common_attributes, |
| 233 | *(s64 *)raw_data); | 233 | *(s64 *)raw_data); |
| 234 | ret = 0; | ||
| 234 | break; | 235 | break; |
| 235 | default: | 236 | default: |
| 236 | break; | 237 | break; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/regmap.h> | 10 | #include <linux/regmap.h> |
| 11 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
| 12 | #include <linux/bitops.h> | 12 | #include <linux/bitops.h> |
| 13 | #include <linux/bitfield.h> | ||
| 13 | 14 | ||
| 14 | #include <linux/iio/iio.h> | 15 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | 16 | #include <linux/iio/sysfs.h> |
| @@ -144,9 +145,8 @@ · 128 unmodified lines | |||
| 144 | #define FXOS8700_NVM_DATA_BNK0 0xa7 | 145 | #define FXOS8700_NVM_DATA_BNK0 0xa7 |
| 145 | 146 | ||
| 146 | /* Bit definitions for FXOS8700_CTRL_REG1 */ | 147 | /* Bit definitions for FXOS8700_CTRL_REG1 */ |
| 147 | #define FXOS8700_CTRL_ODR_MSK 0x38 | ||
| 148 | #define FXOS8700_CTRL_ODR_MAX 0x00 | 148 | #define FXOS8700_CTRL_ODR_MAX 0x00 |
| 149 | #define FXOS8700_CTRL_ODR_MIN GENMASK(4, 3) | 149 | #define FXOS8700_CTRL_ODR_MSK GENMASK(5, 3) |
| 150 | 150 | ||
| 151 | /* Bit definitions for FXOS8700_M_CTRL_REG1 */ | 151 | /* Bit definitions for FXOS8700_M_CTRL_REG1 */ |
| 152 | #define FXOS8700_HMS_MASK GENMASK(1, 0) | 152 | #define FXOS8700_HMS_MASK GENMASK(1, 0) |
| @@ -320,7 +320,7 @@ static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type) · 167 unmodified lines | |||
| 320 | switch (iio_type) { | 320 | switch (iio_type) { |
| 321 | case IIO_ACCEL: | 321 | case IIO_ACCEL: |
| 322 | return FXOS8700_ACCEL; | 322 | return FXOS8700_ACCEL; |
| 323 | case IIO_ANGL_VEL: | 323 | case IIO_MAGN: |
| 324 | return FXOS8700_MAGN; | 324 | return FXOS8700_MAGN; |
| 325 | default: | 325 | default: |
| 326 | return -EINVAL; | 326 | return -EINVAL; |
| @@ -345,15 +345,35 @@ static int fxos8700_set_active_mode(struct fxos8700_data *data, · 18 unmodified lines | |||
| 345 | static int fxos8700_set_scale(struct fxos8700_data *data, | 345 | static int fxos8700_set_scale(struct fxos8700_data *data, |
| 346 | enum fxos8700_sensor t, int uscale) | 346 | enum fxos8700_sensor t, int uscale) |
| 347 | { | 347 | { |
| 348 | int i; | 348 | int i, ret, val; |
| 349 | bool active_mode; | ||
| 349 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); | 350 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); |
| 350 | struct device *dev = regmap_get_device(data->regmap); | 351 | struct device *dev = regmap_get_device(data->regmap); |
| 351 | 352 | ||
| 352 | if (t == FXOS8700_MAGN) { | 353 | if (t == FXOS8700_MAGN) { |
| 353 | dev_err(dev, "Magnetometer scale is locked at 1200uT\n"); | 354 | dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n"); |
| 354 | return -EINVAL; | 355 | return -EINVAL; |
| 355 | } | 356 | } |
| 356 | 357 | ||
| 358 | /* | ||
| 359 | * When device is in active mode, it failed to set an ACCEL | ||
| 360 | * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG. | ||
| 361 | * This is not align with the datasheet, but it is a fxos8700 | ||
| 362 | * chip behavier. Set the device in standby mode before setting | ||
| 363 | * an ACCEL full-scale range. | ||
| 364 | */ | ||
| 365 | ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val); | ||
| 366 | if (ret) | ||
| 367 | return ret; | ||
| 368 | |||
| 369 | active_mode = val & FXOS8700_ACTIVE; | ||
| 370 | if (active_mode) { | ||
| 371 | ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, | ||
| 372 | val & ~FXOS8700_ACTIVE); | ||
| 373 | if (ret) | ||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 357 | for (i = 0; i < scale_num; i++) | 377 | for (i = 0; i < scale_num; i++) |
| 358 | if (fxos8700_accel_scale[i].uscale == uscale) | 378 | if (fxos8700_accel_scale[i].uscale == uscale) |
| 359 | break; | 379 | break; |
| @@ -361,8 +381,12 @@ static int fxos8700_set_scale(struct fxos8700_data *data, · 1 unmodified line | |||
| 361 | if (i == scale_num) | 381 | if (i == scale_num) |
| 362 | return -EINVAL; | 382 | return -EINVAL; |
| 363 | 383 | ||
| 364 | return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, | 384 | ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, |
| 365 | fxos8700_accel_scale[i].bits); | 385 | fxos8700_accel_scale[i].bits); |
| 386 | if (ret) | ||
| 387 | return ret; | ||
| 388 | return regmap_write(data->regmap, FXOS8700_CTRL_REG1, | ||
| 389 | active_mode); | ||
| 366 | } | 390 | } |
| 367 | 391 | ||
| 368 | static int fxos8700_get_scale(struct fxos8700_data *data, | 392 | static int fxos8700_get_scale(struct fxos8700_data *data, |
| @@ -372,7 +396,7 @@ static int fxos8700_get_scale(struct fxos8700_data *data, · 3 unmodified lines | |||
| 372 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); | 396 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); |
| 373 | 397 | ||
| 374 | if (t == FXOS8700_MAGN) { | 398 | if (t == FXOS8700_MAGN) { |
| 375 | *uscale = 1200; /* Magnetometer is locked at 1200uT */ | 399 | *uscale = 1000; /* Magnetometer is locked at 0.001Gs */ |
| 376 | return 0; | 400 | return 0; |
| 377 | } | 401 | } |
| 378 | 402 | ||
| @@ -394,22 +418,61 @@ static int fxos8700_get_data(struct fxos8700_data *data, int chan_type, · 15 unmodified lines | |||
| 394 | int axis, int *val) | 418 | int axis, int *val) |
| 395 | { | 419 | { |
| 396 | u8 base, reg; | 420 | u8 base, reg; |
| 421 | s16 tmp; | ||
| 397 | int ret; | 422 | int ret; |
| 398 | enum fxos8700_sensor type = fxos8700_to_sensor(chan_type); | ||
| 399 | 423 | ||
| 400 | base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB; | 424 | /* |
| 425 | * Different register base addresses varies with channel types. | ||
| 426 | * This bug hasn't been noticed before because using an enum is | ||
| 427 | * really hard to read. Use an a switch statement to take over that. | ||
| 428 | */ | ||
| 429 | switch (chan_type) { | ||
| 430 | case IIO_ACCEL: | ||
| 431 | base = FXOS8700_OUT_X_MSB; | ||
| 432 | break; | ||
| 433 | case IIO_MAGN: | ||
| 434 | base = FXOS8700_M_OUT_X_MSB; | ||
| 435 | break; | ||
| 436 | default: | ||
| 437 | return -EINVAL; | ||
| 438 | } | ||
| 401 | 439 | ||
| 402 | /* Block read 6 bytes of device output registers to avoid data loss */ | 440 | /* Block read 6 bytes of device output registers to avoid data loss */ |
| 403 | ret = regmap_bulk_read(data->regmap, base, data->buf, | 441 | ret = regmap_bulk_read(data->regmap, base, data->buf, |
| 404 | FXOS8700_DATA_BUF_SIZE); | 442 | sizeof(data->buf)); |
| 405 | if (ret) | 443 | if (ret) |
| 406 | return ret; | 444 | return ret; |
| 407 | 445 | ||
| 408 | /* Convert axis to buffer index */ | 446 | /* Convert axis to buffer index */ |
| 409 | reg = axis - IIO_MOD_X; | 447 | reg = axis - IIO_MOD_X; |
| 410 | 448 | ||
| 449 | /* | ||
| 450 | * Convert to native endianness. The accel data and magn data | ||
| 451 | * are signed, so a forced type conversion is needed. | ||
| 452 | */ | ||
| 453 | tmp = be16_to_cpu(data->buf[reg]); | ||
| 454 | |||
| 455 | /* | ||
| 456 | * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis | ||
| 457 | * 14-bit left-justified sample data and MAGN output data registers | ||
| 458 | * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply | ||
| 459 | * a signed 2 bits right shift to the readback raw data from ACCEL | ||
| 460 | * output data register and keep that from MAGN sensor as the origin. | ||
| 461 | * Value should be extended to 32 bit. | ||
| 462 | */ | ||
| 463 | switch (chan_type) { | ||
| 464 | case IIO_ACCEL: | ||
| 465 | tmp = tmp >> 2; | ||
| 466 | break; | ||
| 467 | case IIO_MAGN: | ||
| 468 | /* Nothing to do */ | ||
| 469 | break; | ||
| 470 | default: | ||
| 471 | return -EINVAL; | ||
| 472 | } | ||
| 473 | |||
| 411 | /* Convert to native endianness */ | 474 | /* Convert to native endianness */ |
| 412 | *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15); | 475 | *val = sign_extend32(tmp, 15); |
| 413 | 476 | ||
| 414 | return 0; | 477 | return 0; |
| 415 | } | 478 | } |
| @@ -445,10 +508,9 @@ static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t, · 29 unmodified lines | |||
| 445 | if (i >= odr_num) | 508 | if (i >= odr_num) |
| 446 | return -EINVAL; | 509 | return -EINVAL; |
| 447 | 510 | ||
| 448 | return regmap_update_bits(data->regmap, | 511 | val &= ~FXOS8700_CTRL_ODR_MSK; |
| 449 | FXOS8700_CTRL_REG1, | 512 | val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE; |
| 450 | FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE, | 513 | return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val); |
| 451 | fxos8700_odr[i].bits << 3 | active_mode); | ||
| 452 | } | 514 | } |
| 453 | 515 | ||
| 454 | static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t, | 516 | static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t, |
| @@ -461,7 +523,7 @@ static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t, · 6 unmodified lines | |||
| 461 | if (ret) | 523 | if (ret) |
| 462 | return ret; | 524 | return ret; |
| 463 | 525 | ||
| 464 | val &= FXOS8700_CTRL_ODR_MSK; | 526 | val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val); |
| 465 | 527 | ||
| 466 | for (i = 0; i < odr_num; i++) | 528 | for (i = 0; i < odr_num; i++) |
| 467 | if (val == fxos8700_odr[i].bits) | 529 | if (val == fxos8700_odr[i].bits) |
| @@ -526,7 +588,7 @@ static IIO_CONST_ATTR(in_accel_sampling_frequency_available, · 58 unmodified lines | |||
| 526 | static IIO_CONST_ATTR(in_magn_sampling_frequency_available, | 588 | static IIO_CONST_ATTR(in_magn_sampling_frequency_available, |
| 527 | "1.5625 6.25 12.5 50 100 200 400 800"); | 589 | "1.5625 6.25 12.5 50 100 200 400 800"); |
| 528 | static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976"); | 590 | static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976"); |
| 529 | static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200"); | 591 | static IIO_CONST_ATTR(in_magn_scale_available, "0.001000"); |
| 530 | 592 | ||
| 531 | static struct attribute *fxos8700_attrs[] = { | 593 | static struct attribute *fxos8700_attrs[] = { |
| 532 | &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr, | 594 | &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr, |
| @@ -592,14 +654,19 @@ static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi) · 59 unmodified lines | |||
| 592 | if (ret) | 654 | if (ret) |
| 593 | return ret; | 655 | return ret; |
| 594 | 656 | ||
| 595 | /* Max ODR (800Hz individual or 400Hz hybrid), active mode */ | 657 | /* |
| 596 | ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, | 658 | * Set max full-scale range (+/-8G) for ACCEL sensor in chip |
| 597 | FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE); | 659 | * initialization then activate the device. |
| 660 | */ | ||
| 661 | ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G); | ||
| 598 | if (ret) | 662 | if (ret) |
| 599 | return ret; | 663 | return ret; |
| 600 | 664 | ||
| 601 | /* Set for max full-scale range (+/-8G) */ | 665 | /* Max ODR (800Hz individual or 400Hz hybrid), active mode */ |
| 602 | return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G); | 666 | return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1, |
| 667 | FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE, | ||
| 668 | FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) | | ||
| 669 | FXOS8700_ACTIVE); | ||
| 603 | } | 670 | } |
| 604 | 671 | ||
| 605 | static void fxos8700_chip_uninit(void *data) | 672 | static void fxos8700_chip_uninit(void *data) |
| @@ -4,6 +4,7 @@ config IIO_ST_LSM6DSX · 3 unmodified lines | |||
| 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" | 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" |
| 5 | depends on (I2C || SPI || I3C) | 5 | depends on (I2C || SPI || I3C) |
| 6 | select IIO_BUFFER | 6 | select IIO_BUFFER |
| 7 | select IIO_TRIGGERED_BUFFER | ||
| 7 | select IIO_KFIFO_BUF | 8 | select IIO_KFIFO_BUF |
| 8 | select IIO_ST_LSM6DSX_I2C if (I2C) | 9 | select IIO_ST_LSM6DSX_I2C if (I2C) |
| 9 | select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) | 10 | select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) |
| @@ -440,6 +440,8 @@ static int cm32181_probe(struct i2c_client *client) · 439 unmodified lines | |||
| 440 | if (!indio_dev) | 440 | if (!indio_dev) |
| 441 | return -ENOMEM; | 441 | return -ENOMEM; |
| 442 | 442 | ||
| 443 | i2c_set_clientdata(client, indio_dev); | ||
| 444 | |||
| 443 | /* | 445 | /* |
| 444 | * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the | 446 | * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the |
| 445 | * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address. | 447 | * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address. |
| @@ -460,8 +462,6 @@ static int cm32181_probe(struct i2c_client *client) · 14 unmodified lines | |||
| 460 | return PTR_ERR(client); | 462 | return PTR_ERR(client); |
| 461 | } | 463 | } |
| 462 | 464 | ||
| 463 | i2c_set_clientdata(client, indio_dev); | ||
| 464 | |||
| 465 | cm32181 = iio_priv(indio_dev); | 465 | cm32181 = iio_priv(indio_dev); |
| 466 | cm32181->client = client; | 466 | cm32181->client = client; |
| 467 | cm32181->dev = dev; | 467 | cm32181->dev = dev; |
| @@ -490,7 +490,8 @@ static int cm32181_probe(struct i2c_client *client) · 22 unmodified lines | |||
| 490 | 490 | ||
| 491 | static int cm32181_suspend(struct device *dev) | 491 | static int cm32181_suspend(struct device *dev) |
| 492 | { | 492 | { |
| 493 | struct i2c_client *client = to_i2c_client(dev); | 493 | struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev)); |
| 494 | struct i2c_client *client = cm32181->client; | ||
| 494 | 495 | ||
| 495 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, | 496 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, |
| 496 | CM32181_CMD_ALS_DISABLE); | 497 | CM32181_CMD_ALS_DISABLE); |
| @@ -498,8 +499,8 @@ static int cm32181_suspend(struct device *dev) · 1 unmodified line | |||
| 498 | 499 | ||
| 499 | static int cm32181_resume(struct device *dev) | 500 | static int cm32181_resume(struct device *dev) |
| 500 | { | 501 | { |
| 501 | struct i2c_client *client = to_i2c_client(dev); | ||
| 502 | struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev)); | 502 | struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev)); |
| 503 | struct i2c_client *client = cm32181->client; | ||
| 503 | 504 | ||
| 504 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, | 505 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, |
| 505 | cm32181->conf_regs[CM32181_REG_ADDR_CMD]); | 506 | cm32181->conf_regs[CM32181_REG_ADDR_CMD]); |
| @@ -76,7 +76,7 @@ void bond_debug_reregister(struct bonding *bond) · 75 unmodified lines | |||
| 76 | 76 | ||
| 77 | d = debugfs_rename(bonding_debug_root, bond->debug_dir, | 77 | d = debugfs_rename(bonding_debug_root, bond->debug_dir, |
| 78 | bonding_debug_root, bond->dev->name); | 78 | bonding_debug_root, bond->dev->name); |
| 79 | if (d) { | 79 | if (!IS_ERR(d)) { |
| 80 | bond->debug_dir = d; | 80 | bond->debug_dir = d; |
| 81 | } else { | 81 | } else { |
| 82 | netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n"); | 82 | netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n"); |
| @@ -1302,14 +1302,26 @@ mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port) · 1301 unmodified lines | |||
| 1302 | if (!priv->ports[port].pvid) | 1302 | if (!priv->ports[port].pvid) |
| 1303 | mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK, | 1303 | mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK, |
| 1304 | MT7530_VLAN_ACC_TAGGED); | 1304 | MT7530_VLAN_ACC_TAGGED); |
| 1305 | } | ||
| 1306 | 1305 | ||
| 1307 | /* Set the port as a user port which is to be able to recognize VID | 1306 | /* Set the port as a user port which is to be able to recognize |
| 1308 | * from incoming packets before fetching entry within the VLAN table. | 1307 | * VID from incoming packets before fetching entry within the |
| 1309 | */ | 1308 | * VLAN table. |
| 1310 | mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, | 1309 | */ |
| 1311 | VLAN_ATTR(MT7530_VLAN_USER) | | 1310 | mt7530_rmw(priv, MT7530_PVC_P(port), |
| 1312 | PVC_EG_TAG(MT7530_VLAN_EG_DISABLED)); | 1311 | VLAN_ATTR_MASK | PVC_EG_TAG_MASK, |
| 1312 | VLAN_ATTR(MT7530_VLAN_USER) | | ||
| 1313 | PVC_EG_TAG(MT7530_VLAN_EG_DISABLED)); | ||
| 1314 | } else { | ||
| 1315 | /* Also set CPU ports to the "user" VLAN port attribute, to | ||
| 1316 | * allow VLAN classification, but keep the EG_TAG attribute as | ||
| 1317 | * "consistent" (i.o.w. don't change its value) for packets | ||
| 1318 | * received by the switch from the CPU, so that tagged packets | ||
| 1319 | * are forwarded to user ports as tagged, and untagged as | ||
| 1320 | * untagged. | ||
| 1321 | */ | ||
| 1322 | mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK, | ||
| 1323 | VLAN_ATTR(MT7530_VLAN_USER)); | ||
| 1324 | } | ||
| 1313 | } | 1325 | } |
| 1314 | 1326 | ||
| 1315 | static void | 1327 | static void |
| @@ -4684,25 +4684,26 @@ static int init_reset_optional(struct platform_device *pdev) · 4683 unmodified lines | |||
| 4684 | if (ret) | 4684 | if (ret) |
| 4685 | return dev_err_probe(&pdev->dev, ret, | 4685 | return dev_err_probe(&pdev->dev, ret, |
| 4686 | "failed to init SGMII PHY\n"); | 4686 | "failed to init SGMII PHY\n"); |
| 4687 | } | ||
| 4688 | 4687 | ||
| 4689 | ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_GEM_CONFIG); | 4688 | ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_GEM_CONFIG); |
| 4690 | if (!ret) { | 4689 | if (!ret) { |
| 4691 | u32 pm_info[2]; | 4690 | u32 pm_info[2]; |
| 4691 | |||
| 4692 | ret = of_property_read_u32_array(pdev->dev.of_node, "power-domains", | ||
| 4693 | pm_info, ARRAY_SIZE(pm_info)); | ||
| 4694 | if (ret) { | ||
| 4695 | dev_err(&pdev->dev, "Failed to read power management information\n"); | ||
| 4696 | goto err_out_phy_exit; | ||
| 4697 | } | ||
| 4698 | ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_FIXED, 0); | ||
| 4699 | if (ret) | ||
| 4700 | goto err_out_phy_exit; | ||
| 4692 | 4701 | ||
| 4693 | ret = of_property_read_u32_array(pdev->dev.of_node, "power-domains", | 4702 | ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_SGMII_MODE, 1); |
| 4694 | pm_info, ARRAY_SIZE(pm_info)); | 4703 | if (ret) |
| 4695 | if (ret) { | 4704 | goto err_out_phy_exit; |
| 4696 | dev_err(&pdev->dev, "Failed to read power management information\n"); | ||
| 4697 | goto err_out_phy_exit; | ||
| 4698 | } | 4705 | } |
| 4699 | ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_FIXED, 0); | ||
| 4700 | if (ret) | ||
| 4701 | goto err_out_phy_exit; | ||
| 4702 | 4706 | ||
| 4703 | ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_SGMII_MODE, 1); | ||
| 4704 | if (ret) | ||
| 4705 | goto err_out_phy_exit; | ||
| 4706 | } | 4707 | } |
| 4707 | 4708 | ||
| 4708 | /* Fully reset controller at hardware level if mapped in device tree */ | 4709 | /* Fully reset controller at hardware level if mapped in device tree */ |
| @@ -5534,7 +5534,7 @@ bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw) · 5533 unmodified lines | |||
| 5534 | * returned by the firmware is a 16 bit * value, but is indexed | 5534 | * returned by the firmware is a 16 bit * value, but is indexed |
| 5535 | * by [fls(speed) - 1] | 5535 | * by [fls(speed) - 1] |
| 5536 | */ | 5536 | */ |
| 5537 | static const u32 ice_aq_to_link_speed[15] = { | 5537 | static const u32 ice_aq_to_link_speed[] = { |
| 5538 | SPEED_10, /* BIT(0) */ | 5538 | SPEED_10, /* BIT(0) */ |
| 5539 | SPEED_100, | 5539 | SPEED_100, |
| 5540 | SPEED_1000, | 5540 | SPEED_1000, |
| @@ -5546,10 +5546,6 @@ static const u32 ice_aq_to_link_speed[15] = { · 5 unmodified lines | |||
| 5546 | SPEED_40000, | 5546 | SPEED_40000, |
| 5547 | SPEED_50000, | 5547 | SPEED_50000, |
| 5548 | SPEED_100000, /* BIT(10) */ | 5548 | SPEED_100000, /* BIT(10) */ |
| 5549 | 0, | ||
| 5550 | 0, | ||
| 5551 | 0, | ||
| 5552 | 0 /* BIT(14) */ | ||
| 5553 | }; | 5549 | }; |
| 5554 | 5550 | ||
| 5555 | /** | 5551 | /** |
| @@ -5560,5 +5556,8 @@ static const u32 ice_aq_to_link_speed[15] = { · 4 unmodified lines | |||
| 5560 | */ | 5556 | */ |
| 5561 | u32 ice_get_link_speed(u16 index) | 5557 | u32 ice_get_link_speed(u16 index) |
| 5562 | { | 5558 | { |
| 5559 | if (index >= ARRAY_SIZE(ice_aq_to_link_speed)) | ||
| 5560 | return 0; | ||
| 5561 | |||
| 5563 | return ice_aq_to_link_speed[index]; | 5562 | return ice_aq_to_link_speed[index]; |
| 5564 | } | 5563 | } |
| @@ -5724,7 +5724,7 @@ static int __init ice_module_init(void) · 5723 unmodified lines | |||
| 5724 | pr_info("%s\n", ice_driver_string); | 5724 | pr_info("%s\n", ice_driver_string); |
| 5725 | pr_info("%s\n", ice_copyright); | 5725 | pr_info("%s\n", ice_copyright); |
| 5726 | 5726 | ||
| 5727 | ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME); | 5727 | ice_wq = alloc_workqueue("%s", 0, 0, KBUILD_MODNAME); |
| 5728 | if (!ice_wq) { | 5728 | if (!ice_wq) { |
| 5729 | pr_err("Failed to create workqueue\n"); | 5729 | pr_err("Failed to create workqueue\n"); |
| 5730 | return -ENOMEM; | 5730 | return -ENOMEM; |
| @@ -5420,7 +5420,7 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, · 5419 unmodified lines | |||
| 5420 | */ | 5420 | */ |
| 5421 | status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw)); | 5421 | status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw)); |
| 5422 | if (status) | 5422 | if (status) |
| 5423 | goto err_free_lkup_exts; | 5423 | goto err_unroll; |
| 5424 | 5424 | ||
| 5425 | /* Group match words into recipes using preferred recipe grouping | 5425 | /* Group match words into recipes using preferred recipe grouping |
| 5426 | * criteria. | 5426 | * criteria. |
| @@ -1688,7 +1688,7 @@ ice_tc_forward_to_queue(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr, · 1687 unmodified lines | |||
| 1688 | struct ice_vsi *ch_vsi = NULL; | 1688 | struct ice_vsi *ch_vsi = NULL; |
| 1689 | u16 queue = act->rx_queue; | 1689 | u16 queue = act->rx_queue; |
| 1690 | 1690 | ||
| 1691 | if (queue > vsi->num_rxq) { | 1691 | if (queue >= vsi->num_rxq) { |
| 1692 | NL_SET_ERR_MSG_MOD(fltr->extack, | 1692 | NL_SET_ERR_MSG_MOD(fltr->extack, |
| 1693 | "Unable to add filter because specified queue is invalid"); | 1693 | "Unable to add filter because specified queue is invalid"); |
| 1694 | return -EINVAL; | 1694 | return -EINVAL; |
| @@ -39,7 +39,7 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, · 38 unmodified lines | |||
| 39 | return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd); | 39 | return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | static const u32 ice_legacy_aq_to_vc_speed[15] = { | 42 | static const u32 ice_legacy_aq_to_vc_speed[] = { |
| 43 | VIRTCHNL_LINK_SPEED_100MB, /* BIT(0) */ | 43 | VIRTCHNL_LINK_SPEED_100MB, /* BIT(0) */ |
| 44 | VIRTCHNL_LINK_SPEED_100MB, | 44 | VIRTCHNL_LINK_SPEED_100MB, |
| 45 | VIRTCHNL_LINK_SPEED_1GB, | 45 | VIRTCHNL_LINK_SPEED_1GB, |
| @@ -51,10 +51,6 @@ static const u32 ice_legacy_aq_to_vc_speed[15] = { · 5 unmodified lines | |||
| 51 | VIRTCHNL_LINK_SPEED_40GB, | 51 | VIRTCHNL_LINK_SPEED_40GB, |
| 52 | VIRTCHNL_LINK_SPEED_40GB, | 52 | VIRTCHNL_LINK_SPEED_40GB, |
| 53 | VIRTCHNL_LINK_SPEED_40GB, | 53 | VIRTCHNL_LINK_SPEED_40GB, |
| 54 | VIRTCHNL_LINK_SPEED_UNKNOWN, | ||
| 55 | VIRTCHNL_LINK_SPEED_UNKNOWN, | ||
| 56 | VIRTCHNL_LINK_SPEED_UNKNOWN, | ||
| 57 | VIRTCHNL_LINK_SPEED_UNKNOWN /* BIT(14) */ | ||
| 58 | }; | 54 | }; |
| 59 | 55 | ||
| 60 | /** | 56 | /** |
| @@ -71,21 +67,20 @@ static const u32 ice_legacy_aq_to_vc_speed[15] = { · 10 unmodified lines | |||
| 71 | */ | 67 | */ |
| 72 | u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed) | 68 | u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed) |
| 73 | { | 69 | { |
| 74 | u32 speed; | 70 | /* convert a BIT() value into an array index */ |
| 71 | u32 index = fls(link_speed) - 1; | ||
| 75 | 72 | ||
| 76 | if (adv_link_support) { | 73 | if (adv_link_support) |
| 77 | /* convert a BIT() value into an array index */ | 74 | return ice_get_link_speed(index); |
| 78 | speed = ice_get_link_speed(fls(link_speed) - 1); | 75 | else if (index < ARRAY_SIZE(ice_legacy_aq_to_vc_speed)) |
| 79 | } else { | ||
| 80 | /* Virtchnl speeds are not defined for every speed supported in | 76 | /* Virtchnl speeds are not defined for every speed supported in |
| 81 | * the hardware. To maintain compatibility with older AVF | 77 | * the hardware. To maintain compatibility with older AVF |
| 82 | * drivers, while reporting the speed the new speed values are | 78 | * drivers, while reporting the speed the new speed values are |
| 83 | * resolved to the closest known virtchnl speeds | 79 | * resolved to the closest known virtchnl speeds |
| 84 | */ | 80 | */ |
| 85 | speed = ice_legacy_aq_to_vc_speed[fls(link_speed) - 1]; | 81 | return ice_legacy_aq_to_vc_speed[index]; |
| 86 | } | ||
| 87 | 82 | ||
| 88 | return speed; | 83 | return VIRTCHNL_LINK_SPEED_UNKNOWN; |
| 89 | } | 84 | } |
| 90 | 85 | ||
| 91 | /* The mailbox overflow detection algorithm helps to check if there | 86 | /* The mailbox overflow detection algorithm helps to check if there |
| @@ -44,13 +44,17 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | /* outer VLAN ops regardless of port VLAN config */ | 45 | /* outer VLAN ops regardless of port VLAN config */ |
| 46 | vlan_ops->add_vlan = ice_vsi_add_vlan; | 46 | vlan_ops->add_vlan = ice_vsi_add_vlan; |
| 47 | vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering; | ||
| 48 | vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; | 47 | vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; |
| 49 | vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; | 48 | vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; |
| 50 | 49 | ||
| 51 | if (ice_vf_is_port_vlan_ena(vf)) { | 50 | if (ice_vf_is_port_vlan_ena(vf)) { |
| 52 | /* setup outer VLAN ops */ | 51 | /* setup outer VLAN ops */ |
| 53 | vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan; | 52 | vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan; |
| 53 | /* all Rx traffic should be in the domain of the | ||
| 54 | * assigned port VLAN, so prevent disabling Rx VLAN | ||
| 55 | * filtering | ||
| 56 | */ | ||
| 57 | vlan_ops->dis_rx_filtering = noop_vlan; | ||
| 54 | vlan_ops->ena_rx_filtering = | 58 | vlan_ops->ena_rx_filtering = |
| 55 | ice_vsi_ena_rx_vlan_filtering; | 59 | ice_vsi_ena_rx_vlan_filtering; |
| 56 | 60 | ||
| @@ -63,6 +67,9 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) · 6 unmodified lines | |||
| 63 | vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; | 67 | vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; |
| 64 | vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; | 68 | vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; |
| 65 | } else { | 69 | } else { |
| 70 | vlan_ops->dis_rx_filtering = | ||
| 71 | ice_vsi_dis_rx_vlan_filtering; | ||
| 72 | |||
| 66 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) | 73 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) |
| 67 | vlan_ops->ena_rx_filtering = noop_vlan; | 74 | vlan_ops->ena_rx_filtering = noop_vlan; |
| 68 | else | 75 | else |
| @@ -96,7 +103,14 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) · 27 unmodified lines | |||
| 96 | vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan; | 103 | vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan; |
| 97 | vlan_ops->ena_rx_filtering = | 104 | vlan_ops->ena_rx_filtering = |
| 98 | ice_vsi_ena_rx_vlan_filtering; | 105 | ice_vsi_ena_rx_vlan_filtering; |
| 106 | /* all Rx traffic should be in the domain of the | ||
| 107 | * assigned port VLAN, so prevent disabling Rx VLAN | ||
| 108 | * filtering | ||
| 109 | */ | ||
| 110 | vlan_ops->dis_rx_filtering = noop_vlan; | ||
| 99 | } else { | 111 | } else { |
| 112 | vlan_ops->dis_rx_filtering = | ||
| 113 | ice_vsi_dis_rx_vlan_filtering; | ||
| 100 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) | 114 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) |
| 101 | vlan_ops->ena_rx_filtering = noop_vlan; | 115 | vlan_ops->ena_rx_filtering = noop_vlan; |
| 102 | else | 116 | else |
| @@ -2942,7 +2942,9 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) · 2941 unmodified lines | |||
| 2942 | if (tx_buffer->next_to_watch && | 2942 | if (tx_buffer->next_to_watch && |
| 2943 | time_after(jiffies, tx_buffer->time_stamp + | 2943 | time_after(jiffies, tx_buffer->time_stamp + |
| 2944 | (adapter->tx_timeout_factor * HZ)) && | 2944 | (adapter->tx_timeout_factor * HZ)) && |
| 2945 | !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF)) { | 2945 | !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) && |
| 2946 | (rd32(IGC_TDH(tx_ring->reg_idx)) != | ||
| 2947 | readl(tx_ring->tail))) { | ||
| 2946 | /* detected Tx unit hang */ | 2948 | /* detected Tx unit hang */ |
| 2947 | netdev_err(tx_ring->netdev, | 2949 | netdev_err(tx_ring->netdev, |
| 2948 | "Detected Tx Unit Hang\n" | 2950 | "Detected Tx Unit Hang\n" |
| @@ -5068,6 +5070,24 @@ static int igc_change_mtu(struct net_device *netdev, int new_mtu) · 2119 unmodified lines | |||
| 5068 | return 0; | 5070 | return 0; |
| 5069 | } | 5071 | } |
| 5070 | 5072 | ||
| 5073 | /** | ||
| 5074 | * igc_tx_timeout - Respond to a Tx Hang | ||
| 5075 | * @netdev: network interface device structure | ||
| 5076 | * @txqueue: queue number that timed out | ||
| 5077 | **/ | ||
| 5078 | static void igc_tx_timeout(struct net_device *netdev, | ||
| 5079 | unsigned int __always_unused txqueue) | ||
| 5080 | { | ||
| 5081 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 5082 | struct igc_hw *hw = &adapter->hw; | ||
| 5083 | |||
| 5084 | /* Do the reset outside of interrupt context */ | ||
| 5085 | adapter->tx_timeout_count++; | ||
| 5086 | schedule_work(&adapter->reset_task); | ||
| 5087 | wr32(IGC_EICS, | ||
| 5088 | (adapter->eims_enable_mask & ~adapter->eims_other)); | ||
| 5089 | } | ||
| 5090 | |||
| 5071 | /** | 5091 | /** |
| 5072 | * igc_get_stats64 - Get System Network Statistics | 5092 | * igc_get_stats64 - Get System Network Statistics |
| 5073 | * @netdev: network interface device structure | 5093 | * @netdev: network interface device structure |
| @@ -5495,7 +5515,7 @@ static void igc_watchdog_task(struct work_struct *work) · 421 unmodified lines | |||
| 5495 | case SPEED_100: | 5515 | case SPEED_100: |
| 5496 | case SPEED_1000: | 5516 | case SPEED_1000: |
| 5497 | case SPEED_2500: | 5517 | case SPEED_2500: |
| 5498 | adapter->tx_timeout_factor = 7; | 5518 | adapter->tx_timeout_factor = 1; |
| 5499 | break; | 5519 | break; |
| 5500 | } | 5520 | } |
| 5501 | 5521 | ||
| @@ -6347,6 +6367,7 @@ static const struct net_device_ops igc_netdev_ops = { · 845 unmodified lines | |||
| 6347 | .ndo_set_rx_mode = igc_set_rx_mode, | 6367 | .ndo_set_rx_mode = igc_set_rx_mode, |
| 6348 | .ndo_set_mac_address = igc_set_mac, | 6368 | .ndo_set_mac_address = igc_set_mac, |
| 6349 | .ndo_change_mtu = igc_change_mtu, | 6369 | .ndo_change_mtu = igc_change_mtu, |
| 6370 | .ndo_tx_timeout = igc_tx_timeout, | ||
| 6350 | .ndo_get_stats64 = igc_get_stats64, | 6371 | .ndo_get_stats64 = igc_get_stats64, |
| 6351 | .ndo_fix_features = igc_fix_features, | 6372 | .ndo_fix_features = igc_fix_features, |
| 6352 | .ndo_set_features = igc_set_features, | 6373 | .ndo_set_features = igc_set_features, |
| @@ -1621,8 +1621,8 @@ static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, · 1620 unmodified lines | |||
| 1621 | if (IS_ERR(pp)) | 1621 | if (IS_ERR(pp)) |
| 1622 | return pp; | 1622 | return pp; |
| 1623 | 1623 | ||
| 1624 | err = __xdp_rxq_info_reg(xdp_q, ð->dummy_dev, eth->rx_napi.napi_id, | 1624 | err = __xdp_rxq_info_reg(xdp_q, ð->dummy_dev, id, |
| 1625 | id, PAGE_SIZE); | 1625 | eth->rx_napi.napi_id, PAGE_SIZE); |
| 1626 | if (err < 0) | 1626 | if (err < 0) |
| 1627 | goto err_free_pp; | 1627 | goto err_free_pp; |
| 1628 | 1628 | ||
| @@ -1921,7 +1921,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, · 292 unmodified lines | |||
| 1921 | 1921 | ||
| 1922 | while (done < budget) { | 1922 | while (done < budget) { |
| 1923 | unsigned int pktlen, *rxdcsum; | 1923 | unsigned int pktlen, *rxdcsum; |
| 1924 | bool has_hwaccel_tag = false; | ||
| 1924 | struct net_device *netdev; | 1925 | struct net_device *netdev; |
| 1926 | u16 vlan_proto, vlan_tci; | ||
| 1925 | dma_addr_t dma_addr; | 1927 | dma_addr_t dma_addr; |
| 1926 | u32 hash, reason; | 1928 | u32 hash, reason; |
| 1927 | int mac = 0; | 1929 | int mac = 0; |
| @@ -2061,27 +2063,29 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, · 133 unmodified lines | |||
| 2061 | 2063 | ||
| 2062 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { | 2064 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { |
| 2063 | if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { | 2065 | if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { |
| 2064 | if (trxd.rxd3 & RX_DMA_VTAG_V2) | 2066 | if (trxd.rxd3 & RX_DMA_VTAG_V2) { |
| 2065 | __vlan_hwaccel_put_tag(skb, | 2067 | vlan_proto = RX_DMA_VPID(trxd.rxd4); |
| 2066 | htons(RX_DMA_VPID(trxd.rxd4)), | 2068 | vlan_tci = RX_DMA_VID(trxd.rxd4); |
| 2067 | RX_DMA_VID(trxd.rxd4)); | 2069 | has_hwaccel_tag = true; |
| 2070 | } | ||
| 2068 | } else if (trxd.rxd2 & RX_DMA_VTAG) { | 2071 | } else if (trxd.rxd2 & RX_DMA_VTAG) { |
| 2069 | __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), | 2072 | vlan_proto = RX_DMA_VPID(trxd.rxd3); |
| 2070 | RX_DMA_VID(trxd.rxd3)); | 2073 | vlan_tci = RX_DMA_VID(trxd.rxd3); |
| 2074 | has_hwaccel_tag = true; | ||
| 2071 | } | 2075 | } |
| 2072 | } | 2076 | } |
| 2073 | 2077 | ||
| 2074 | /* When using VLAN untagging in combination with DSA, the | 2078 | /* When using VLAN untagging in combination with DSA, the |
| 2075 | * hardware treats the MTK special tag as a VLAN and untags it. | 2079 | * hardware treats the MTK special tag as a VLAN and untags it. |
| 2076 | */ | 2080 | */ |
| 2077 | if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { | 2081 | if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { |
| 2078 | unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); | 2082 | unsigned int port = vlan_proto & GENMASK(2, 0); |
| 2079 | 2083 | ||
| 2080 | if (port < ARRAY_SIZE(eth->dsa_meta) && | 2084 | if (port < ARRAY_SIZE(eth->dsa_meta) && |
| 2081 | eth->dsa_meta[port]) | 2085 | eth->dsa_meta[port]) |
| 2082 | skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); | 2086 | skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); |
| 2083 | 2087 | } else if (has_hwaccel_tag) { | |
| 2084 | __vlan_hwaccel_clear_tag(skb); | 2088 | __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); |
| 2085 | } | 2089 | } |
| 2086 | 2090 | ||
| 2087 | skb_record_rx_queue(skb, 0); | 2091 | skb_record_rx_queue(skb, 0); |
| @@ -3177,7 +3181,7 @@ static void mtk_gdm_config(struct mtk_eth *eth, u32 config) · 1089 unmodified lines | |||
| 3177 | 3181 | ||
| 3178 | val |= config; | 3182 | val |= config; |
| 3179 | 3183 | ||
| 3180 | if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) | 3184 | if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) |
| 3181 | val |= MTK_GDMA_SPECIAL_TAG; | 3185 | val |= MTK_GDMA_SPECIAL_TAG; |
| 3182 | 3186 | ||
| 3183 | mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); | 3187 | mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); |
| @@ -3243,8 +3247,7 @@ static int mtk_open(struct net_device *dev) · 59 unmodified lines | |||
| 3243 | struct mtk_eth *eth = mac->hw; | 3247 | struct mtk_eth *eth = mac->hw; |
| 3244 | int i, err; | 3248 | int i, err; |
| 3245 | 3249 | ||
| 3246 | if ((mtk_uses_dsa(dev) && !eth->prog) && | 3250 | if (mtk_uses_dsa(dev) && !eth->prog) { |
| 3247 | !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { | ||
| 3248 | for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { | 3251 | for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { |
| 3249 | struct metadata_dst *md_dst = eth->dsa_meta[i]; | 3252 | struct metadata_dst *md_dst = eth->dsa_meta[i]; |
| 3250 | 3253 | ||
| @@ -3261,8 +3264,7 @@ static int mtk_open(struct net_device *dev) · 10 unmodified lines | |||
| 3261 | } | 3264 | } |
| 3262 | } else { | 3265 | } else { |
| 3263 | /* Hardware special tag parsing needs to be disabled if at least | 3266 | /* Hardware special tag parsing needs to be disabled if at least |
| 3264 | * one MAC does not use DSA, or the second MAC of the MT7621 and | 3267 | * one MAC does not use DSA. |
| 3265 | * MT7623 SoCs is being used. | ||
| 3266 | */ | 3268 | */ |
| 3267 | u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); | 3269 | u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); |
| 3268 | val &= ~MTK_CDMP_STAG_EN; | 3270 | val &= ~MTK_CDMP_STAG_EN; |
| @@ -245,8 +245,9 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev) · 244 unmodified lines | |||
| 245 | pages = dev->priv.dbg.pages_debugfs; | 245 | pages = dev->priv.dbg.pages_debugfs; |
| 246 | 246 | ||
| 247 | debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages); | 247 | debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages); |
| 248 | debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.vfs_pages); | 248 | debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]); |
| 249 | debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.host_pf_pages); | 249 | debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]); |
| 250 | debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]); | ||
| 250 | debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); | 251 | debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); |
| 251 | debugfs_create_u32("fw_pages_give_dropped", 0400, pages, &dev->priv.give_pages_dropped); | 252 | debugfs_create_u32("fw_pages_give_dropped", 0400, pages, &dev->priv.give_pages_dropped); |
| 252 | debugfs_create_u32("fw_pages_reclaim_discard", 0400, pages, | 253 | debugfs_create_u32("fw_pages_reclaim_discard", 0400, pages, |
| @@ -64,6 +64,7 @@ static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) · 63 unmodified lines | |||
| 64 | MLX5_GET(mtrc_cap, out, num_string_trace); | 64 | MLX5_GET(mtrc_cap, out, num_string_trace); |
| 65 | tracer->str_db.num_string_db = MLX5_GET(mtrc_cap, out, num_string_db); | 65 | tracer->str_db.num_string_db = MLX5_GET(mtrc_cap, out, num_string_db); |
| 66 | tracer->owner = !!MLX5_GET(mtrc_cap, out, trace_owner); | 66 | tracer->owner = !!MLX5_GET(mtrc_cap, out, trace_owner); |
| 67 | tracer->str_db.loaded = false; | ||
| 67 | 68 | ||
| 68 | for (i = 0; i < tracer->str_db.num_string_db; i++) { | 69 | for (i = 0; i < tracer->str_db.num_string_db; i++) { |
| 69 | mtrc_cap_sp = MLX5_ADDR_OF(mtrc_cap, out, string_db_param[i]); | 70 | mtrc_cap_sp = MLX5_ADDR_OF(mtrc_cap, out, string_db_param[i]); |
| @@ -783,6 +784,7 @@ static int mlx5_fw_tracer_set_mtrc_conf(struct mlx5_fw_tracer *tracer) · 713 unmodified lines | |||
| 783 | if (err) | 784 | if (err) |
| 784 | mlx5_core_warn(dev, "FWTracer: Failed to set tracer configurations %d\n", err); | 785 | mlx5_core_warn(dev, "FWTracer: Failed to set tracer configurations %d\n", err); |
| 785 | 786 | ||
| 787 | tracer->buff.consumer_index = 0; | ||
| 786 | return err; | 788 | return err; |
| 787 | } | 789 | } |
| 788 | 790 | ||
| @@ -847,7 +849,6 @@ static void mlx5_fw_tracer_ownership_change(struct work_struct *work) · 58 unmodified lines | |||
| 847 | mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); | 849 | mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); |
| 848 | if (tracer->owner) { | 850 | if (tracer->owner) { |
| 849 | tracer->owner = false; | 851 | tracer->owner = false; |
| 850 | tracer->buff.consumer_index = 0; | ||
| 851 | return; | 852 | return; |
| 852 | } | 853 | } |
| 853 | 854 | ||
| @@ -95,7 +95,7 @@ void mlx5_ec_cleanup(struct mlx5_core_dev *dev) · 94 unmodified lines | |||
| 95 | 95 | ||
| 96 | mlx5_host_pf_cleanup(dev); | 96 | mlx5_host_pf_cleanup(dev); |
| 97 | 97 | ||
| 98 | err = mlx5_wait_for_pages(dev, &dev->priv.host_pf_pages); | 98 | err = mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_HOST_PF]); |
| 99 | if (err) | 99 | if (err) |
| 100 | mlx5_core_warn(dev, "Timeout reclaiming external host PF pages err(%d)\n", err); | 100 | mlx5_core_warn(dev, "Timeout reclaiming external host PF pages err(%d)\n", err); |
| 101 | } | 101 | } |
| @@ -438,10 +438,6 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, · 437 unmodified lines | |||
| 438 | 438 | ||
| 439 | switch (event) { | 439 | switch (event) { |
| 440 | case SWITCHDEV_FDB_ADD_TO_BRIDGE: | 440 | case SWITCHDEV_FDB_ADD_TO_BRIDGE: |
| 441 | /* only handle the event on native eswtich of representor */ | ||
| 442 | if (!mlx5_esw_bridge_is_local(dev, rep, esw)) | ||
| 443 | break; | ||
| 444 | |||
| 445 | fdb_info = container_of(info, | 441 | fdb_info = container_of(info, |
| 446 | struct switchdev_notifier_fdb_info, | 442 | struct switchdev_notifier_fdb_info, |
| 447 | info); | 443 | info); |
| @@ -450,7 +450,7 @@ void mlx5e_enable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc) · 449 unmodified lines | |||
| 450 | 450 | ||
| 451 | void mlx5e_disable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc) | 451 | void mlx5e_disable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc) |
| 452 | { | 452 | { |
| 453 | if (fs->vlan->cvlan_filter_disabled) | 453 | if (!fs->vlan || fs->vlan->cvlan_filter_disabled) |
| 454 | return; | 454 | return; |
| 455 | 455 | ||
| 456 | fs->vlan->cvlan_filter_disabled = true; | 456 | fs->vlan->cvlan_filter_disabled = true; |
| @@ -597,7 +597,8 @@ static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param · 596 unmodified lines | |||
| 597 | rq->ix = c->ix; | 597 | rq->ix = c->ix; |
| 598 | rq->channel = c; | 598 | rq->channel = c; |
| 599 | rq->mdev = mdev; | 599 | rq->mdev = mdev; |
| 600 | rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); | 600 | rq->hw_mtu = |
| 601 | MLX5E_SW2HW_MTU(params, params->sw_mtu) - ETH_FCS_LEN * !params->scatter_fcs_en; | ||
| 601 | rq->xdpsq = &c->rq_xdpsq; | 602 | rq->xdpsq = &c->rq_xdpsq; |
| 602 | rq->stats = &c->priv->channel_stats[c->ix]->rq; | 603 | rq->stats = &c->priv->channel_stats[c->ix]->rq; |
| 603 | rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev); | 604 | rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev); |
| @@ -1020,35 +1021,6 @@ int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state) · 416 unmodified lines | |||
| 1020 | return mlx5e_rq_to_ready(rq, curr_state); | 1021 | return mlx5e_rq_to_ready(rq, curr_state); |
| 1021 | } | 1022 | } |
| 1022 | 1023 | ||
| 1023 | static int mlx5e_modify_rq_scatter_fcs(struct mlx5e_rq *rq, bool enable) | ||
| 1024 | { | ||
| 1025 | struct mlx5_core_dev *mdev = rq->mdev; | ||
| 1026 | |||
| 1027 | void *in; | ||
| 1028 | void *rqc; | ||
| 1029 | int inlen; | ||
| 1030 | int err; | ||
| 1031 | |||
| 1032 | inlen = MLX5_ST_SZ_BYTES(modify_rq_in); | ||
| 1033 | in = kvzalloc(inlen, GFP_KERNEL); | ||
| 1034 | if (!in) | ||
| 1035 | return -ENOMEM; | ||
| 1036 | |||
| 1037 | rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx); | ||
| 1038 | |||
| 1039 | MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY); | ||
| 1040 | MLX5_SET64(modify_rq_in, in, modify_bitmask, | ||
| 1041 | MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_SCATTER_FCS); | ||
| 1042 | MLX5_SET(rqc, rqc, scatter_fcs, enable); | ||
| 1043 | MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY); | ||
| 1044 | |||
| 1045 | err = mlx5_core_modify_rq(mdev, rq->rqn, in); | ||
| 1046 | |||
| 1047 | kvfree(in); | ||
| 1048 | |||
| 1049 | return err; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) | 1024 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) |
| 1053 | { | 1025 | { |
| 1054 | struct mlx5_core_dev *mdev = rq->mdev; | 1026 | struct mlx5_core_dev *mdev = rq->mdev; |
| @@ -3328,20 +3300,6 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) · 2273 unmodified lines | |||
| 3328 | mlx5e_destroy_tises(priv); | 3300 | mlx5e_destroy_tises(priv); |
| 3329 | } | 3301 | } |
| 3330 | 3302 | ||
| 3331 | static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool enable) | ||
| 3332 | { | ||
| 3333 | int err = 0; | ||
| 3334 | int i; | ||
| 3335 | |||
| 3336 | for (i = 0; i < chs->num; i++) { | ||
| 3337 | err = mlx5e_modify_rq_scatter_fcs(&chs->c[i]->rq, enable); | ||
| 3338 | if (err) | ||
| 3339 | return err; | ||
| 3340 | } | ||
| 3341 | |||
| 3342 | return 0; | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd) | 3303 | static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd) |
| 3346 | { | 3304 | { |
| 3347 | int err; | 3305 | int err; |
| @@ -3917,41 +3875,27 @@ static int mlx5e_set_rx_port_ts(struct mlx5_core_dev *mdev, bool enable) · 569 unmodified lines | |||
| 3917 | return mlx5_set_ports_check(mdev, in, sizeof(in)); | 3875 | return mlx5_set_ports_check(mdev, in, sizeof(in)); |
| 3918 | } | 3876 | } |
| 3919 | 3877 | ||
| 3878 | static int mlx5e_set_rx_port_ts_wrap(struct mlx5e_priv *priv, void *ctx) | ||
| 3879 | { | ||
| 3880 | struct mlx5_core_dev *mdev = priv->mdev; | ||
| 3881 | bool enable = *(bool *)ctx; | ||
| 3882 | |||
| 3883 | return mlx5e_set_rx_port_ts(mdev, enable); | ||
| 3884 | } | ||
| 3885 | |||
| 3920 | static int set_feature_rx_fcs(struct net_device *netdev, bool enable) | 3886 | static int set_feature_rx_fcs(struct net_device *netdev, bool enable) |
| 3921 | { | 3887 | { |
| 3922 | struct mlx5e_priv *priv = netdev_priv(netdev); | 3888 | struct mlx5e_priv *priv = netdev_priv(netdev); |
| 3923 | struct mlx5e_channels *chs = &priv->channels; | 3889 | struct mlx5e_channels *chs = &priv->channels; |
| 3924 | struct mlx5_core_dev *mdev = priv->mdev; | 3890 | struct mlx5e_params new_params; |
| 3925 | int err; | 3891 | int err; |
| 3926 | 3892 | ||
| 3927 | mutex_lock(&priv->state_lock); | 3893 | mutex_lock(&priv->state_lock); |
| 3928 | 3894 | ||
| 3929 | if (enable) { | 3895 | new_params = chs->params; |
| 3930 | err = mlx5e_set_rx_port_ts(mdev, false); | 3896 | new_params.scatter_fcs_en = enable; |
| 3931 | if (err) | 3897 | err = mlx5e_safe_switch_params(priv, &new_params, mlx5e_set_rx_port_ts_wrap, |
| 3932 | goto out; | 3898 | &new_params.scatter_fcs_en, true); |
| 3933 | |||
| 3934 | chs->params.scatter_fcs_en = true; | ||
| 3935 | err = mlx5e_modify_channels_scatter_fcs(chs, true); | ||
| 3936 | if (err) { | ||
| 3937 | chs->params.scatter_fcs_en = false; | ||
| 3938 | mlx5e_set_rx_port_ts(mdev, true); | ||
| 3939 | } | ||
| 3940 | } else { | ||
| 3941 | chs->params.scatter_fcs_en = false; | ||
| 3942 | err = mlx5e_modify_channels_scatter_fcs(chs, false); | ||
| 3943 | if (err) { | ||
| 3944 | chs->params.scatter_fcs_en = true; | ||
| 3945 | goto out; | ||
| 3946 | } | ||
| 3947 | err = mlx5e_set_rx_port_ts(mdev, true); | ||
| 3948 | if (err) { | ||
| 3949 | mlx5_core_warn(mdev, "Failed to set RX port timestamp %d\n", err); | ||
| 3950 | err = 0; | ||
| 3951 | } | ||
| 3952 | } | ||
| 3953 | |||
| 3954 | out: | ||
| 3955 | mutex_unlock(&priv->state_lock); | 3899 | mutex_unlock(&priv->state_lock); |
| 3956 | return err; | 3900 | return err; |
| 3957 | } | 3901 | } |
| @@ -4088,6 +4032,10 @@ static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev · 130 unmodified lines | |||
| 4088 | if (netdev->features & NETIF_F_GRO_HW) | 4032 | if (netdev->features & NETIF_F_GRO_HW) |
| 4089 | netdev_warn(netdev, "Disabling HW_GRO, not supported in switchdev mode\n"); | 4033 | netdev_warn(netdev, "Disabling HW_GRO, not supported in switchdev mode\n"); |
| 4090 | 4034 | ||
| 4035 | features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; | ||
| 4036 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | ||
| 4037 | netdev_warn(netdev, "Disabling HW_VLAN CTAG FILTERING, not supported in switchdev mode\n"); | ||
| 4038 | |||
| 4091 | return features; | 4039 | return features; |
| 4092 | } | 4040 | } |
| 4093 | 4041 | ||
| @@ -1715,7 +1715,7 @@ void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 · 1714 unmodified lines | |||
| 1715 | struct mlx5_esw_bridge *bridge; | 1715 | struct mlx5_esw_bridge *bridge; |
| 1716 | 1716 | ||
| 1717 | port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); | 1717 | port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); |
| 1718 | if (!port || port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER) | 1718 | if (!port) |
| 1719 | return; | 1719 | return; |
| 1720 | 1720 | ||
| 1721 | bridge = port->bridge; | 1721 | bridge = port->bridge; |
| @@ -191,16 +191,16 @@ static inline int mlx5_ptys_rate_enum_to_int(enum mlx5_ptys_rate rate) · 190 unmodified lines | |||
| 191 | } | 191 | } |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | static int mlx5i_get_speed_settings(u16 ib_link_width_oper, u16 ib_proto_oper) | 194 | static u32 mlx5i_get_speed_settings(u16 ib_link_width_oper, u16 ib_proto_oper) |
| 195 | { | 195 | { |
| 196 | int rate, width; | 196 | int rate, width; |
| 197 | 197 | ||
| 198 | rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper); | 198 | rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper); |
| 199 | if (rate < 0) | 199 | if (rate < 0) |
| 200 | return -EINVAL; | 200 | return SPEED_UNKNOWN; |
| 201 | width = mlx5_ptys_width_enum_to_int(ib_link_width_oper); | 201 | width = mlx5_ptys_width_enum_to_int(ib_link_width_oper); |
| 202 | if (width < 0) | 202 | if (width < 0) |
| 203 | return -EINVAL; | 203 | return SPEED_UNKNOWN; |
| 204 | 204 | ||
| 205 | return rate * width; | 205 | return rate * width; |
| 206 | } | 206 | } |
| @@ -223,16 +223,13 @@ static int mlx5i_get_link_ksettings(struct net_device *netdev, · 16 unmodified lines | |||
| 223 | ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); | 223 | ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); |
| 224 | 224 | ||
| 225 | speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper); | 225 | speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper); |
| 226 | if (speed < 0) | 226 | link_ksettings->base.speed = speed; |
| 227 | return -EINVAL; | 227 | link_ksettings->base.duplex = speed == SPEED_UNKNOWN ? DUPLEX_UNKNOWN : DUPLEX_FULL; |
| 228 | 228 | ||
| 229 | link_ksettings->base.duplex = DUPLEX_FULL; | ||
| 230 | link_ksettings->base.port = PORT_OTHER; | 229 | link_ksettings->base.port = PORT_OTHER; |
| 231 | 230 | ||
| 232 | link_ksettings->base.autoneg = AUTONEG_DISABLE; | 231 | link_ksettings->base.autoneg = AUTONEG_DISABLE; |
| 233 | 232 | ||
| 234 | link_ksettings->base.speed = speed; | ||
| 235 | |||
| 236 | return 0; | 233 | return 0; |
| 237 | } | 234 | } |
| 238 | 235 | ||
| @@ -2131,7 +2131,7 @@ static int __init mlx5_init(void) · 2130 unmodified lines | |||
| 2131 | mlx5_core_verify_params(); | 2131 | mlx5_core_verify_params(); |
| 2132 | mlx5_register_debugfs(); | 2132 | mlx5_register_debugfs(); |
| 2133 | 2133 | ||
| 2134 | err = pci_register_driver(&mlx5_core_driver); | 2134 | err = mlx5e_init(); |
| 2135 | if (err) | 2135 | if (err) |
| 2136 | goto err_debug; | 2136 | goto err_debug; |
| 2137 | 2137 | ||
| @@ -2139,16 +2139,16 @@ static int __init mlx5_init(void) · 1 unmodified line | |||
| 2139 | if (err) | 2139 | if (err) |
| 2140 | goto err_sf; | 2140 | goto err_sf; |
| 2141 | 2141 | ||
| 2142 | err = mlx5e_init(); | 2142 | err = pci_register_driver(&mlx5_core_driver); |
| 2143 | if (err) | 2143 | if (err) |
| 2144 | goto err_en; | 2144 | goto err_pci; |
| 2145 | 2145 | ||
| 2146 | return 0; | 2146 | return 0; |
| 2147 | 2147 | ||
| 2148 | err_en: | 2148 | err_pci: |
| 2149 | mlx5_sf_driver_unregister(); | 2149 | mlx5_sf_driver_unregister(); |
| 2150 | err_sf: | 2150 | err_sf: |
| 2151 | pci_unregister_driver(&mlx5_core_driver); | 2151 | mlx5e_cleanup(); |
| 2152 | err_debug: | 2152 | err_debug: |
| 2153 | mlx5_unregister_debugfs(); | 2153 | mlx5_unregister_debugfs(); |
| 2154 | return err; | 2154 | return err; |
| @@ -2156,9 +2156,9 @@ err_debug: · 1 unmodified line | |||
| 2156 | 2156 | ||
| 2157 | static void __exit mlx5_cleanup(void) | 2157 | static void __exit mlx5_cleanup(void) |
| 2158 | { | 2158 | { |
| 2159 | mlx5e_cleanup(); | ||
| 2160 | mlx5_sf_driver_unregister(); | ||
| 2161 | pci_unregister_driver(&mlx5_core_driver); | 2159 | pci_unregister_driver(&mlx5_core_driver); |
| 2160 | mlx5_sf_driver_unregister(); | ||
| 2161 | mlx5e_cleanup(); | ||
| 2162 | mlx5_unregister_debugfs(); | 2162 | mlx5_unregister_debugfs(); |
| 2163 | } | 2163 | } |
| 2164 | 2164 | ||
| @@ -74,6 +74,14 @@ static u32 get_function(u16 func_id, bool ec_function) · 73 unmodified lines | |||
| 74 | return (u32)func_id | (ec_function << 16); | 74 | return (u32)func_id | (ec_function << 16); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_function) | ||
| 78 | { | ||
| 79 | if (!func_id) | ||
| 80 | return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF; | ||
| 81 | |||
| 82 | return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF; | ||
| 83 | } | ||
| 84 | |||
| 77 | static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function) | 85 | static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function) |
| 78 | { | 86 | { |
| 79 | struct rb_root *root; | 87 | struct rb_root *root; |
| @@ -333,6 +341,7 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, · 253 unmodified lines | |||
| 333 | u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0}; | 341 | u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0}; |
| 334 | int inlen = MLX5_ST_SZ_BYTES(manage_pages_in); | 342 | int inlen = MLX5_ST_SZ_BYTES(manage_pages_in); |
| 335 | int notify_fail = event; | 343 | int notify_fail = event; |
| 344 | u16 func_type; | ||
| 336 | u64 addr; | 345 | u64 addr; |
| 337 | int err; | 346 | int err; |
| 338 | u32 *in; | 347 | u32 *in; |
| @@ -384,11 +393,9 @@ retry: · 45 unmodified lines | |||
| 384 | goto out_dropped; | 393 | goto out_dropped; |
| 385 | } | 394 | } |
| 386 | 395 | ||
| 396 | func_type = func_id_to_type(dev, func_id, ec_function); | ||
| 397 | dev->priv.page_counters[func_type] += npages; | ||
| 387 | dev->priv.fw_pages += npages; | 398 | dev->priv.fw_pages += npages; |
| 388 | if (func_id) | ||
| 389 | dev->priv.vfs_pages += npages; | ||
| 390 | else if (mlx5_core_is_ecpf(dev) && !ec_function) | ||
| 391 | dev->priv.host_pf_pages += npages; | ||
| 392 | 399 | ||
| 393 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n", | 400 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n", |
| 394 | npages, ec_function, func_id, err); | 401 | npages, ec_function, func_id, err); |
| @@ -415,6 +422,7 @@ static void release_all_pages(struct mlx5_core_dev *dev, u16 func_id, · 20 unmodified lines | |||
| 415 | struct rb_root *root; | 422 | struct rb_root *root; |
| 416 | struct rb_node *p; | 423 | struct rb_node *p; |
| 417 | int npages = 0; | 424 | int npages = 0; |
| 425 | u16 func_type; | ||
| 418 | 426 | ||
| 419 | root = xa_load(&dev->priv.page_root_xa, function); | 427 | root = xa_load(&dev->priv.page_root_xa, function); |
| 420 | if (WARN_ON_ONCE(!root)) | 428 | if (WARN_ON_ONCE(!root)) |
| @@ -429,11 +437,9 @@ static void release_all_pages(struct mlx5_core_dev *dev, u16 func_id, · 8 unmodified lines | |||
| 429 | free_fwp(dev, fwp, fwp->free_count); | 437 | free_fwp(dev, fwp, fwp->free_count); |
| 430 | } | 438 | } |
| 431 | 439 | ||
| 440 | func_type = func_id_to_type(dev, func_id, ec_function); | ||
| 441 | dev->priv.page_counters[func_type] -= npages; | ||
| 432 | dev->priv.fw_pages -= npages; | 442 | dev->priv.fw_pages -= npages; |
| 433 | if (func_id) | ||
| 434 | dev->priv.vfs_pages -= npages; | ||
| 435 | else if (mlx5_core_is_ecpf(dev) && !ec_function) | ||
| 436 | dev->priv.host_pf_pages -= npages; | ||
| 437 | 443 | ||
| 438 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x\n", | 444 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x\n", |
| 439 | npages, ec_function, func_id); | 445 | npages, ec_function, func_id); |
| @@ -499,6 +505,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, · 59 unmodified lines | |||
| 499 | int outlen = MLX5_ST_SZ_BYTES(manage_pages_out); | 505 | int outlen = MLX5_ST_SZ_BYTES(manage_pages_out); |
| 500 | u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {}; | 506 | u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {}; |
| 501 | int num_claimed; | 507 | int num_claimed; |
| 508 | u16 func_type; | ||
| 502 | u32 *out; | 509 | u32 *out; |
| 503 | int err; | 510 | int err; |
| 504 | int i; | 511 | int i; |
| @@ -550,11 +557,9 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, · 45 unmodified lines | |||
| 550 | if (nclaimed) | 557 | if (nclaimed) |
| 551 | *nclaimed = num_claimed; | 558 | *nclaimed = num_claimed; |
| 552 | 559 | ||
| 560 | func_type = func_id_to_type(dev, func_id, ec_function); | ||
| 561 | dev->priv.page_counters[func_type] -= num_claimed; | ||
| 553 | dev->priv.fw_pages -= num_claimed; | 562 | dev->priv.fw_pages -= num_claimed; |
| 554 | if (func_id) | ||
| 555 | dev->priv.vfs_pages -= num_claimed; | ||
| 556 | else if (mlx5_core_is_ecpf(dev) && !ec_function) | ||
| 557 | dev->priv.host_pf_pages -= num_claimed; | ||
| 558 | 563 | ||
| 559 | out_free: | 564 | out_free: |
| 560 | kvfree(out); | 565 | kvfree(out); |
| @@ -707,12 +712,12 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) · 146 unmodified lines | |||
| 707 | WARN(dev->priv.fw_pages, | 712 | WARN(dev->priv.fw_pages, |
| 708 | "FW pages counter is %d after reclaiming all pages\n", | 713 | "FW pages counter is %d after reclaiming all pages\n", |
| 709 | dev->priv.fw_pages); | 714 | dev->priv.fw_pages); |
| 710 | WARN(dev->priv.vfs_pages, | 715 | WARN(dev->priv.page_counters[MLX5_VF], |
| 711 | "VFs FW pages counter is %d after reclaiming all pages\n", | 716 | "VFs FW pages counter is %d after reclaiming all pages\n", |
| 712 | dev->priv.vfs_pages); | 717 | dev->priv.page_counters[MLX5_VF]); |
| 713 | WARN(dev->priv.host_pf_pages, | 718 | WARN(dev->priv.page_counters[MLX5_HOST_PF], |
| 714 | "External host PF FW pages counter is %d after reclaiming all pages\n", | 719 | "External host PF FW pages counter is %d after reclaiming all pages\n", |
| 715 | dev->priv.host_pf_pages); | 720 | dev->priv.page_counters[MLX5_HOST_PF]); |
| 716 | 721 | ||
| 717 | return 0; | 722 | return 0; |
| 718 | } | 723 | } |
| @@ -147,7 +147,7 @@ mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf) · 146 unmodified lines | |||
| 147 | 147 | ||
| 148 | mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf); | 148 | mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf); |
| 149 | 149 | ||
| 150 | if (mlx5_wait_for_pages(dev, &dev->priv.vfs_pages)) | 150 | if (mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF])) |
| 151 | mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); | 151 | mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| @@ -1138,12 +1138,14 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule, · 1137 unmodified lines | |||
| 1138 | rule->flow_source)) | 1138 | rule->flow_source)) |
| 1139 | return 0; | 1139 | return 0; |
| 1140 | 1140 | ||
| 1141 | mlx5dr_domain_nic_lock(nic_dmn); | ||
| 1142 | |||
| 1141 | ret = mlx5dr_matcher_select_builders(matcher, | 1143 | ret = mlx5dr_matcher_select_builders(matcher, |
| 1142 | nic_matcher, | 1144 | nic_matcher, |
| 1143 | dr_rule_get_ipv(¶m->outer), | 1145 | dr_rule_get_ipv(¶m->outer), |
| 1144 | dr_rule_get_ipv(¶m->inner)); | 1146 | dr_rule_get_ipv(¶m->inner)); |
| 1145 | if (ret) | 1147 | if (ret) |
| 1146 | return ret; | 1148 | goto err_unlock; |
| 1147 | 1149 | ||
| 1148 | hw_ste_arr_is_opt = nic_matcher->num_of_builders <= DR_RULE_MAX_STES_OPTIMIZED; | 1150 | hw_ste_arr_is_opt = nic_matcher->num_of_builders <= DR_RULE_MAX_STES_OPTIMIZED; |
| 1149 | if (likely(hw_ste_arr_is_opt)) { | 1151 | if (likely(hw_ste_arr_is_opt)) { |
| @@ -1152,12 +1154,12 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule, · 2 unmodified lines | |||
| 1152 | hw_ste_arr = kzalloc((nic_matcher->num_of_builders + DR_ACTION_MAX_STES) * | 1154 | hw_ste_arr = kzalloc((nic_matcher->num_of_builders + DR_ACTION_MAX_STES) * |
| 1153 | DR_STE_SIZE, GFP_KERNEL); | 1155 | DR_STE_SIZE, GFP_KERNEL); |
| 1154 | 1156 | ||
| 1155 | if (!hw_ste_arr) | 1157 | if (!hw_ste_arr) { |
| 1156 | return -ENOMEM; | 1158 | ret = -ENOMEM; |
| 1159 | goto err_unlock; | ||
| 1160 | } | ||
| 1157 | } | 1161 | } |
| 1158 | 1162 | ||
| 1159 | mlx5dr_domain_nic_lock(nic_dmn); | ||
| 1160 | |||
| 1161 | ret = mlx5dr_matcher_add_to_tbl_nic(dmn, nic_matcher); | 1163 | ret = mlx5dr_matcher_add_to_tbl_nic(dmn, nic_matcher); |
| 1162 | if (ret) | 1164 | if (ret) |
| 1163 | goto free_hw_ste; | 1165 | goto free_hw_ste; |
| @@ -1223,7 +1225,10 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule, · 59 unmodified lines | |||
| 1223 | 1225 | ||
| 1224 | mlx5dr_domain_nic_unlock(nic_dmn); | 1226 | mlx5dr_domain_nic_unlock(nic_dmn); |
| 1225 | 1227 | ||
| 1226 | goto out; | 1228 | if (unlikely(!hw_ste_arr_is_opt)) |
| 1229 | kfree(hw_ste_arr); | ||
| 1230 | |||
| 1231 | return 0; | ||
| 1227 | 1232 | ||
| 1228 | free_rule: | 1233 | free_rule: |
| 1229 | dr_rule_clean_rule_members(rule, nic_rule); | 1234 | dr_rule_clean_rule_members(rule, nic_rule); |
| @@ -1238,12 +1243,12 @@ remove_from_nic_tbl: · 8 unmodified lines | |||
| 1238 | mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher); | 1243 | mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher); |
| 1239 | 1244 | ||
| 1240 | free_hw_ste: | 1245 | free_hw_ste: |
| 1241 | mlx5dr_domain_nic_unlock(nic_dmn); | 1246 | if (!hw_ste_arr_is_opt) |
| 1242 | |||
| 1243 | out: | ||
| 1244 | if (unlikely(!hw_ste_arr_is_opt)) | ||
| 1245 | kfree(hw_ste_arr); | 1247 | kfree(hw_ste_arr); |
| 1246 | 1248 | ||
| 1249 | err_unlock: | ||
| 1250 | mlx5dr_domain_nic_unlock(nic_dmn); | ||
| 1251 | |||
| 1247 | return ret; | 1252 | return ret; |
| 1248 | } | 1253 | } |
| 1249 | 1254 | ||
| @@ -632,7 +632,7 @@ int sparx5_ptp_init(struct sparx5 *sparx5) · 631 unmodified lines | |||
| 632 | /* Enable master counters */ | 632 | /* Enable master counters */ |
| 633 | spx5_wr(PTP_PTP_DOM_CFG_PTP_ENA_SET(0x7), sparx5, PTP_PTP_DOM_CFG); | 633 | spx5_wr(PTP_PTP_DOM_CFG_PTP_ENA_SET(0x7), sparx5, PTP_PTP_DOM_CFG); |
| 634 | 634 | ||
| 635 | for (i = 0; i < sparx5->port_count; i++) { | 635 | for (i = 0; i < SPX5_PORTS; i++) { |
| 636 | port = sparx5->ports[i]; | 636 | port = sparx5->ports[i]; |
| 637 | if (!port) | 637 | if (!port) |
| 638 | continue; | 638 | continue; |
| @@ -648,7 +648,7 @@ void sparx5_ptp_deinit(struct sparx5 *sparx5) · 9 unmodified lines | |||
| 648 | struct sparx5_port *port; | 648 | struct sparx5_port *port; |
| 649 | int i; | 649 | int i; |
| 650 | 650 | ||
| 651 | for (i = 0; i < sparx5->port_count; i++) { | 651 | for (i = 0; i < SPX5_PORTS; i++) { |
| 652 | port = sparx5->ports[i]; | 652 | port = sparx5->ports[i]; |
| 653 | if (!port) | 653 | if (!port) |
| 654 | continue; | 654 | continue; |
| @@ -1217,9 +1217,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 1216 unmodified lines | |||
| 1217 | unsigned int max_queues_per_port = num_online_cpus(); | 1217 | unsigned int max_queues_per_port = num_online_cpus(); |
| 1218 | struct gdma_context *gc = pci_get_drvdata(pdev); | 1218 | struct gdma_context *gc = pci_get_drvdata(pdev); |
| 1219 | struct gdma_irq_context *gic; | 1219 | struct gdma_irq_context *gic; |
| 1220 | unsigned int max_irqs; | 1220 | unsigned int max_irqs, cpu; |
| 1221 | u16 *cpus; | ||
| 1222 | cpumask_var_t req_mask; | ||
| 1223 | int nvec, irq; | 1221 | int nvec, irq; |
| 1224 | int err, i = 0, j; | 1222 | int err, i = 0, j; |
| 1225 | 1223 | ||
| @@ -1240,21 +1238,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 14 unmodified lines | |||
| 1240 | goto free_irq_vector; | 1238 | goto free_irq_vector; |
| 1241 | } | 1239 | } |
| 1242 | 1240 | ||
| 1243 | if (!zalloc_cpumask_var(&req_mask, GFP_KERNEL)) { | ||
| 1244 | err = -ENOMEM; | ||
| 1245 | goto free_irq; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | cpus = kcalloc(nvec, sizeof(*cpus), GFP_KERNEL); | ||
| 1249 | if (!cpus) { | ||
| 1250 | err = -ENOMEM; | ||
| 1251 | goto free_mask; | ||
| 1252 | } | ||
| 1253 | for (i = 0; i < nvec; i++) | ||
| 1254 | cpus[i] = cpumask_local_spread(i, gc->numa_node); | ||
| 1255 | |||
| 1256 | for (i = 0; i < nvec; i++) { | 1241 | for (i = 0; i < nvec; i++) { |
| 1257 | cpumask_set_cpu(cpus[i], req_mask); | ||
| 1258 | gic = &gc->irq_contexts[i]; | 1242 | gic = &gc->irq_contexts[i]; |
| 1259 | gic->handler = NULL; | 1243 | gic->handler = NULL; |
| 1260 | gic->arg = NULL; | 1244 | gic->arg = NULL; |
| @@ -1269,17 +1253,16 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 8 unmodified lines | |||
| 1269 | irq = pci_irq_vector(pdev, i); | 1253 | irq = pci_irq_vector(pdev, i); |
| 1270 | if (irq < 0) { | 1254 | if (irq < 0) { |
| 1271 | err = irq; | 1255 | err = irq; |
| 1272 | goto free_mask; | 1256 | goto free_irq; |
| 1273 | } | 1257 | } |
| 1274 | 1258 | ||
| 1275 | err = request_irq(irq, mana_gd_intr, 0, gic->name, gic); | 1259 | err = request_irq(irq, mana_gd_intr, 0, gic->name, gic); |
| 1276 | if (err) | 1260 | if (err) |
| 1277 | goto free_mask; | 1261 | goto free_irq; |
| 1278 | irq_set_affinity_and_hint(irq, req_mask); | 1262 | |
| 1279 | cpumask_clear(req_mask); | 1263 | cpu = cpumask_local_spread(i, gc->numa_node); |
| 1264 | irq_set_affinity_and_hint(irq, cpumask_of(cpu)); | ||
| 1280 | } | 1265 | } |
| 1281 | free_cpumask_var(req_mask); | ||
| 1282 | kfree(cpus); | ||
| 1283 | 1266 | ||
| 1284 | err = mana_gd_alloc_res_map(nvec, &gc->msix_resource); | 1267 | err = mana_gd_alloc_res_map(nvec, &gc->msix_resource); |
| 1285 | if (err) | 1268 | if (err) |
| @@ -1290,13 +1273,12 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 4 unmodified lines | |||
| 1290 | 1273 | ||
| 1291 | return 0; | 1274 | return 0; |
| 1292 | 1275 | ||
| 1293 | free_mask: | ||
| 1294 | free_cpumask_var(req_mask); | ||
| 1295 | kfree(cpus); | ||
| 1296 | free_irq: | 1276 | free_irq: |
| 1297 | for (j = i - 1; j >= 0; j--) { | 1277 | for (j = i - 1; j >= 0; j--) { |
| 1298 | irq = pci_irq_vector(pdev, j); | 1278 | irq = pci_irq_vector(pdev, j); |
| 1299 | gic = &gc->irq_contexts[j]; | 1279 | gic = &gc->irq_contexts[j]; |
| 1280 | |||
| 1281 | irq_update_affinity_hint(irq, NULL); | ||
| 1300 | free_irq(irq, gic); | 1282 | free_irq(irq, gic); |
| 1301 | } | 1283 | } |
| 1302 | 1284 | ||
| @@ -1324,6 +1306,9 @@ static void mana_gd_remove_irqs(struct pci_dev *pdev) · 21 unmodified lines | |||
| 1324 | continue; | 1306 | continue; |
| 1325 | 1307 | ||
| 1326 | gic = &gc->irq_contexts[i]; | 1308 | gic = &gc->irq_contexts[i]; |
| 1309 | |||
| 1310 | /* Need to clear the hint before free_irq */ | ||
| 1311 | irq_update_affinity_hint(irq, NULL); | ||
| 1327 | free_irq(irq, gic); | 1312 | free_irq(irq, gic); |
| 1328 | } | 1313 | } |
| 1329 | 1314 | ||
| @@ -605,6 +605,18 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, · 604 unmodified lines | |||
| 605 | flow_rule_match_control(rule, &match); | 605 | flow_rule_match_control(rule, &match); |
| 606 | } | 606 | } |
| 607 | 607 | ||
| 608 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { | ||
| 609 | struct flow_match_vlan match; | ||
| 610 | |||
| 611 | flow_rule_match_vlan(rule, &match); | ||
| 612 | filter->key_type = OCELOT_VCAP_KEY_ANY; | ||
| 613 | filter->vlan.vid.value = match.key->vlan_id; | ||
| 614 | filter->vlan.vid.mask = match.mask->vlan_id; | ||
| 615 | filter->vlan.pcp.value[0] = match.key->vlan_priority; | ||
| 616 | filter->vlan.pcp.mask[0] = match.mask->vlan_priority; | ||
| 617 | match_protocol = false; | ||
| 618 | } | ||
| 619 | |||
| 608 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { | 620 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { |
| 609 | struct flow_match_eth_addrs match; | 621 | struct flow_match_eth_addrs match; |
| 610 | 622 | ||
| @@ -737,18 +749,6 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, · 126 unmodified lines | |||
| 737 | match_protocol = false; | 749 | match_protocol = false; |
| 738 | } | 750 | } |
| 739 | 751 | ||
| 740 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { | ||
| 741 | struct flow_match_vlan match; | ||
| 742 | |||
| 743 | flow_rule_match_vlan(rule, &match); | ||
| 744 | filter->key_type = OCELOT_VCAP_KEY_ANY; | ||
| 745 | filter->vlan.vid.value = match.key->vlan_id; | ||
| 746 | filter->vlan.vid.mask = match.mask->vlan_id; | ||
| 747 | filter->vlan.pcp.value[0] = match.key->vlan_priority; | ||
| 748 | filter->vlan.pcp.mask[0] = match.mask->vlan_priority; | ||
| 749 | match_protocol = false; | ||
| 750 | } | ||
| 751 | |||
| 752 | finished_key_parsing: | 752 | finished_key_parsing: |
| 753 | if (match_protocol && proto != ETH_P_ALL) { | 753 | if (match_protocol && proto != ETH_P_ALL) { |
| 754 | if (filter->block_id == VCAP_ES0) { | 754 | if (filter->block_id == VCAP_ES0) { |
| @@ -335,8 +335,8 @@ static void · 334 unmodified lines | |||
| 335 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) | 335 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 336 | { | 336 | { |
| 337 | trap->key_type = OCELOT_VCAP_KEY_IPV6; | 337 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 338 | trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | 338 | trap->key.ipv6.proto.value[0] = IPPROTO_UDP; |
| 339 | trap->key.ipv4.proto.mask[0] = 0xff; | 339 | trap->key.ipv6.proto.mask[0] = 0xff; |
| 340 | trap->key.ipv6.dport.value = PTP_EV_PORT; | 340 | trap->key.ipv6.dport.value = PTP_EV_PORT; |
| 341 | trap->key.ipv6.dport.mask = 0xffff; | 341 | trap->key.ipv6.dport.mask = 0xffff; |
| 342 | } | 342 | } |
| @@ -355,8 +355,8 @@ static void · 12 unmodified lines | |||
| 355 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) | 355 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 356 | { | 356 | { |
| 357 | trap->key_type = OCELOT_VCAP_KEY_IPV6; | 357 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 358 | trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | 358 | trap->key.ipv6.proto.value[0] = IPPROTO_UDP; |
| 359 | trap->key.ipv4.proto.mask[0] = 0xff; | 359 | trap->key.ipv6.proto.mask[0] = 0xff; |
| 360 | trap->key.ipv6.dport.value = PTP_GEN_PORT; | 360 | trap->key.ipv6.dport.value = PTP_GEN_PORT; |
| 361 | trap->key.ipv6.dport.mask = 0xffff; | 361 | trap->key.ipv6.dport.mask = 0xffff; |
| 362 | } | 362 | } |
| @@ -293,35 +293,131 @@ nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port, · 292 unmodified lines | |||
| 293 | } | 293 | } |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static const u16 nfp_eth_media_table[] = { | 296 | static const struct nfp_eth_media_link_mode { |
| 297 | [NFP_MEDIA_1000BASE_CX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | 297 | u16 ethtool_link_mode; |
| 298 | [NFP_MEDIA_1000BASE_KX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | 298 | u16 speed; |
| 299 | [NFP_MEDIA_10GBASE_KX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | 299 | } nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { |
| 300 | [NFP_MEDIA_10GBASE_KR] = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, | 300 | [NFP_MEDIA_1000BASE_CX] = { |
| 301 | [NFP_MEDIA_10GBASE_CX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | 301 | .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, |
| 302 | [NFP_MEDIA_10GBASE_CR] = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, | 302 | .speed = NFP_SPEED_1G, |
| 303 | [NFP_MEDIA_10GBASE_SR] = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, | 303 | }, |
| 304 | [NFP_MEDIA_10GBASE_ER] = ETHTOOL_LINK_MODE_10000baseER_Full_BIT, | 304 | [NFP_MEDIA_1000BASE_KX] = { |
| 305 | [NFP_MEDIA_25GBASE_KR] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | 305 | .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, |
| 306 | [NFP_MEDIA_25GBASE_KR_S] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | 306 | .speed = NFP_SPEED_1G, |
| 307 | [NFP_MEDIA_25GBASE_CR] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | 307 | }, |
| 308 | [NFP_MEDIA_25GBASE_CR_S] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | 308 | [NFP_MEDIA_10GBASE_KX4] = { |
| 309 | [NFP_MEDIA_25GBASE_SR] = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, | 309 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, |
| 310 | [NFP_MEDIA_40GBASE_CR4] = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, | 310 | .speed = NFP_SPEED_10G, |
| 311 | [NFP_MEDIA_40GBASE_KR4] = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, | 311 | }, |
| 312 | [NFP_MEDIA_40GBASE_SR4] = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, | 312 | [NFP_MEDIA_10GBASE_KR] = { |
| 313 | [NFP_MEDIA_40GBASE_LR4] = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, | 313 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, |
| 314 | [NFP_MEDIA_50GBASE_KR] = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, | 314 | .speed = NFP_SPEED_10G, |
| 315 | [NFP_MEDIA_50GBASE_SR] = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, | 315 | }, |
| 316 | [NFP_MEDIA_50GBASE_CR] = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, | 316 | [NFP_MEDIA_10GBASE_CX4] = { |
| 317 | [NFP_MEDIA_50GBASE_LR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | 317 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, |
| 318 | [NFP_MEDIA_50GBASE_ER] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | 318 | .speed = NFP_SPEED_10G, |
| 319 | [NFP_MEDIA_50GBASE_FR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | 319 | }, |
| 320 | [NFP_MEDIA_100GBASE_KR4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | 320 | [NFP_MEDIA_10GBASE_CR] = { |
| 321 | [NFP_MEDIA_100GBASE_SR4] = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, | 321 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, |
| 322 | [NFP_MEDIA_100GBASE_CR4] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | 322 | .speed = NFP_SPEED_10G, |
| 323 | [NFP_MEDIA_100GBASE_KP4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | 323 | }, |
| 324 | [NFP_MEDIA_100GBASE_CR10] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | 324 | [NFP_MEDIA_10GBASE_SR] = { |
| 325 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, | ||
| 326 | .speed = NFP_SPEED_10G, | ||
| 327 | }, | ||
| 328 | [NFP_MEDIA_10GBASE_ER] = { | ||
| 329 | .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseER_Full_BIT, | ||
| 330 | .speed = NFP_SPEED_10G, | ||
| 331 | }, | ||
| 332 | [NFP_MEDIA_25GBASE_KR] = { | ||
| 333 | .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | ||
| 334 | .speed = NFP_SPEED_25G, | ||
| 335 | }, | ||
| 336 | [NFP_MEDIA_25GBASE_KR_S] = { | ||
| 337 | .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | ||
| 338 | .speed = NFP_SPEED_25G, | ||
| 339 | }, | ||
| 340 | [NFP_MEDIA_25GBASE_CR] = { | ||
| 341 | .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | ||
| 342 | .speed = NFP_SPEED_25G, | ||
| 343 | }, | ||
| 344 | [NFP_MEDIA_25GBASE_CR_S] = { | ||
| 345 | .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | ||
| 346 | .speed = NFP_SPEED_25G, | ||
| 347 | }, | ||
| 348 | [NFP_MEDIA_25GBASE_SR] = { | ||
| 349 | .ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, | ||
| 350 | .speed = NFP_SPEED_25G, | ||
| 351 | }, | ||
| 352 | [NFP_MEDIA_40GBASE_CR4] = { | ||
| 353 | .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, | ||
| 354 | .speed = NFP_SPEED_40G, | ||
| 355 | }, | ||
| 356 | [NFP_MEDIA_40GBASE_KR4] = { | ||
| 357 | .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, | ||
| 358 | .speed = NFP_SPEED_40G, | ||
| 359 | }, | ||
| 360 | [NFP_MEDIA_40GBASE_SR4] = { | ||
| 361 | .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, | ||
| 362 | .speed = NFP_SPEED_40G, | ||
| 363 | }, | ||
| 364 | [NFP_MEDIA_40GBASE_LR4] = { | ||
| 365 | .ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, | ||
| 366 | .speed = NFP_SPEED_40G, | ||
| 367 | }, | ||
| 368 | [NFP_MEDIA_50GBASE_KR] = { | ||
| 369 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, | ||
| 370 | .speed = NFP_SPEED_50G, | ||
| 371 | }, | ||
| 372 | [NFP_MEDIA_50GBASE_SR] = { | ||
| 373 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, | ||
| 374 | .speed = NFP_SPEED_50G, | ||
| 375 | }, | ||
| 376 | [NFP_MEDIA_50GBASE_CR] = { | ||
| 377 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, | ||
| 378 | .speed = NFP_SPEED_50G, | ||
| 379 | }, | ||
| 380 | [NFP_MEDIA_50GBASE_LR] = { | ||
| 381 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | ||
| 382 | .speed = NFP_SPEED_50G, | ||
| 383 | }, | ||
| 384 | [NFP_MEDIA_50GBASE_ER] = { | ||
| 385 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | ||
| 386 | .speed = NFP_SPEED_50G, | ||
| 387 | }, | ||
| 388 | [NFP_MEDIA_50GBASE_FR] = { | ||
| 389 | .ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | ||
| 390 | .speed = NFP_SPEED_50G, | ||
| 391 | }, | ||
| 392 | [NFP_MEDIA_100GBASE_KR4] = { | ||
| 393 | .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | ||
| 394 | .speed = NFP_SPEED_100G, | ||
| 395 | }, | ||
| 396 | [NFP_MEDIA_100GBASE_SR4] = { | ||
| 397 | .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, | ||
| 398 | .speed = NFP_SPEED_100G, | ||
| 399 | }, | ||
| 400 | [NFP_MEDIA_100GBASE_CR4] = { | ||
| 401 | .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | ||
| 402 | .speed = NFP_SPEED_100G, | ||
| 403 | }, | ||
| 404 | [NFP_MEDIA_100GBASE_KP4] = { | ||
| 405 | .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | ||
| 406 | .speed = NFP_SPEED_100G, | ||
| 407 | }, | ||
| 408 | [NFP_MEDIA_100GBASE_CR10] = { | ||
| 409 | .ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | ||
| 410 | .speed = NFP_SPEED_100G, | ||
| 411 | }, | ||
| 412 | }; | ||
| 413 | |||
| 414 | static const unsigned int nfp_eth_speed_map[NFP_SUP_SPEED_NUMBER] = { | ||
| 415 | [NFP_SPEED_1G] = SPEED_1000, | ||
| 416 | [NFP_SPEED_10G] = SPEED_10000, | ||
| 417 | [NFP_SPEED_25G] = SPEED_25000, | ||
| 418 | [NFP_SPEED_40G] = SPEED_40000, | ||
| 419 | [NFP_SPEED_50G] = SPEED_50000, | ||
| 420 | [NFP_SPEED_100G] = SPEED_100000, | ||
| 325 | }; | 421 | }; |
| 326 | 422 | ||
| 327 | static void nfp_add_media_link_mode(struct nfp_port *port, | 423 | static void nfp_add_media_link_mode(struct nfp_port *port, |
| @@ -334,8 +430,12 @@ static void nfp_add_media_link_mode(struct nfp_port *port, · 6 unmodified lines | |||
| 334 | }; | 430 | }; |
| 335 | struct nfp_cpp *cpp = port->app->cpp; | 431 | struct nfp_cpp *cpp = port->app->cpp; |
| 336 | 432 | ||
| 337 | if (nfp_eth_read_media(cpp, ðm)) | 433 | if (nfp_eth_read_media(cpp, ðm)) { |
| 434 | bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); | ||
| 338 | return; | 435 | return; |
| 436 | } | ||
| 437 | |||
| 438 | bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); | ||
| 339 | 439 | ||
| 340 | for (u32 i = 0; i < 2; i++) { | 440 | for (u32 i = 0; i < 2; i++) { |
| 341 | supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]); | 441 | supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]); |
| @@ -344,20 +444,26 @@ static void nfp_add_media_link_mode(struct nfp_port *port, · 2 unmodified lines | |||
| 344 | 444 | ||
| 345 | for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { | 445 | for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { |
| 346 | if (i < 64) { | 446 | if (i < 64) { |
| 347 | if (supported_modes[0] & BIT_ULL(i)) | 447 | if (supported_modes[0] & BIT_ULL(i)) { |
| 348 | __set_bit(nfp_eth_media_table[i], | 448 | __set_bit(nfp_eth_media_table[i].ethtool_link_mode, |
| 349 | cmd->link_modes.supported); | 449 | cmd->link_modes.supported); |
| 450 | __set_bit(nfp_eth_media_table[i].speed, | ||
| 451 | port->speed_bitmap); | ||
| 452 | } | ||
| 350 | 453 | ||
| 351 | if (advertised_modes[0] & BIT_ULL(i)) | 454 | if (advertised_modes[0] & BIT_ULL(i)) |
| 352 | __set_bit(nfp_eth_media_table[i], | 455 | __set_bit(nfp_eth_media_table[i].ethtool_link_mode, |
| 353 | cmd->link_modes.advertising); | 456 | cmd->link_modes.advertising); |
| 354 | } else { | 457 | } else { |
| 355 | if (supported_modes[1] & BIT_ULL(i - 64)) | 458 | if (supported_modes[1] & BIT_ULL(i - 64)) { |
| 356 | __set_bit(nfp_eth_media_table[i], | 459 | __set_bit(nfp_eth_media_table[i].ethtool_link_mode, |
| 357 | cmd->link_modes.supported); | 460 | cmd->link_modes.supported); |
| 461 | __set_bit(nfp_eth_media_table[i].speed, | ||
| 462 | port->speed_bitmap); | ||
| 463 | } | ||
| 358 | 464 | ||
| 359 | if (advertised_modes[1] & BIT_ULL(i - 64)) | 465 | if (advertised_modes[1] & BIT_ULL(i - 64)) |
| 360 | __set_bit(nfp_eth_media_table[i], | 466 | __set_bit(nfp_eth_media_table[i].ethtool_link_mode, |
| 361 | cmd->link_modes.advertising); | 467 | cmd->link_modes.advertising); |
| 362 | } | 468 | } |
| 363 | } | 469 | } |
| @@ -468,6 +574,22 @@ nfp_net_set_link_ksettings(struct net_device *netdev, · 104 unmodified lines | |||
| 468 | 574 | ||
| 469 | if (cmd->base.speed != SPEED_UNKNOWN) { | 575 | if (cmd->base.speed != SPEED_UNKNOWN) { |
| 470 | u32 speed = cmd->base.speed / eth_port->lanes; | 576 | u32 speed = cmd->base.speed / eth_port->lanes; |
| 577 | bool is_supported = false; | ||
| 578 | |||
| 579 | for (u32 i = 0; i < NFP_SUP_SPEED_NUMBER; i++) { | ||
| 580 | if (cmd->base.speed == nfp_eth_speed_map[i] && | ||
| 581 | test_bit(i, port->speed_bitmap)) { | ||
| 582 | is_supported = true; | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 587 | if (!is_supported) { | ||
| 588 | netdev_err(netdev, "Speed %u is not supported.\n", | ||
| 589 | cmd->base.speed); | ||
| 590 | err = -EINVAL; | ||
| 591 | goto err_bad_set; | ||
| 592 | } | ||
| 471 | 593 | ||
| 472 | if (req_aneg) { | 594 | if (req_aneg) { |
| 473 | netdev_err(netdev, "Speed changing is not allowed when working on autoneg mode.\n"); | 595 | netdev_err(netdev, "Speed changing is not allowed when working on autoneg mode.\n"); |
| @@ -38,6 +38,16 @@ enum nfp_port_flags { · 37 unmodified lines | |||
| 38 | NFP_PORT_CHANGED = 0, | 38 | NFP_PORT_CHANGED = 0, |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | enum { | ||
| 42 | NFP_SPEED_1G, | ||
| 43 | NFP_SPEED_10G, | ||
| 44 | NFP_SPEED_25G, | ||
| 45 | NFP_SPEED_40G, | ||
| 46 | NFP_SPEED_50G, | ||
| 47 | NFP_SPEED_100G, | ||
| 48 | NFP_SUP_SPEED_NUMBER | ||
| 49 | }; | ||
| 50 | |||
| 41 | /** | 51 | /** |
| 42 | * struct nfp_port - structure representing NFP port | 52 | * struct nfp_port - structure representing NFP port |
| 43 | * @netdev: backpointer to associated netdev | 53 | * @netdev: backpointer to associated netdev |
| @@ -52,6 +62,7 @@ enum nfp_port_flags { · 8 unmodified lines | |||
| 52 | * @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change | 62 | * @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change |
| 53 | * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry | 63 | * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry |
| 54 | * @eth_stats: for %NFP_PORT_PHYS_PORT MAC stats if available | 64 | * @eth_stats: for %NFP_PORT_PHYS_PORT MAC stats if available |
| 65 | * @speed_bitmap: for %NFP_PORT_PHYS_PORT supported speed bitmap | ||
| 55 | * @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3) | 66 | * @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3) |
| 56 | * @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id | 67 | * @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id |
| 57 | * @pf_split: for %NFP_PORT_PF_PORT %true if PCI PF has more than one vNIC | 68 | * @pf_split: for %NFP_PORT_PF_PORT %true if PCI PF has more than one vNIC |
| @@ -78,6 +89,7 @@ struct nfp_port { · 20 unmodified lines | |||
| 78 | bool eth_forced; | 89 | bool eth_forced; |
| 79 | struct nfp_eth_table_port *eth_port; | 90 | struct nfp_eth_table_port *eth_port; |
| 80 | u8 __iomem *eth_stats; | 91 | u8 __iomem *eth_stats; |
| 92 | DECLARE_BITMAP(speed_bitmap, NFP_SUP_SPEED_NUMBER); | ||
| 81 | }; | 93 | }; |
| 82 | /* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */ | 94 | /* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */ |
| 83 | struct { | 95 | struct { |
| @@ -708,9 +708,16 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb, · 707 unmodified lines | |||
| 708 | q->lif->index, q->name, q->hw_type, q->hw_index, | 708 | q->lif->index, q->name, q->hw_type, q->hw_index, |
| 709 | q->head_idx, ring_doorbell); | 709 | q->head_idx, ring_doorbell); |
| 710 | 710 | ||
| 711 | if (ring_doorbell) | 711 | if (ring_doorbell) { |
| 712 | ionic_dbell_ring(lif->kern_dbpage, q->hw_type, | 712 | ionic_dbell_ring(lif->kern_dbpage, q->hw_type, |
| 713 | q->dbval | q->head_idx); | 713 | q->dbval | q->head_idx); |
| 714 | |||
| 715 | q->dbell_jiffies = jiffies; | ||
| 716 | |||
| 717 | if (q_to_qcq(q)->napi_qcq) | ||
| 718 | mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline, | ||
| 719 | jiffies + IONIC_NAPI_DEADLINE); | ||
| 720 | } | ||
| 714 | } | 721 | } |
| 715 | 722 | ||
| 716 | static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos) | 723 | static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos) |
| @@ -25,6 +25,12 @@ · 24 unmodified lines | |||
| 25 | #define IONIC_DEV_INFO_REG_COUNT 32 | 25 | #define IONIC_DEV_INFO_REG_COUNT 32 |
| 26 | #define IONIC_DEV_CMD_REG_COUNT 32 | 26 | #define IONIC_DEV_CMD_REG_COUNT 32 |
| 27 | 27 | ||
| 28 | #define IONIC_NAPI_DEADLINE (HZ / 200) /* 5ms */ | ||
| 29 | #define IONIC_ADMIN_DOORBELL_DEADLINE (HZ / 2) /* 500ms */ | ||
| 30 | #define IONIC_TX_DOORBELL_DEADLINE (HZ / 100) /* 10ms */ | ||
| 31 | #define IONIC_RX_MIN_DOORBELL_DEADLINE (HZ / 100) /* 10ms */ | ||
| 32 | #define IONIC_RX_MAX_DOORBELL_DEADLINE (HZ * 5) /* 5s */ | ||
| 33 | |||
| 28 | struct ionic_dev_bar { | 34 | struct ionic_dev_bar { |
| 29 | void __iomem *vaddr; | 35 | void __iomem *vaddr; |
| 30 | phys_addr_t bus_addr; | 36 | phys_addr_t bus_addr; |
| @@ -216,6 +222,8 @@ struct ionic_queue { · 185 unmodified lines | |||
| 216 | struct ionic_lif *lif; | 222 | struct ionic_lif *lif; |
| 217 | struct ionic_desc_info *info; | 223 | struct ionic_desc_info *info; |
| 218 | u64 dbval; | 224 | u64 dbval; |
| 225 | unsigned long dbell_deadline; | ||
| 226 | unsigned long dbell_jiffies; | ||
| 219 | u16 head_idx; | 227 | u16 head_idx; |
| 220 | u16 tail_idx; | 228 | u16 tail_idx; |
| 221 | unsigned int index; | 229 | unsigned int index; |
| @@ -361,4 +369,8 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info, · 139 unmodified lines | |||
| 361 | int ionic_heartbeat_check(struct ionic *ionic); | 369 | int ionic_heartbeat_check(struct ionic *ionic); |
| 362 | bool ionic_is_fw_running(struct ionic_dev *idev); | 370 | bool ionic_is_fw_running(struct ionic_dev *idev); |
| 363 | 371 | ||
| 372 | bool ionic_adminq_poke_doorbell(struct ionic_queue *q); | ||
| 373 | bool ionic_txq_poke_doorbell(struct ionic_queue *q); | ||
| 374 | bool ionic_rxq_poke_doorbell(struct ionic_queue *q); | ||
| 375 | |||
| 364 | #endif /* _IONIC_DEV_H_ */ | 376 | #endif /* _IONIC_DEV_H_ */ |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | #include "ionic.h" | 17 | #include "ionic.h" |
| 18 | #include "ionic_bus.h" | 18 | #include "ionic_bus.h" |
| 19 | #include "ionic_dev.h" | ||
| 19 | #include "ionic_lif.h" | 20 | #include "ionic_lif.h" |
| 20 | #include "ionic_txrx.h" | 21 | #include "ionic_txrx.h" |
| 21 | #include "ionic_ethtool.h" | 22 | #include "ionic_ethtool.h" |
| @@ -200,6 +201,13 @@ void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep) · 178 unmodified lines | |||
| 200 | } | 201 | } |
| 201 | } | 202 | } |
| 202 | 203 | ||
| 204 | static void ionic_napi_deadline(struct timer_list *timer) | ||
| 205 | { | ||
| 206 | struct ionic_qcq *qcq = container_of(timer, struct ionic_qcq, napi_deadline); | ||
| 207 | |||
| 208 | napi_schedule(&qcq->napi); | ||
| 209 | } | ||
| 210 | |||
| 203 | static irqreturn_t ionic_isr(int irq, void *data) | 211 | static irqreturn_t ionic_isr(int irq, void *data) |
| 204 | { | 212 | { |
| 205 | struct napi_struct *napi = data; | 213 | struct napi_struct *napi = data; |
| @@ -269,6 +277,7 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) · 63 unmodified lines | |||
| 269 | .oper = IONIC_Q_ENABLE, | 277 | .oper = IONIC_Q_ENABLE, |
| 270 | }, | 278 | }, |
| 271 | }; | 279 | }; |
| 280 | int ret; | ||
| 272 | 281 | ||
| 273 | idev = &lif->ionic->idev; | 282 | idev = &lif->ionic->idev; |
| 274 | dev = lif->ionic->dev; | 283 | dev = lif->ionic->dev; |
| @@ -276,16 +285,24 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) · 1 unmodified line | |||
| 276 | dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n", | 285 | dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n", |
| 277 | ctx.cmd.q_control.index, ctx.cmd.q_control.type); | 286 | ctx.cmd.q_control.index, ctx.cmd.q_control.type); |
| 278 | 287 | ||
| 288 | if (qcq->flags & IONIC_QCQ_F_INTR) | ||
| 289 | ionic_intr_clean(idev->intr_ctrl, qcq->intr.index); | ||
| 290 | |||
| 291 | ret = ionic_adminq_post_wait(lif, &ctx); | ||
| 292 | if (ret) | ||
| 293 | return ret; | ||
| 294 | |||
| 295 | if (qcq->napi.poll) | ||
| 296 | napi_enable(&qcq->napi); | ||
| 297 | |||
| 279 | if (qcq->flags & IONIC_QCQ_F_INTR) { | 298 | if (qcq->flags & IONIC_QCQ_F_INTR) { |
| 280 | irq_set_affinity_hint(qcq->intr.vector, | 299 | irq_set_affinity_hint(qcq->intr.vector, |
| 281 | &qcq->intr.affinity_mask); | 300 | &qcq->intr.affinity_mask); |
| 282 | napi_enable(&qcq->napi); | ||
| 283 | ionic_intr_clean(idev->intr_ctrl, qcq->intr.index); | ||
| 284 | ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, | 301 | ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, |
| 285 | IONIC_INTR_MASK_CLEAR); | 302 | IONIC_INTR_MASK_CLEAR); |
| 286 | } | 303 | } |
| 287 | 304 | ||
| 288 | return ionic_adminq_post_wait(lif, &ctx); | 305 | return 0; |
| 289 | } | 306 | } |
| 290 | 307 | ||
| 291 | static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int fw_err) | 308 | static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int fw_err) |
| @@ -316,6 +333,7 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f · 24 unmodified lines | |||
| 316 | synchronize_irq(qcq->intr.vector); | 333 | synchronize_irq(qcq->intr.vector); |
| 317 | irq_set_affinity_hint(qcq->intr.vector, NULL); | 334 | irq_set_affinity_hint(qcq->intr.vector, NULL); |
| 318 | napi_disable(&qcq->napi); | 335 | napi_disable(&qcq->napi); |
| 336 | del_timer_sync(&qcq->napi_deadline); | ||
| 319 | } | 337 | } |
| 320 | 338 | ||
| 321 | /* If there was a previous fw communcation error, don't bother with | 339 | /* If there was a previous fw communcation error, don't bother with |
| @@ -451,6 +469,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, · 129 unmodified lines | |||
| 451 | 469 | ||
| 452 | n_qcq->intr.vector = src_qcq->intr.vector; | 470 | n_qcq->intr.vector = src_qcq->intr.vector; |
| 453 | n_qcq->intr.index = src_qcq->intr.index; | 471 | n_qcq->intr.index = src_qcq->intr.index; |
| 472 | n_qcq->napi_qcq = src_qcq->napi_qcq; | ||
| 454 | } | 473 | } |
| 455 | 474 | ||
| 456 | static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq) | 475 | static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq) |
| @@ -564,13 +583,15 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, · 107 unmodified lines | |||
| 564 | } | 583 | } |
| 565 | 584 | ||
| 566 | if (flags & IONIC_QCQ_F_NOTIFYQ) { | 585 | if (flags & IONIC_QCQ_F_NOTIFYQ) { |
| 567 | int q_size, cq_size; | 586 | int q_size; |
| 568 | 587 | ||
| 569 | /* q & cq need to be contiguous in case of notifyq */ | 588 | /* q & cq need to be contiguous in NotifyQ, so alloc it all in q |
| 589 | * and don't alloc qc. We leave new->qc_size and new->qc_base | ||
| 590 | * as 0 to be sure we don't try to free it later. | ||
| 591 | */ | ||
| 570 | q_size = ALIGN(num_descs * desc_size, PAGE_SIZE); | 592 | q_size = ALIGN(num_descs * desc_size, PAGE_SIZE); |
| 571 | cq_size = ALIGN(num_descs * cq_desc_size, PAGE_SIZE); | 593 | new->q_size = PAGE_SIZE + q_size + |
| 572 | 594 | ALIGN(num_descs * cq_desc_size, PAGE_SIZE); | |
| 573 | new->q_size = PAGE_SIZE + q_size + cq_size; | ||
| 574 | new->q_base = dma_alloc_coherent(dev, new->q_size, | 595 | new->q_base = dma_alloc_coherent(dev, new->q_size, |
| 575 | &new->q_base_pa, GFP_KERNEL); | 596 | &new->q_base_pa, GFP_KERNEL); |
| 576 | if (!new->q_base) { | 597 | if (!new->q_base) { |
| @@ -773,8 +794,14 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) · 196 unmodified lines | |||
| 773 | dev_dbg(dev, "txq->hw_type %d\n", q->hw_type); | 794 | dev_dbg(dev, "txq->hw_type %d\n", q->hw_type); |
| 774 | dev_dbg(dev, "txq->hw_index %d\n", q->hw_index); | 795 | dev_dbg(dev, "txq->hw_index %d\n", q->hw_index); |
| 775 | 796 | ||
| 776 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) | 797 | q->dbell_deadline = IONIC_TX_DOORBELL_DEADLINE; |
| 798 | q->dbell_jiffies = jiffies; | ||
| 799 | |||
| 800 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) { | ||
| 777 | netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi); | 801 | netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi); |
| 802 | qcq->napi_qcq = qcq; | ||
| 803 | timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); | ||
| 804 | } | ||
| 778 | 805 | ||
| 779 | qcq->flags |= IONIC_QCQ_F_INITED; | 806 | qcq->flags |= IONIC_QCQ_F_INITED; |
| 780 | 807 | ||
| @@ -828,11 +855,17 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) · 47 unmodified lines | |||
| 828 | dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type); | 855 | dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type); |
| 829 | dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index); | 856 | dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index); |
| 830 | 857 | ||
| 858 | q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE; | ||
| 859 | q->dbell_jiffies = jiffies; | ||
| 860 | |||
| 831 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) | 861 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) |
| 832 | netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi); | 862 | netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi); |
| 833 | else | 863 | else |
| 834 | netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi); | 864 | netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi); |
| 835 | 865 | ||
| 866 | qcq->napi_qcq = qcq; | ||
| 867 | timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); | ||
| 868 | |||
| 836 | qcq->flags |= IONIC_QCQ_F_INITED; | 869 | qcq->flags |= IONIC_QCQ_F_INITED; |
| 837 | 870 | ||
| 838 | return 0; | 871 | return 0; |
| @@ -1150,6 +1183,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) · 311 unmodified lines | |||
| 1150 | struct ionic_dev *idev = &lif->ionic->idev; | 1183 | struct ionic_dev *idev = &lif->ionic->idev; |
| 1151 | unsigned long irqflags; | 1184 | unsigned long irqflags; |
| 1152 | unsigned int flags = 0; | 1185 | unsigned int flags = 0; |
| 1186 | bool resched = false; | ||
| 1153 | int rx_work = 0; | 1187 | int rx_work = 0; |
| 1154 | int tx_work = 0; | 1188 | int tx_work = 0; |
| 1155 | int n_work = 0; | 1189 | int n_work = 0; |
| @@ -1187,6 +1221,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) · 31 unmodified lines | |||
| 1187 | ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags); | 1221 | ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags); |
| 1188 | } | 1222 | } |
| 1189 | 1223 | ||
| 1224 | if (!a_work && ionic_adminq_poke_doorbell(&lif->adminqcq->q)) | ||
| 1225 | resched = true; | ||
| 1226 | if (lif->hwstamp_rxq && !rx_work && ionic_rxq_poke_doorbell(&lif->hwstamp_rxq->q)) | ||
| 1227 | resched = true; | ||
| 1228 | if (lif->hwstamp_txq && !tx_work && ionic_txq_poke_doorbell(&lif->hwstamp_txq->q)) | ||
| 1229 | resched = true; | ||
| 1230 | if (resched) | ||
| 1231 | mod_timer(&lif->adminqcq->napi_deadline, | ||
| 1232 | jiffies + IONIC_NAPI_DEADLINE); | ||
| 1233 | |||
| 1190 | return work_done; | 1234 | return work_done; |
| 1191 | } | 1235 | } |
| 1192 | 1236 | ||
| @@ -3245,8 +3289,14 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif) · 2052 unmodified lines | |||
| 3245 | dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type); | 3289 | dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type); |
| 3246 | dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index); | 3290 | dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index); |
| 3247 | 3291 | ||
| 3292 | q->dbell_deadline = IONIC_ADMIN_DOORBELL_DEADLINE; | ||
| 3293 | q->dbell_jiffies = jiffies; | ||
| 3294 | |||
| 3248 | netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi); | 3295 | netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi); |
| 3249 | 3296 | ||
| 3297 | qcq->napi_qcq = qcq; | ||
| 3298 | timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); | ||
| 3299 | |||
| 3250 | napi_enable(&qcq->napi); | 3300 | napi_enable(&qcq->napi); |
| 3251 | 3301 | ||
| 3252 | if (qcq->flags & IONIC_QCQ_F_INTR) | 3302 | if (qcq->flags & IONIC_QCQ_F_INTR) |
| @@ -74,8 +74,10 @@ struct ionic_qcq { · 73 unmodified lines | |||
| 74 | struct ionic_queue q; | 74 | struct ionic_queue q; |
| 75 | struct ionic_cq cq; | 75 | struct ionic_cq cq; |
| 76 | struct ionic_intr_info intr; | 76 | struct ionic_intr_info intr; |
| 77 | struct timer_list napi_deadline; | ||
| 77 | struct napi_struct napi; | 78 | struct napi_struct napi; |
| 78 | unsigned int flags; | 79 | unsigned int flags; |
| 80 | struct ionic_qcq *napi_qcq; | ||
| 79 | struct dentry *dentry; | 81 | struct dentry *dentry; |
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| @@ -289,6 +289,35 @@ static void ionic_adminq_cb(struct ionic_queue *q, · 288 unmodified lines | |||
| 289 | complete_all(&ctx->work); | 289 | complete_all(&ctx->work); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | bool ionic_adminq_poke_doorbell(struct ionic_queue *q) | ||
| 293 | { | ||
| 294 | struct ionic_lif *lif = q->lif; | ||
| 295 | unsigned long now, then, dif; | ||
| 296 | unsigned long irqflags; | ||
| 297 | |||
| 298 | spin_lock_irqsave(&lif->adminq_lock, irqflags); | ||
| 299 | |||
| 300 | if (q->tail_idx == q->head_idx) { | ||
| 301 | spin_unlock_irqrestore(&lif->adminq_lock, irqflags); | ||
| 302 | return false; | ||
| 303 | } | ||
| 304 | |||
| 305 | now = READ_ONCE(jiffies); | ||
| 306 | then = q->dbell_jiffies; | ||
| 307 | dif = now - then; | ||
| 308 | |||
| 309 | if (dif > q->dbell_deadline) { | ||
| 310 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, | ||
| 311 | q->dbval | q->head_idx); | ||
| 312 | |||
| 313 | q->dbell_jiffies = now; | ||
| 314 | } | ||
| 315 | |||
| 316 | spin_unlock_irqrestore(&lif->adminq_lock, irqflags); | ||
| 317 | |||
| 318 | return true; | ||
| 319 | } | ||
| 320 | |||
| 292 | int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) | 321 | int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) |
| 293 | { | 322 | { |
| 294 | struct ionic_desc_info *desc_info; | 323 | struct ionic_desc_info *desc_info; |
| @@ -22,6 +22,67 @@ static inline void ionic_rxq_post(struct ionic_queue *q, bool ring_dbell, · 21 unmodified lines | |||
| 22 | ionic_q_post(q, ring_dbell, cb_func, cb_arg); | 22 | ionic_q_post(q, ring_dbell, cb_func, cb_arg); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | bool ionic_txq_poke_doorbell(struct ionic_queue *q) | ||
| 26 | { | ||
| 27 | unsigned long now, then, dif; | ||
| 28 | struct netdev_queue *netdev_txq; | ||
| 29 | struct net_device *netdev; | ||
| 30 | |||
| 31 | netdev = q->lif->netdev; | ||
| 32 | netdev_txq = netdev_get_tx_queue(netdev, q->index); | ||
| 33 | |||
| 34 | HARD_TX_LOCK(netdev, netdev_txq, smp_processor_id()); | ||
| 35 | |||
| 36 | if (q->tail_idx == q->head_idx) { | ||
| 37 | HARD_TX_UNLOCK(netdev, netdev_txq); | ||
| 38 | return false; | ||
| 39 | } | ||
| 40 | |||
| 41 | now = READ_ONCE(jiffies); | ||
| 42 | then = q->dbell_jiffies; | ||
| 43 | dif = now - then; | ||
| 44 | |||
| 45 | if (dif > q->dbell_deadline) { | ||
| 46 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, | ||
| 47 | q->dbval | q->head_idx); | ||
| 48 | |||
| 49 | q->dbell_jiffies = now; | ||
| 50 | } | ||
| 51 | |||
| 52 | HARD_TX_UNLOCK(netdev, netdev_txq); | ||
| 53 | |||
| 54 | return true; | ||
| 55 | } | ||
| 56 | |||
| 57 | bool ionic_rxq_poke_doorbell(struct ionic_queue *q) | ||
| 58 | { | ||
| 59 | unsigned long now, then, dif; | ||
| 60 | |||
| 61 | /* no lock, called from rx napi or txrx napi, nothing else can fill */ | ||
| 62 | |||
| 63 | if (q->tail_idx == q->head_idx) | ||
| 64 | return false; | ||
| 65 | |||
| 66 | now = READ_ONCE(jiffies); | ||
| 67 | then = q->dbell_jiffies; | ||
| 68 | dif = now - then; | ||
| 69 | |||
| 70 | if (dif > q->dbell_deadline) { | ||
| 71 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, | ||
| 72 | q->dbval | q->head_idx); | ||
| 73 | |||
| 74 | q->dbell_jiffies = now; | ||
| 75 | |||
| 76 | dif = 2 * q->dbell_deadline; | ||
| 77 | if (dif > IONIC_RX_MAX_DOORBELL_DEADLINE) | ||
| 78 | dif = IONIC_RX_MAX_DOORBELL_DEADLINE; | ||
| 79 | |||
| 80 | q->dbell_deadline = dif; | ||
| 81 | } | ||
| 82 | |||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 25 | static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q) | 86 | static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q) |
| 26 | { | 87 | { |
| 27 | return netdev_get_tx_queue(q->lif->netdev, q->index); | 88 | return netdev_get_tx_queue(q->lif->netdev, q->index); |
| @@ -424,6 +485,12 @@ void ionic_rx_fill(struct ionic_queue *q) · 396 unmodified lines | |||
| 424 | 485 | ||
| 425 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, | 486 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, |
| 426 | q->dbval | q->head_idx); | 487 | q->dbval | q->head_idx); |
| 488 | |||
| 489 | q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE; | ||
| 490 | q->dbell_jiffies = jiffies; | ||
| 491 | |||
| 492 | mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline, | ||
| 493 | jiffies + IONIC_NAPI_DEADLINE); | ||
| 427 | } | 494 | } |
| 428 | 495 | ||
| 429 | void ionic_rx_empty(struct ionic_queue *q) | 496 | void ionic_rx_empty(struct ionic_queue *q) |
| @@ -511,6 +578,9 @@ int ionic_tx_napi(struct napi_struct *napi, int budget) · 81 unmodified lines | |||
| 511 | work_done, flags); | 578 | work_done, flags); |
| 512 | } | 579 | } |
| 513 | 580 | ||
| 581 | if (!work_done && ionic_txq_poke_doorbell(&qcq->q)) | ||
| 582 | mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); | ||
| 583 | |||
| 514 | return work_done; | 584 | return work_done; |
| 515 | } | 585 | } |
| 516 | 586 | ||
| @@ -544,23 +614,29 @@ int ionic_rx_napi(struct napi_struct *napi, int budget) · 27 unmodified lines | |||
| 544 | work_done, flags); | 614 | work_done, flags); |
| 545 | } | 615 | } |
| 546 | 616 | ||
| 617 | if (!work_done && ionic_rxq_poke_doorbell(&qcq->q)) | ||
| 618 | mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); | ||
| 619 | |||
| 547 | return work_done; | 620 | return work_done; |
| 548 | } | 621 | } |
| 549 | 622 | ||
| 550 | int ionic_txrx_napi(struct napi_struct *napi, int budget) | 623 | int ionic_txrx_napi(struct napi_struct *napi, int budget) |
| 551 | { | 624 | { |
| 552 | struct ionic_qcq *qcq = napi_to_qcq(napi); | 625 | struct ionic_qcq *rxqcq = napi_to_qcq(napi); |
| 553 | struct ionic_cq *rxcq = napi_to_cq(napi); | 626 | struct ionic_cq *rxcq = napi_to_cq(napi); |
| 554 | unsigned int qi = rxcq->bound_q->index; | 627 | unsigned int qi = rxcq->bound_q->index; |
| 628 | struct ionic_qcq *txqcq; | ||
| 555 | struct ionic_dev *idev; | 629 | struct ionic_dev *idev; |
| 556 | struct ionic_lif *lif; | 630 | struct ionic_lif *lif; |
| 557 | struct ionic_cq *txcq; | 631 | struct ionic_cq *txcq; |
| 632 | bool resched = false; | ||
| 558 | u32 rx_work_done = 0; | 633 | u32 rx_work_done = 0; |
| 559 | u32 tx_work_done = 0; | 634 | u32 tx_work_done = 0; |
| 560 | u32 flags = 0; | 635 | u32 flags = 0; |
| 561 | 636 | ||
| 562 | lif = rxcq->bound_q->lif; | 637 | lif = rxcq->bound_q->lif; |
| 563 | idev = &lif->ionic->idev; | 638 | idev = &lif->ionic->idev; |
| 639 | txqcq = lif->txqcqs[qi]; | ||
| 564 | txcq = &lif->txqcqs[qi]->cq; | 640 | txcq = &lif->txqcqs[qi]->cq; |
| 565 | 641 | ||
| 566 | tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT, | 642 | tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT, |
| @@ -572,7 +648,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) · 5 unmodified lines | |||
| 572 | ionic_rx_fill(rxcq->bound_q); | 648 | ionic_rx_fill(rxcq->bound_q); |
| 573 | 649 | ||
| 574 | if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) { | 650 | if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) { |
| 575 | ionic_dim_update(qcq, 0); | 651 | ionic_dim_update(rxqcq, 0); |
| 576 | flags |= IONIC_INTR_CRED_UNMASK; | 652 | flags |= IONIC_INTR_CRED_UNMASK; |
| 577 | rxcq->bound_intr->rearm_count++; | 653 | rxcq->bound_intr->rearm_count++; |
| 578 | } | 654 | } |
| @@ -583,6 +659,13 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) · 4 unmodified lines | |||
| 583 | tx_work_done + rx_work_done, flags); | 659 | tx_work_done + rx_work_done, flags); |
| 584 | } | 660 | } |
| 585 | 661 | ||
| 662 | if (!rx_work_done && ionic_rxq_poke_doorbell(&rxqcq->q)) | ||
| 663 | resched = true; | ||
| 664 | if (!tx_work_done && ionic_txq_poke_doorbell(&txqcq->q)) | ||
| 665 | resched = true; | ||
| 666 | if (resched) | ||
| 667 | mod_timer(&rxqcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); | ||
| 668 | |||
| 586 | return rx_work_done; | 669 | return rx_work_done; |
| 587 | } | 670 | } |
| 588 | 671 | ||
| @@ -1034,7 +1034,7 @@ static int netvsc_dma_map(struct hv_device *hv_dev, · 1033 unmodified lines | |||
| 1034 | 1034 | ||
| 1035 | packet->dma_range = kcalloc(page_count, | 1035 | packet->dma_range = kcalloc(page_count, |
| 1036 | sizeof(*packet->dma_range), | 1036 | sizeof(*packet->dma_range), |
| 1037 | GFP_KERNEL); | 1037 | GFP_ATOMIC); |
| 1038 | if (!packet->dma_range) | 1038 | if (!packet->dma_range) |
| 1039 | return -ENOMEM; | 1039 | return -ENOMEM; |
| 1040 | 1040 | ||
| @@ -261,6 +261,8 @@ static struct phy_driver meson_gxl_phy[] = { · 260 unmodified lines | |||
| 261 | .handle_interrupt = meson_gxl_handle_interrupt, | 261 | .handle_interrupt = meson_gxl_handle_interrupt, |
| 262 | .suspend = genphy_suspend, | 262 | .suspend = genphy_suspend, |
| 263 | .resume = genphy_resume, | 263 | .resume = genphy_resume, |
| 264 | .read_mmd = genphy_read_mmd_unsupported, | ||
| 265 | .write_mmd = genphy_write_mmd_unsupported, | ||
| 264 | }, { | 266 | }, { |
| 265 | PHY_ID_MATCH_EXACT(0x01803301), | 267 | PHY_ID_MATCH_EXACT(0x01803301), |
| 266 | .name = "Meson G12A Internal PHY", | 268 | .name = "Meson G12A Internal PHY", |
| @@ -1816,10 +1816,9 @@ int phylink_fwnode_phy_connect(struct phylink *pl, · 1815 unmodified lines | |||
| 1816 | 1816 | ||
| 1817 | ret = phy_attach_direct(pl->netdev, phy_dev, flags, | 1817 | ret = phy_attach_direct(pl->netdev, phy_dev, flags, |
| 1818 | pl->link_interface); | 1818 | pl->link_interface); |
| 1819 | if (ret) { | 1819 | phy_device_free(phy_dev); |
| 1820 | phy_device_free(phy_dev); | 1820 | if (ret) |
| 1821 | return ret; | 1821 | return ret; |
| 1822 | } | ||
| 1823 | 1822 | ||
| 1824 | ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface); | 1823 | ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface); |
| 1825 | if (ret) | 1824 | if (ret) |
| @@ -57,9 +57,7 @@ · 56 unmodified lines | |||
| 57 | static inline int | 57 | static inline int |
| 58 | pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) | 58 | pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) |
| 59 | { | 59 | { |
| 60 | return usbnet_read_cmd(dev, req, | 60 | return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 61 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
| 62 | USB_RECIP_DEVICE, | ||
| 63 | val, index, NULL, 0); | 61 | val, index, NULL, 0); |
| 64 | } | 62 | } |
| 65 | 63 | ||
| @@ -45,6 +45,8 @@ struct nvme_dhchap_queue_context { · 44 unmodified lines | |||
| 45 | int sess_key_len; | 45 | int sess_key_len; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | struct workqueue_struct *nvme_auth_wq; | ||
| 49 | |||
| 48 | #define nvme_auth_flags_from_qid(qid) \ | 50 | #define nvme_auth_flags_from_qid(qid) \ |
| 49 | (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED | 51 | (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED |
| 50 | #define nvme_auth_queue_from_qid(ctrl, qid) \ | 52 | #define nvme_auth_queue_from_qid(ctrl, qid) \ |
| @@ -866,7 +868,7 @@ int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid) · 815 unmodified lines | |||
| 866 | 868 | ||
| 867 | chap = &ctrl->dhchap_ctxs[qid]; | 869 | chap = &ctrl->dhchap_ctxs[qid]; |
| 868 | cancel_work_sync(&chap->auth_work); | 870 | cancel_work_sync(&chap->auth_work); |
| 869 | queue_work(nvme_wq, &chap->auth_work); | 871 | queue_work(nvme_auth_wq, &chap->auth_work); |
| 870 | return 0; | 872 | return 0; |
| 871 | } | 873 | } |
| 872 | EXPORT_SYMBOL_GPL(nvme_auth_negotiate); | 874 | EXPORT_SYMBOL_GPL(nvme_auth_negotiate); |
| @@ -1008,10 +1010,15 @@ EXPORT_SYMBOL_GPL(nvme_auth_free); · 135 unmodified lines | |||
| 1008 | 1010 | ||
| 1009 | int __init nvme_init_auth(void) | 1011 | int __init nvme_init_auth(void) |
| 1010 | { | 1012 | { |
| 1013 | nvme_auth_wq = alloc_workqueue("nvme-auth-wq", | ||
| 1014 | WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); | ||
| 1015 | if (!nvme_auth_wq) | ||
| 1016 | return -ENOMEM; | ||
| 1017 | |||
| 1011 | nvme_chap_buf_cache = kmem_cache_create("nvme-chap-buf-cache", | 1018 | nvme_chap_buf_cache = kmem_cache_create("nvme-chap-buf-cache", |
| 1012 | CHAP_BUF_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL); | 1019 | CHAP_BUF_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL); |
| 1013 | if (!nvme_chap_buf_cache) | 1020 | if (!nvme_chap_buf_cache) |
| 1014 | return -ENOMEM; | 1021 | goto err_destroy_workqueue; |
| 1015 | 1022 | ||
| 1016 | nvme_chap_buf_pool = mempool_create(16, mempool_alloc_slab, | 1023 | nvme_chap_buf_pool = mempool_create(16, mempool_alloc_slab, |
| 1017 | mempool_free_slab, nvme_chap_buf_cache); | 1024 | mempool_free_slab, nvme_chap_buf_cache); |
| @@ -1021,6 +1028,8 @@ int __init nvme_init_auth(void) · 3 unmodified lines | |||
| 1021 | return 0; | 1028 | return 0; |
| 1022 | err_destroy_chap_buf_cache: | 1029 | err_destroy_chap_buf_cache: |
| 1023 | kmem_cache_destroy(nvme_chap_buf_cache); | 1030 | kmem_cache_destroy(nvme_chap_buf_cache); |
| 1031 | err_destroy_workqueue: | ||
| 1032 | destroy_workqueue(nvme_auth_wq); | ||
| 1024 | return -ENOMEM; | 1033 | return -ENOMEM; |
| 1025 | } | 1034 | } |
| 1026 | 1035 | ||
| @@ -1028,4 +1037,5 @@ void __exit nvme_exit_auth(void) · 1 unmodified line | |||
| 1028 | { | 1037 | { |
| 1029 | mempool_destroy(nvme_chap_buf_pool); | 1038 | mempool_destroy(nvme_chap_buf_pool); |
| 1030 | kmem_cache_destroy(nvme_chap_buf_cache); | 1039 | kmem_cache_destroy(nvme_chap_buf_cache); |
| 1040 | destroy_workqueue(nvme_auth_wq); | ||
| 1031 | } | 1041 | } |
| @@ -4921,7 +4921,9 @@ out_cleanup_admin_q: · 4920 unmodified lines | |||
| 4921 | blk_mq_destroy_queue(ctrl->admin_q); | 4921 | blk_mq_destroy_queue(ctrl->admin_q); |
| 4922 | blk_put_queue(ctrl->admin_q); | 4922 | blk_put_queue(ctrl->admin_q); |
| 4923 | out_free_tagset: | 4923 | out_free_tagset: |
| 4924 | blk_mq_free_tag_set(ctrl->admin_tagset); | 4924 | blk_mq_free_tag_set(set); |
| 4925 | ctrl->admin_q = NULL; | ||
| 4926 | ctrl->fabrics_q = NULL; | ||
| 4925 | return ret; | 4927 | return ret; |
| 4926 | } | 4928 | } |
| 4927 | EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set); | 4929 | EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set); |
| @@ -4983,6 +4985,7 @@ int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, · 55 unmodified lines | |||
| 4983 | 4985 | ||
| 4984 | out_free_tag_set: | 4986 | out_free_tag_set: |
| 4985 | blk_mq_free_tag_set(set); | 4987 | blk_mq_free_tag_set(set); |
| 4988 | ctrl->connect_q = NULL; | ||
| 4986 | return ret; | 4989 | return ret; |
| 4987 | } | 4990 | } |
| 4988 | EXPORT_SYMBOL_GPL(nvme_alloc_io_tag_set); | 4991 | EXPORT_SYMBOL_GPL(nvme_alloc_io_tag_set); |
| @@ -1685,8 +1685,10 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, · 1684 unmodified lines | |||
| 1685 | else { | 1685 | else { |
| 1686 | queue = nvmet_fc_alloc_target_queue(iod->assoc, 0, | 1686 | queue = nvmet_fc_alloc_target_queue(iod->assoc, 0, |
| 1687 | be16_to_cpu(rqst->assoc_cmd.sqsize)); | 1687 | be16_to_cpu(rqst->assoc_cmd.sqsize)); |
| 1688 | if (!queue) | 1688 | if (!queue) { |
| 1689 | ret = VERR_QUEUE_ALLOC_FAIL; | 1689 | ret = VERR_QUEUE_ALLOC_FAIL; |
| 1690 | nvmet_fc_tgt_a_put(iod->assoc); | ||
| 1691 | } | ||
| 1690 | } | 1692 | } |
| 1691 | } | 1693 | } |
| 1692 | 1694 | ||
| @@ -98,6 +98,9 @@ static int brcm_nvram_parse(struct brcm_nvram *priv) · 97 unmodified lines | |||
| 98 | len = le32_to_cpu(header.len); | 98 | len = le32_to_cpu(header.len); |
| 99 | 99 | ||
| 100 | data = kzalloc(len, GFP_KERNEL); | 100 | data = kzalloc(len, GFP_KERNEL); |
| 101 | if (!data) | ||
| 102 | return -ENOMEM; | ||
| 103 | |||
| 101 | memcpy_fromio(data, priv->base, len); | 104 | memcpy_fromio(data, priv->base, len); |
| 102 | data[len - 1] = '\0'; | 105 | data[len - 1] = '\0'; |
| 103 | 106 | ||
| @@ -770,31 +770,32 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) · 769 unmodified lines | |||
| 770 | return ERR_PTR(rval); | 770 | return ERR_PTR(rval); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | if (config->wp_gpio) | 773 | nvmem->id = rval; |
| 774 | nvmem->wp_gpio = config->wp_gpio; | 774 | |
| 775 | else if (!config->ignore_wp) | 775 | nvmem->dev.type = &nvmem_provider_type; |
| 776 | nvmem->dev.bus = &nvmem_bus_type; | ||
| 777 | nvmem->dev.parent = config->dev; | ||
| 778 | |||
| 779 | device_initialize(&nvmem->dev); | ||
| 780 | |||
| 781 | if (!config->ignore_wp) | ||
| 776 | nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp", | 782 | nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp", |
| 777 | GPIOD_OUT_HIGH); | 783 | GPIOD_OUT_HIGH); |
| 778 | if (IS_ERR(nvmem->wp_gpio)) { | 784 | if (IS_ERR(nvmem->wp_gpio)) { |
| 779 | ida_free(&nvmem_ida, nvmem->id); | ||
| 780 | rval = PTR_ERR(nvmem->wp_gpio); | 785 | rval = PTR_ERR(nvmem->wp_gpio); |
| 781 | kfree(nvmem); | 786 | nvmem->wp_gpio = NULL; |
| 782 | return ERR_PTR(rval); | 787 | goto err_put_device; |
| 783 | } | 788 | } |
| 784 | 789 | ||
| 785 | kref_init(&nvmem->refcnt); | 790 | kref_init(&nvmem->refcnt); |
| 786 | INIT_LIST_HEAD(&nvmem->cells); | 791 | INIT_LIST_HEAD(&nvmem->cells); |
| 787 | 792 | ||
| 788 | nvmem->id = rval; | ||
| 789 | nvmem->owner = config->owner; | 793 | nvmem->owner = config->owner; |
| 790 | if (!nvmem->owner && config->dev->driver) | 794 | if (!nvmem->owner && config->dev->driver) |
| 791 | nvmem->owner = config->dev->driver->owner; | 795 | nvmem->owner = config->dev->driver->owner; |
| 792 | nvmem->stride = config->stride ?: 1; | 796 | nvmem->stride = config->stride ?: 1; |
| 793 | nvmem->word_size = config->word_size ?: 1; | 797 | nvmem->word_size = config->word_size ?: 1; |
| 794 | nvmem->size = config->size; | 798 | nvmem->size = config->size; |
| 795 | nvmem->dev.type = &nvmem_provider_type; | ||
| 796 | nvmem->dev.bus = &nvmem_bus_type; | ||
| 797 | nvmem->dev.parent = config->dev; | ||
| 798 | nvmem->root_only = config->root_only; | 799 | nvmem->root_only = config->root_only; |
| 799 | nvmem->priv = config->priv; | 800 | nvmem->priv = config->priv; |
| 800 | nvmem->type = config->type; | 801 | nvmem->type = config->type; |
| @@ -822,11 +823,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) · 21 unmodified lines | |||
| 822 | break; | 823 | break; |
| 823 | } | 824 | } |
| 824 | 825 | ||
| 825 | if (rval) { | 826 | if (rval) |
| 826 | ida_free(&nvmem_ida, nvmem->id); | 827 | goto err_put_device; |
| 827 | kfree(nvmem); | ||
| 828 | return ERR_PTR(rval); | ||
| 829 | } | ||
| 830 | 828 | ||
| 831 | nvmem->read_only = device_property_present(config->dev, "read-only") || | 829 | nvmem->read_only = device_property_present(config->dev, "read-only") || |
| 832 | config->read_only || !nvmem->reg_write; | 830 | config->read_only || !nvmem->reg_write; |
| @@ -835,28 +833,22 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) · 2 unmodified lines | |||
| 835 | nvmem->dev.groups = nvmem_dev_groups; | 833 | nvmem->dev.groups = nvmem_dev_groups; |
| 836 | #endif | 834 | #endif |
| 837 | 835 | ||
| 838 | dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); | ||
| 839 | |||
| 840 | rval = device_register(&nvmem->dev); | ||
| 841 | if (rval) | ||
| 842 | goto err_put_device; | ||
| 843 | |||
| 844 | if (nvmem->nkeepout) { | 836 | if (nvmem->nkeepout) { |
| 845 | rval = nvmem_validate_keepouts(nvmem); | 837 | rval = nvmem_validate_keepouts(nvmem); |
| 846 | if (rval) | 838 | if (rval) |
| 847 | goto err_device_del; | 839 | goto err_put_device; |
| 848 | } | 840 | } |
| 849 | 841 | ||
| 850 | if (config->compat) { | 842 | if (config->compat) { |
| 851 | rval = nvmem_sysfs_setup_compat(nvmem, config); | 843 | rval = nvmem_sysfs_setup_compat(nvmem, config); |
| 852 | if (rval) | 844 | if (rval) |
| 853 | goto err_device_del; | 845 | goto err_put_device; |
| 854 | } | 846 | } |
| 855 | 847 | ||
| 856 | if (config->cells) { | 848 | if (config->cells) { |
| 857 | rval = nvmem_add_cells(nvmem, config->cells, config->ncells); | 849 | rval = nvmem_add_cells(nvmem, config->cells, config->ncells); |
| 858 | if (rval) | 850 | if (rval) |
| 859 | goto err_teardown_compat; | 851 | goto err_remove_cells; |
| 860 | } | 852 | } |
| 861 | 853 | ||
| 862 | rval = nvmem_add_cells_from_table(nvmem); | 854 | rval = nvmem_add_cells_from_table(nvmem); |
| @@ -867,17 +859,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) · 4 unmodified lines | |||
| 867 | if (rval) | 859 | if (rval) |
| 868 | goto err_remove_cells; | 860 | goto err_remove_cells; |
| 869 | 861 | ||
| 862 | dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); | ||
| 863 | |||
| 864 | rval = device_add(&nvmem->dev); | ||
| 865 | if (rval) | ||
| 866 | goto err_remove_cells; | ||
| 867 | |||
| 870 | blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); | 868 | blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); |
| 871 | 869 | ||
| 872 | return nvmem; | 870 | return nvmem; |
| 873 | 871 | ||
| 874 | err_remove_cells: | 872 | err_remove_cells: |
| 875 | nvmem_device_remove_all_cells(nvmem); | 873 | nvmem_device_remove_all_cells(nvmem); |
| 876 | err_teardown_compat: | ||
| 877 | if (config->compat) | 874 | if (config->compat) |
| 878 | nvmem_sysfs_remove_compat(nvmem, config); | 875 | nvmem_sysfs_remove_compat(nvmem, config); |
| 879 | err_device_del: | ||
| 880 | device_del(&nvmem->dev); | ||
| 881 | err_put_device: | 876 | err_put_device: |
| 882 | put_device(&nvmem->dev); | 877 | put_device(&nvmem->dev); |
| 883 | 878 | ||
| @@ -1242,16 +1237,21 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id) · 358 unmodified lines | |||
| 1242 | if (!cell_np) | 1237 | if (!cell_np) |
| 1243 | return ERR_PTR(-ENOENT); | 1238 | return ERR_PTR(-ENOENT); |
| 1244 | 1239 | ||
| 1245 | nvmem_np = of_get_next_parent(cell_np); | 1240 | nvmem_np = of_get_parent(cell_np); |
| 1246 | if (!nvmem_np) | 1241 | if (!nvmem_np) { |
| 1242 | of_node_put(cell_np); | ||
| 1247 | return ERR_PTR(-EINVAL); | 1243 | return ERR_PTR(-EINVAL); |
| 1244 | } | ||
| 1248 | 1245 | ||
| 1249 | nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); | 1246 | nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); |
| 1250 | of_node_put(nvmem_np); | 1247 | of_node_put(nvmem_np); |
| 1251 | if (IS_ERR(nvmem)) | 1248 | if (IS_ERR(nvmem)) { |
| 1249 | of_node_put(cell_np); | ||
| 1252 | return ERR_CAST(nvmem); | 1250 | return ERR_CAST(nvmem); |
| 1251 | } | ||
| 1253 | 1252 | ||
| 1254 | cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np); | 1253 | cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np); |
| 1254 | of_node_put(cell_np); | ||
| 1255 | if (!cell_entry) { | 1255 | if (!cell_entry) { |
| 1256 | __nvmem_device_put(nvmem); | 1256 | __nvmem_device_put(nvmem); |
| 1257 | return ERR_PTR(-ENOENT); | 1257 | return ERR_PTR(-ENOENT); |
| @@ -166,6 +166,7 @@ static const struct of_device_id sdam_match_table[] = { · 165 unmodified lines | |||
| 166 | { .compatible = "qcom,spmi-sdam" }, | 166 | { .compatible = "qcom,spmi-sdam" }, |
| 167 | {}, | 167 | {}, |
| 168 | }; | 168 | }; |
| 169 | MODULE_DEVICE_TABLE(of, sdam_match_table); | ||
| 169 | 170 | ||
| 170 | static struct platform_driver sdam_driver = { | 171 | static struct platform_driver sdam_driver = { |
| 171 | .driver = { | 172 | .driver = { |
| @@ -41,8 +41,21 @@ static int sunxi_sid_read(void *context, unsigned int offset, · 40 unmodified lines | |||
| 41 | void *val, size_t bytes) | 41 | void *val, size_t bytes) |
| 42 | { | 42 | { |
| 43 | struct sunxi_sid *sid = context; | 43 | struct sunxi_sid *sid = context; |
| 44 | u32 word; | ||
| 45 | |||
| 46 | /* .stride = 4 so offset is guaranteed to be aligned */ | ||
| 47 | __ioread32_copy(val, sid->base + sid->value_offset + offset, bytes / 4); | ||
| 44 | 48 | ||
| 45 | memcpy_fromio(val, sid->base + sid->value_offset + offset, bytes); | 49 | val += round_down(bytes, 4); |
| 50 | offset += round_down(bytes, 4); | ||
| 51 | bytes = bytes % 4; | ||
| 52 | |||
| 53 | if (!bytes) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | /* Handle any trailing bytes */ | ||
| 57 | word = readl_relaxed(sid->base + sid->value_offset + offset); | ||
| 58 | memcpy(val, &word, bytes); | ||
| 46 | 59 | ||
| 47 | return 0; | 60 | return 0; |
| 48 | } | 61 | } |
| @@ -965,8 +965,19 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) · 964 unmodified lines | |||
| 965 | } | 965 | } |
| 966 | 966 | ||
| 967 | of_dma_range_parser_init(&parser, node); | 967 | of_dma_range_parser_init(&parser, node); |
| 968 | for_each_of_range(&parser, &range) | 968 | for_each_of_range(&parser, &range) { |
| 969 | if (range.cpu_addr == OF_BAD_ADDR) { | ||
| 970 | pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", | ||
| 971 | range.bus_addr, node); | ||
| 972 | continue; | ||
| 973 | } | ||
| 969 | num_ranges++; | 974 | num_ranges++; |
| 975 | } | ||
| 976 | |||
| 977 | if (!num_ranges) { | ||
| 978 | ret = -EINVAL; | ||
| 979 | goto out; | ||
| 980 | } | ||
| 970 | 981 | ||
| 971 | r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL); | 982 | r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL); |
| 972 | if (!r) { | 983 | if (!r) { |
| @@ -975,18 +986,16 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) · 2 unmodified lines | |||
| 975 | } | 986 | } |
| 976 | 987 | ||
| 977 | /* | 988 | /* |
| 978 | * Record all info in the generic DMA ranges array for struct device. | 989 | * Record all info in the generic DMA ranges array for struct device, |
| 990 | * returning an error if we don't find any parsable ranges. | ||
| 979 | */ | 991 | */ |
| 980 | *map = r; | 992 | *map = r; |
| 981 | of_dma_range_parser_init(&parser, node); | 993 | of_dma_range_parser_init(&parser, node); |
| 982 | for_each_of_range(&parser, &range) { | 994 | for_each_of_range(&parser, &range) { |
| 983 | pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", | 995 | pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", |
| 984 | range.bus_addr, range.cpu_addr, range.size); | 996 | range.bus_addr, range.cpu_addr, range.size); |
| 985 | if (range.cpu_addr == OF_BAD_ADDR) { | 997 | if (range.cpu_addr == OF_BAD_ADDR) |
| 986 | pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", | ||
| 987 | range.bus_addr, node); | ||
| 988 | continue; | 998 | continue; |
| 989 | } | ||
| 990 | r->cpu_start = range.cpu_addr; | 999 | r->cpu_start = range.cpu_addr; |
| 991 | r->dma_start = range.bus_addr; | 1000 | r->dma_start = range.bus_addr; |
| 992 | r->size = range.size; | 1001 | r->size = range.size; |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | |||
| 26 | #include <linux/serial_core.h> | 26 | #include <linux/serial_core.h> |
| 27 | #include <linux/sysfs.h> | 27 | #include <linux/sysfs.h> |
| 28 | #include <linux/random.h> | 28 | #include <linux/random.h> |
| 29 | #include <linux/kmemleak.h> | ||
| 30 | 29 | ||
| 31 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ | 30 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
| 32 | #include <asm/page.h> | 31 | #include <asm/page.h> |
| @@ -525,12 +524,9 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, · 492 unmodified lines | |||
| 525 | size = dt_mem_next_cell(dt_root_size_cells, &prop); | 524 | size = dt_mem_next_cell(dt_root_size_cells, &prop); |
| 526 | 525 | ||
| 527 | if (size && | 526 | if (size && |
| 528 | early_init_dt_reserve_memory(base, size, nomap) == 0) { | 527 | early_init_dt_reserve_memory(base, size, nomap) == 0) |
| 529 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", | 528 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", |
| 530 | uname, &base, (unsigned long)(size / SZ_1M)); | 529 | uname, &base, (unsigned long)(size / SZ_1M)); |
| 531 | if (!nomap) | ||
| 532 | kmemleak_alloc_phys(base, size, 0); | ||
| 533 | } | ||
| 534 | else | 530 | else |
| 535 | pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", | 531 | pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", |
| 536 | uname, &base, (unsigned long)(size / SZ_1M)); | 532 | uname, &base, (unsigned long)(size / SZ_1M)); |
| @@ -525,6 +525,7 @@ static int __init of_platform_default_populate_init(void) · 524 unmodified lines | |||
| 525 | if (IS_ENABLED(CONFIG_PPC)) { | 525 | if (IS_ENABLED(CONFIG_PPC)) { |
| 526 | struct device_node *boot_display = NULL; | 526 | struct device_node *boot_display = NULL; |
| 527 | struct platform_device *dev; | 527 | struct platform_device *dev; |
| 528 | int display_number = 0; | ||
| 528 | int ret; | 529 | int ret; |
| 529 | 530 | ||
| 530 | /* Check if we have a MacOS display without a node spec */ | 531 | /* Check if we have a MacOS display without a node spec */ |
| @@ -555,16 +556,23 @@ static int __init of_platform_default_populate_init(void) · 24 unmodified lines | |||
| 555 | if (!of_get_property(node, "linux,opened", NULL) || | 556 | if (!of_get_property(node, "linux,opened", NULL) || |
| 556 | !of_get_property(node, "linux,boot-display", NULL)) | 557 | !of_get_property(node, "linux,boot-display", NULL)) |
| 557 | continue; | 558 | continue; |
| 558 | dev = of_platform_device_create(node, "of-display", NULL); | 559 | dev = of_platform_device_create(node, "of-display.0", NULL); |
| 560 | of_node_put(node); | ||
| 559 | if (WARN_ON(!dev)) | 561 | if (WARN_ON(!dev)) |
| 560 | return -ENOMEM; | 562 | return -ENOMEM; |
| 561 | boot_display = node; | 563 | boot_display = node; |
| 564 | display_number++; | ||
| 562 | break; | 565 | break; |
| 563 | } | 566 | } |
| 564 | for_each_node_by_type(node, "display") { | 567 | for_each_node_by_type(node, "display") { |
| 568 | char buf[14]; | ||
| 569 | const char *of_display_format = "of-display.%d"; | ||
| 570 | |||
| 565 | if (!of_get_property(node, "linux,opened", NULL) || node == boot_display) | 571 | if (!of_get_property(node, "linux,opened", NULL) || node == boot_display) |
| 566 | continue; | 572 | continue; |
| 567 | of_platform_device_create(node, "of-display", NULL); | 573 | ret = snprintf(buf, sizeof(buf), of_display_format, display_number++); |
| 574 | if (ret < sizeof(buf)) | ||
| 575 | of_platform_device_create(node, buf, NULL); | ||
| 568 | } | 576 | } |
| 569 | 577 | ||
| 570 | } else { | 578 | } else { |
| @@ -274,8 +274,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun · 273 unmodified lines | |||
| 274 | 274 | ||
| 275 | /* We'll use a local copy of buf */ | 275 | /* We'll use a local copy of buf */ |
| 276 | count = min_t(size_t, count, sizeof(in)-1); | 276 | count = min_t(size_t, count, sizeof(in)-1); |
| 277 | strncpy(in, buf, count); | 277 | strscpy(in, buf, count + 1); |
| 278 | in[count] = '\0'; | ||
| 279 | 278 | ||
| 280 | /* Let's clean up the target. 0xff is a blank pattern */ | 279 | /* Let's clean up the target. 0xff is a blank pattern */ |
| 281 | memset(&hwpath, 0xff, sizeof(hwpath)); | 280 | memset(&hwpath, 0xff, sizeof(hwpath)); |
| @@ -388,8 +387,7 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count · 106 unmodified lines | |||
| 388 | 387 | ||
| 389 | /* We'll use a local copy of buf */ | 388 | /* We'll use a local copy of buf */ |
| 390 | count = min_t(size_t, count, sizeof(in)-1); | 389 | count = min_t(size_t, count, sizeof(in)-1); |
| 391 | strncpy(in, buf, count); | 390 | strscpy(in, buf, count + 1); |
| 392 | in[count] = '\0'; | ||
| 393 | 391 | ||
| 394 | /* Let's clean up the target. 0 is a blank pattern */ | 392 | /* Let's clean up the target. 0 is a blank pattern */ |
| 395 | memset(&layers, 0, sizeof(layers)); | 393 | memset(&layers, 0, sizeof(layers)); |
| @@ -756,8 +754,7 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, · 360 unmodified lines | |||
| 756 | 754 | ||
| 757 | /* We'll use a local copy of buf */ | 755 | /* We'll use a local copy of buf */ |
| 758 | count = min_t(size_t, count, sizeof(in)-1); | 756 | count = min_t(size_t, count, sizeof(in)-1); |
| 759 | strncpy(in, buf, count); | 757 | strscpy(in, buf, count + 1); |
| 760 | in[count] = '\0'; | ||
| 761 | 758 | ||
| 762 | /* Current flags are stored in primary boot path entry */ | 759 | /* Current flags are stored in primary boot path entry */ |
| 763 | pathentry = &pdcspath_entry_primary; | 760 | pathentry = &pdcspath_entry_primary; |
| @@ -188,9 +188,10 @@ static int efi_set_time(struct device *dev, struct rtc_time *tm) · 187 unmodified lines | |||
| 188 | 188 | ||
| 189 | static int efi_procfs(struct device *dev, struct seq_file *seq) | 189 | static int efi_procfs(struct device *dev, struct seq_file *seq) |
| 190 | { | 190 | { |
| 191 | efi_time_t eft, alm; | 191 | efi_time_t eft, alm; |
| 192 | efi_time_cap_t cap; | 192 | efi_time_cap_t cap; |
| 193 | efi_bool_t enabled, pending; | 193 | efi_bool_t enabled, pending; |
| 194 | struct rtc_device *rtc = dev_get_drvdata(dev); | ||
| 194 | 195 | ||
| 195 | memset(&eft, 0, sizeof(eft)); | 196 | memset(&eft, 0, sizeof(eft)); |
| 196 | memset(&alm, 0, sizeof(alm)); | 197 | memset(&alm, 0, sizeof(alm)); |
| @@ -213,23 +214,25 @@ static int efi_procfs(struct device *dev, struct seq_file *seq) · 16 unmodified lines | |||
| 213 | /* XXX fixme: convert to string? */ | 214 | /* XXX fixme: convert to string? */ |
| 214 | seq_printf(seq, "Timezone\t: %u\n", eft.timezone); | 215 | seq_printf(seq, "Timezone\t: %u\n", eft.timezone); |
| 215 | 216 | ||
| 216 | seq_printf(seq, | 217 | if (test_bit(RTC_FEATURE_ALARM, rtc->features)) { |
| 217 | "Alarm Time\t: %u:%u:%u.%09u\n" | 218 | seq_printf(seq, |
| 218 | "Alarm Date\t: %u-%u-%u\n" | 219 | "Alarm Time\t: %u:%u:%u.%09u\n" |
| 219 | "Alarm Daylight\t: %u\n" | 220 | "Alarm Date\t: %u-%u-%u\n" |
| 220 | "Enabled\t\t: %s\n" | 221 | "Alarm Daylight\t: %u\n" |
| 221 | "Pending\t\t: %s\n", | 222 | "Enabled\t\t: %s\n" |
| 222 | alm.hour, alm.minute, alm.second, alm.nanosecond, | 223 | "Pending\t\t: %s\n", |
| 223 | alm.year, alm.month, alm.day, | 224 | alm.hour, alm.minute, alm.second, alm.nanosecond, |
| 224 | alm.daylight, | 225 | alm.year, alm.month, alm.day, |
| 225 | enabled == 1 ? "yes" : "no", | 226 | alm.daylight, |
| 226 | pending == 1 ? "yes" : "no"); | 227 | enabled == 1 ? "yes" : "no", |
| 227 | 228 | pending == 1 ? "yes" : "no"); | |
| 228 | if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE) | 229 | |
| 229 | seq_puts(seq, "Timezone\t: unspecified\n"); | 230 | if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE) |
| 230 | else | 231 | seq_puts(seq, "Timezone\t: unspecified\n"); |
| 231 | /* XXX fixme: convert to string? */ | 232 | else |
| 232 | seq_printf(seq, "Timezone\t: %u\n", alm.timezone); | 233 | /* XXX fixme: convert to string? */ |
| 234 | seq_printf(seq, "Timezone\t: %u\n", alm.timezone); | ||
| 235 | } | ||
| 233 | 236 | ||
| 234 | /* | 237 | /* |
| 235 | * now prints the capabilities | 238 | * now prints the capabilities |
| @@ -269,7 +272,10 @@ static int __init efi_rtc_probe(struct platform_device *dev) · 33 unmodified lines | |||
| 269 | 272 | ||
| 270 | rtc->ops = &efi_rtc_ops; | 273 | rtc->ops = &efi_rtc_ops; |
| 271 | clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); | 274 | clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); |
| 272 | set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features); | 275 | if (efi_rt_services_supported(EFI_RT_SUPPORTED_WAKEUP_SERVICES)) |
| 276 | set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features); | ||
| 277 | else | ||
| 278 | clear_bit(RTC_FEATURE_ALARM, rtc->features); | ||
| 273 | 279 | ||
| 274 | device_init_wakeup(&dev->dev, true); | 280 | device_init_wakeup(&dev->dev, true); |
| 275 | 281 | ||
| @@ -240,8 +240,8 @@ static int sp_rtc_probe(struct platform_device *plat_dev) · 239 unmodified lines | |||
| 240 | if (IS_ERR(sp_rtc->reg_base)) | 240 | if (IS_ERR(sp_rtc->reg_base)) |
| 241 | return dev_err_probe(&plat_dev->dev, PTR_ERR(sp_rtc->reg_base), | 241 | return dev_err_probe(&plat_dev->dev, PTR_ERR(sp_rtc->reg_base), |
| 242 | "%s devm_ioremap_resource fail\n", RTC_REG_NAME); | 242 | "%s devm_ioremap_resource fail\n", RTC_REG_NAME); |
| 243 | dev_dbg(&plat_dev->dev, "res = 0x%x, reg_base = 0x%lx\n", | 243 | dev_dbg(&plat_dev->dev, "res = %pR, reg_base = %p\n", |
| 244 | sp_rtc->res->start, (unsigned long)sp_rtc->reg_base); | 244 | sp_rtc->res, sp_rtc->reg_base); |
| 245 | 245 | ||
| 246 | sp_rtc->irq = platform_get_irq(plat_dev, 0); | 246 | sp_rtc->irq = platform_get_irq(plat_dev, 0); |
| 247 | if (sp_rtc->irq < 0) | 247 | if (sp_rtc->irq < 0) |
| @@ -43,15 +43,23 @@ static void __dma_rx_complete(struct uart_8250_port *p) · 42 unmodified lines | |||
| 43 | struct uart_8250_dma *dma = p->dma; | 43 | struct uart_8250_dma *dma = p->dma; |
| 44 | struct tty_port *tty_port = &p->port.state->port; | 44 | struct tty_port *tty_port = &p->port.state->port; |
| 45 | struct dma_tx_state state; | 45 | struct dma_tx_state state; |
| 46 | enum dma_status dma_status; | ||
| 46 | int count; | 47 | int count; |
| 47 | 48 | ||
| 48 | dma->rx_running = 0; | 49 | /* |
| 49 | dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); | 50 | * New DMA Rx can be started during the completion handler before it |
| 51 | * could acquire port's lock and it might still be ongoing. Don't to | ||
| 52 | * anything in such case. | ||
| 53 | */ | ||
| 54 | dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); | ||
| 55 | if (dma_status == DMA_IN_PROGRESS) | ||
| 56 | return; | ||
| 50 | 57 | ||
| 51 | count = dma->rx_size - state.residue; | 58 | count = dma->rx_size - state.residue; |
| 52 | 59 | ||
| 53 | tty_insert_flip_string(tty_port, dma->rx_buf, count); | 60 | tty_insert_flip_string(tty_port, dma->rx_buf, count); |
| 54 | p->port.icount.rx += count; | 61 | p->port.icount.rx += count; |
| 62 | dma->rx_running = 0; | ||
| 55 | 63 | ||
| 56 | tty_flip_buffer_push(tty_port); | 64 | tty_flip_buffer_push(tty_port); |
| 57 | } | 65 | } |
| @@ -62,9 +70,14 @@ static void dma_rx_complete(void *param) · 4 unmodified lines | |||
| 62 | struct uart_8250_dma *dma = p->dma; | 70 | struct uart_8250_dma *dma = p->dma; |
| 63 | unsigned long flags; | 71 | unsigned long flags; |
| 64 | 72 | ||
| 65 | __dma_rx_complete(p); | ||
| 66 | |||
| 67 | spin_lock_irqsave(&p->port.lock, flags); | 73 | spin_lock_irqsave(&p->port.lock, flags); |
| 74 | if (dma->rx_running) | ||
| 75 | __dma_rx_complete(p); | ||
| 76 | |||
| 77 | /* | ||
| 78 | * Cannot be combined with the previous check because __dma_rx_complete() | ||
| 79 | * changes dma->rx_running. | ||
| 80 | */ | ||
| 68 | if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR)) | 81 | if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR)) |
| 69 | p->dma->rx_dma(p); | 82 | p->dma->rx_dma(p); |
| 70 | spin_unlock_irqrestore(&p->port.lock, flags); | 83 | spin_unlock_irqrestore(&p->port.lock, flags); |
| @@ -797,25 +797,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) · 796 unmodified lines | |||
| 797 | spin_unlock(&port->lock); | 797 | spin_unlock(&port->lock); |
| 798 | } | 798 | } |
| 799 | 799 | ||
| 800 | if (stm32_usart_rx_dma_enabled(port)) | ||
| 801 | return IRQ_WAKE_THREAD; | ||
| 802 | else | ||
| 803 | return IRQ_HANDLED; | ||
| 804 | } | ||
| 805 | |||
| 806 | static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr) | ||
| 807 | { | ||
| 808 | struct uart_port *port = ptr; | ||
| 809 | struct tty_port *tport = &port->state->port; | ||
| 810 | struct stm32_port *stm32_port = to_stm32_port(port); | ||
| 811 | unsigned int size; | ||
| 812 | unsigned long flags; | ||
| 813 | |||
| 814 | /* Receiver timeout irq for DMA RX */ | 800 | /* Receiver timeout irq for DMA RX */ |
| 815 | if (!stm32_port->throttled) { | 801 | if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) { |
| 816 | spin_lock_irqsave(&port->lock, flags); | 802 | spin_lock(&port->lock); |
| 817 | size = stm32_usart_receive_chars(port, false); | 803 | size = stm32_usart_receive_chars(port, false); |
| 818 | uart_unlock_and_check_sysrq_irqrestore(port, flags); | 804 | uart_unlock_and_check_sysrq(port); |
| 819 | if (size) | 805 | if (size) |
| 820 | tty_flip_buffer_push(tport); | 806 | tty_flip_buffer_push(tport); |
| 821 | } | 807 | } |
| @@ -1015,10 +1001,8 @@ static int stm32_usart_startup(struct uart_port *port) · 193 unmodified lines | |||
| 1015 | u32 val; | 1001 | u32 val; |
| 1016 | int ret; | 1002 | int ret; |
| 1017 | 1003 | ||
| 1018 | ret = request_threaded_irq(port->irq, stm32_usart_interrupt, | 1004 | ret = request_irq(port->irq, stm32_usart_interrupt, |
| 1019 | stm32_usart_threaded_interrupt, | 1005 | IRQF_NO_SUSPEND, name, port); |
| 1020 | IRQF_ONESHOT | IRQF_NO_SUSPEND, | ||
| 1021 | name, port); | ||
| 1022 | if (ret) | 1006 | if (ret) |
| 1023 | return ret; | 1007 | return ret; |
| 1024 | 1008 | ||
| @@ -1601,13 +1585,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, · 576 unmodified lines | |||
| 1601 | struct dma_slave_config config; | 1585 | struct dma_slave_config config; |
| 1602 | int ret; | 1586 | int ret; |
| 1603 | 1587 | ||
| 1604 | /* | ||
| 1605 | * Using DMA and threaded handler for the console could lead to | ||
| 1606 | * deadlocks. | ||
| 1607 | */ | ||
| 1608 | if (uart_console(port)) | ||
| 1609 | return -ENODEV; | ||
| 1610 | |||
| 1611 | stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L, | 1588 | stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L, |
| 1612 | &stm32port->rx_dma_buf, | 1589 | &stm32port->rx_dma_buf, |
| 1613 | GFP_KERNEL); | 1590 | GFP_KERNEL); |
| @@ -386,10 +386,6 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) · 385 unmodified lines | |||
| 386 | 386 | ||
| 387 | uni_mode = use_unicode(inode); | 387 | uni_mode = use_unicode(inode); |
| 388 | attr = use_attributes(inode); | 388 | attr = use_attributes(inode); |
| 389 | ret = -ENXIO; | ||
| 390 | vc = vcs_vc(inode, &viewed); | ||
| 391 | if (!vc) | ||
| 392 | goto unlock_out; | ||
| 393 | 389 | ||
| 394 | ret = -EINVAL; | 390 | ret = -EINVAL; |
| 395 | if (pos < 0) | 391 | if (pos < 0) |
| @@ -407,6 +403,11 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) · 11 unmodified lines | |||
| 407 | unsigned int this_round, skip = 0; | 403 | unsigned int this_round, skip = 0; |
| 408 | int size; | 404 | int size; |
| 409 | 405 | ||
| 406 | ret = -ENXIO; | ||
| 407 | vc = vcs_vc(inode, &viewed); | ||
| 408 | if (!vc) | ||
| 409 | goto unlock_out; | ||
| 410 | |||
| 410 | /* Check whether we are above size each round, | 411 | /* Check whether we are above size each round, |
| 411 | * as copy_to_user at the end of this loop | 412 | * as copy_to_user at the end of this loop |
| 412 | * could sleep. | 413 | * could sleep. |
| @@ -901,7 +901,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 900 unmodified lines | |||
| 901 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); | 901 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); |
| 902 | 902 | ||
| 903 | /* enable vbus override for device mode */ | 903 | /* enable vbus override for device mode */ |
| 904 | if (qcom->mode == USB_DR_MODE_PERIPHERAL) | 904 | if (qcom->mode != USB_DR_MODE_HOST) |
| 905 | dwc3_qcom_vbus_override_enable(qcom, true); | 905 | dwc3_qcom_vbus_override_enable(qcom, true); |
| 906 | 906 | ||
| 907 | /* register extcon to override sw_vbus on Vbus change later */ | 907 | /* register extcon to override sw_vbus on Vbus change later */ |
| @@ -1014,7 +1014,6 @@ static int fotg210_udc_start(struct usb_gadget *g, · 1013 unmodified lines | |||
| 1014 | int ret; | 1014 | int ret; |
| 1015 | 1015 | ||
| 1016 | /* hook up the driver */ | 1016 | /* hook up the driver */ |
| 1017 | driver->driver.bus = NULL; | ||
| 1018 | fotg210->driver = driver; | 1017 | fotg210->driver = driver; |
| 1019 | 1018 | ||
| 1020 | if (!IS_ERR_OR_NULL(fotg210->phy)) { | 1019 | if (!IS_ERR_OR_NULL(fotg210->phy)) { |
| @@ -279,8 +279,10 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) · 278 unmodified lines | |||
| 279 | struct usb_request *req = ffs->ep0req; | 279 | struct usb_request *req = ffs->ep0req; |
| 280 | int ret; | 280 | int ret; |
| 281 | 281 | ||
| 282 | if (!req) | 282 | if (!req) { |
| 283 | spin_unlock_irq(&ffs->ev.waitq.lock); | ||
| 283 | return -EINVAL; | 284 | return -EINVAL; |
| 285 | } | ||
| 284 | 286 | ||
| 285 | req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); | 287 | req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); |
| 286 | 288 | ||
| @@ -1142,6 +1142,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) · 1141 unmodified lines | |||
| 1142 | } | 1142 | } |
| 1143 | std_as_out_if0_desc.bInterfaceNumber = ret; | 1143 | std_as_out_if0_desc.bInterfaceNumber = ret; |
| 1144 | std_as_out_if1_desc.bInterfaceNumber = ret; | 1144 | std_as_out_if1_desc.bInterfaceNumber = ret; |
| 1145 | std_as_out_if1_desc.bNumEndpoints = 1; | ||
| 1145 | uac2->as_out_intf = ret; | 1146 | uac2->as_out_intf = ret; |
| 1146 | uac2->as_out_alt = 0; | 1147 | uac2->as_out_alt = 0; |
| 1147 | 1148 | ||
| @@ -1830,7 +1830,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget, · 1829 unmodified lines | |||
| 1830 | bcm63xx_select_phy_mode(udc, true); | 1830 | bcm63xx_select_phy_mode(udc, true); |
| 1831 | 1831 | ||
| 1832 | udc->driver = driver; | 1832 | udc->driver = driver; |
| 1833 | driver->driver.bus = NULL; | ||
| 1834 | udc->gadget.dev.of_node = udc->dev->of_node; | 1833 | udc->gadget.dev.of_node = udc->dev->of_node; |
| 1835 | 1834 | ||
| 1836 | spin_unlock_irqrestore(&udc->lock, flags); | 1835 | spin_unlock_irqrestore(&udc->lock, flags); |
| @@ -2285,7 +2285,6 @@ static int fsl_qe_start(struct usb_gadget *gadget, · 2284 unmodified lines | |||
| 2285 | /* lock is needed but whether should use this lock or another */ | 2285 | /* lock is needed but whether should use this lock or another */ |
| 2286 | spin_lock_irqsave(&udc->lock, flags); | 2286 | spin_lock_irqsave(&udc->lock, flags); |
| 2287 | 2287 | ||
| 2288 | driver->driver.bus = NULL; | ||
| 2289 | /* hook up the driver */ | 2288 | /* hook up the driver */ |
| 2290 | udc->driver = driver; | 2289 | udc->driver = driver; |
| 2291 | udc->gadget.speed = driver->max_speed; | 2290 | udc->gadget.speed = driver->max_speed; |
| @@ -1943,7 +1943,6 @@ static int fsl_udc_start(struct usb_gadget *g, · 1942 unmodified lines | |||
| 1943 | /* lock is needed but whether should use this lock or another */ | 1943 | /* lock is needed but whether should use this lock or another */ |
| 1944 | spin_lock_irqsave(&udc_controller->lock, flags); | 1944 | spin_lock_irqsave(&udc_controller->lock, flags); |
| 1945 | 1945 | ||
| 1946 | driver->driver.bus = NULL; | ||
| 1947 | /* hook up the driver */ | 1946 | /* hook up the driver */ |
| 1948 | udc_controller->driver = driver; | 1947 | udc_controller->driver = driver; |
| 1949 | spin_unlock_irqrestore(&udc_controller->lock, flags); | 1948 | spin_unlock_irqrestore(&udc_controller->lock, flags); |
| @@ -1311,7 +1311,6 @@ static int fusb300_udc_start(struct usb_gadget *g, · 1310 unmodified lines | |||
| 1311 | struct fusb300 *fusb300 = to_fusb300(g); | 1311 | struct fusb300 *fusb300 = to_fusb300(g); |
| 1312 | 1312 | ||
| 1313 | /* hook up the driver */ | 1313 | /* hook up the driver */ |
| 1314 | driver->driver.bus = NULL; | ||
| 1315 | fusb300->driver = driver; | 1314 | fusb300->driver = driver; |
| 1316 | 1315 | ||
| 1317 | return 0; | 1316 | return 0; |
| @@ -1375,7 +1375,6 @@ static int goku_udc_start(struct usb_gadget *g, · 1374 unmodified lines | |||
| 1375 | struct goku_udc *dev = to_goku_udc(g); | 1375 | struct goku_udc *dev = to_goku_udc(g); |
| 1376 | 1376 | ||
| 1377 | /* hook up the driver */ | 1377 | /* hook up the driver */ |
| 1378 | driver->driver.bus = NULL; | ||
| 1379 | dev->driver = driver; | 1378 | dev->driver = driver; |
| 1380 | 1379 | ||
| 1381 | /* | 1380 | /* |
| @@ -1906,7 +1906,6 @@ static int gr_udc_start(struct usb_gadget *gadget, · 1905 unmodified lines | |||
| 1906 | spin_lock(&dev->lock); | 1906 | spin_lock(&dev->lock); |
| 1907 | 1907 | ||
| 1908 | /* Hook up the driver */ | 1908 | /* Hook up the driver */ |
| 1909 | driver->driver.bus = NULL; | ||
| 1910 | dev->driver = driver; | 1909 | dev->driver = driver; |
| 1911 | 1910 | ||
| 1912 | /* Get ready for host detection */ | 1911 | /* Get ready for host detection */ |
| @@ -1454,7 +1454,6 @@ static int m66592_udc_start(struct usb_gadget *g, · 1453 unmodified lines | |||
| 1454 | struct m66592 *m66592 = to_m66592(g); | 1454 | struct m66592 *m66592 = to_m66592(g); |
| 1455 | 1455 | ||
| 1456 | /* hook up the driver */ | 1456 | /* hook up the driver */ |
| 1457 | driver->driver.bus = NULL; | ||
| 1458 | m66592->driver = driver; | 1457 | m66592->driver = driver; |
| 1459 | 1458 | ||
| 1460 | m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); | 1459 | m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); |
| @@ -1108,7 +1108,6 @@ static int max3420_udc_start(struct usb_gadget *gadget, · 1107 unmodified lines | |||
| 1108 | 1108 | ||
| 1109 | spin_lock_irqsave(&udc->lock, flags); | 1109 | spin_lock_irqsave(&udc->lock, flags); |
| 1110 | /* hook up the driver */ | 1110 | /* hook up the driver */ |
| 1111 | driver->driver.bus = NULL; | ||
| 1112 | udc->driver = driver; | 1111 | udc->driver = driver; |
| 1113 | udc->gadget.speed = USB_SPEED_FULL; | 1112 | udc->gadget.speed = USB_SPEED_FULL; |
| 1114 | 1113 | ||
| @@ -1243,7 +1243,6 @@ static int mv_u3d_start(struct usb_gadget *g, · 1242 unmodified lines | |||
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | /* hook up the driver ... */ | 1245 | /* hook up the driver ... */ |
| 1246 | driver->driver.bus = NULL; | ||
| 1247 | u3d->driver = driver; | 1246 | u3d->driver = driver; |
| 1248 | 1247 | ||
| 1249 | u3d->ep0_dir = USB_DIR_OUT; | 1248 | u3d->ep0_dir = USB_DIR_OUT; |
| @@ -1359,7 +1359,6 @@ static int mv_udc_start(struct usb_gadget *gadget, · 1358 unmodified lines | |||
| 1359 | spin_lock_irqsave(&udc->lock, flags); | 1359 | spin_lock_irqsave(&udc->lock, flags); |
| 1360 | 1360 | ||
| 1361 | /* hook up the driver ... */ | 1361 | /* hook up the driver ... */ |
| 1362 | driver->driver.bus = NULL; | ||
| 1363 | udc->driver = driver; | 1362 | udc->driver = driver; |
| 1364 | 1363 | ||
| 1365 | udc->usb_state = USB_STATE_ATTACHED; | 1364 | udc->usb_state = USB_STATE_ATTACHED; |
| @@ -1451,7 +1451,6 @@ static int net2272_start(struct usb_gadget *_gadget, · 1450 unmodified lines | |||
| 1451 | dev->ep[i].irqs = 0; | 1451 | dev->ep[i].irqs = 0; |
| 1452 | /* hook up the driver ... */ | 1452 | /* hook up the driver ... */ |
| 1453 | dev->softconnect = 1; | 1453 | dev->softconnect = 1; |
| 1454 | driver->driver.bus = NULL; | ||
| 1455 | dev->driver = driver; | 1454 | dev->driver = driver; |
| 1456 | 1455 | ||
| 1457 | /* ... then enable host detection and ep0; and we're ready | 1456 | /* ... then enable host detection and ep0; and we're ready |
| @@ -2423,7 +2423,6 @@ static int net2280_start(struct usb_gadget *_gadget, · 2422 unmodified lines | |||
| 2423 | dev->ep[i].irqs = 0; | 2423 | dev->ep[i].irqs = 0; |
| 2424 | 2424 | ||
| 2425 | /* hook up the driver ... */ | 2425 | /* hook up the driver ... */ |
| 2426 | driver->driver.bus = NULL; | ||
| 2427 | dev->driver = driver; | 2426 | dev->driver = driver; |
| 2428 | 2427 | ||
| 2429 | retval = device_create_file(&dev->pdev->dev, &dev_attr_function); | 2428 | retval = device_create_file(&dev->pdev->dev, &dev_attr_function); |
| @@ -2066,7 +2066,6 @@ static int omap_udc_start(struct usb_gadget *g, · 2065 unmodified lines | |||
| 2066 | udc->softconnect = 1; | 2066 | udc->softconnect = 1; |
| 2067 | 2067 | ||
| 2068 | /* hook up the driver */ | 2068 | /* hook up the driver */ |
| 2069 | driver->driver.bus = NULL; | ||
| 2070 | udc->driver = driver; | 2069 | udc->driver = driver; |
| 2071 | spin_unlock_irqrestore(&udc->lock, flags); | 2070 | spin_unlock_irqrestore(&udc->lock, flags); |
| 2072 | 2071 | ||
| @@ -2908,7 +2908,6 @@ static int pch_udc_start(struct usb_gadget *g, · 2907 unmodified lines | |||
| 2908 | { | 2908 | { |
| 2909 | struct pch_udc_dev *dev = to_pch_udc(g); | 2909 | struct pch_udc_dev *dev = to_pch_udc(g); |
| 2910 | 2910 | ||
| 2911 | driver->driver.bus = NULL; | ||
| 2912 | dev->driver = driver; | 2911 | dev->driver = driver; |
| 2913 | 2912 | ||
| 2914 | /* get ready for ep0 traffic */ | 2913 | /* get ready for ep0 traffic */ |
| @@ -1933,7 +1933,6 @@ static int amd5536_udc_start(struct usb_gadget *g, · 1932 unmodified lines | |||
| 1933 | struct udc *dev = to_amd5536_udc(g); | 1933 | struct udc *dev = to_amd5536_udc(g); |
| 1934 | u32 tmp; | 1934 | u32 tmp; |
| 1935 | 1935 | ||
| 1936 | driver->driver.bus = NULL; | ||
| 1937 | dev->driver = driver; | 1936 | dev->driver = driver; |
| 1938 | 1937 | ||
| 1939 | /* Some gadget drivers use both ep0 directions. | 1938 | /* Some gadget drivers use both ep0 directions. |
| @@ -1269,6 +1269,9 @@ err_unregister: · 1268 unmodified lines | |||
| 1269 | con->port = NULL; | 1269 | con->port = NULL; |
| 1270 | } | 1270 | } |
| 1271 | 1271 | ||
| 1272 | kfree(ucsi->connector); | ||
| 1273 | ucsi->connector = NULL; | ||
| 1274 | |||
| 1272 | err_reset: | 1275 | err_reset: |
| 1273 | memset(&ucsi->cap, 0, sizeof(ucsi->cap)); | 1276 | memset(&ucsi->cap, 0, sizeof(ucsi->cap)); |
| 1274 | ucsi_reset_ppm(ucsi); | 1277 | ucsi_reset_ppm(ucsi); |
| @@ -1300,7 +1303,8 @@ static void ucsi_resume_work(struct work_struct *work) · 25 unmodified lines | |||
| 1300 | 1303 | ||
| 1301 | int ucsi_resume(struct ucsi *ucsi) | 1304 | int ucsi_resume(struct ucsi *ucsi) |
| 1302 | { | 1305 | { |
| 1303 | queue_work(system_long_wq, &ucsi->resume_work); | 1306 | if (ucsi->connector) |
| 1307 | queue_work(system_long_wq, &ucsi->resume_work); | ||
| 1304 | return 0; | 1308 | return 0; |
| 1305 | } | 1309 | } |
| 1306 | EXPORT_SYMBOL_GPL(ucsi_resume); | 1310 | EXPORT_SYMBOL_GPL(ucsi_resume); |
| @@ -1420,6 +1424,9 @@ void ucsi_unregister(struct ucsi *ucsi) · 113 unmodified lines | |||
| 1420 | /* Disable notifications */ | 1424 | /* Disable notifications */ |
| 1421 | ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); | 1425 | ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
| 1422 | 1426 | ||
| 1427 | if (!ucsi->connector) | ||
| 1428 | return; | ||
| 1429 | |||
| 1423 | for (i = 0; i < ucsi->cap.num_connectors; i++) { | 1430 | for (i = 0; i < ucsi->cap.num_connectors; i++) { |
| 1424 | cancel_work_sync(&ucsi->connector[i].work); | 1431 | cancel_work_sync(&ucsi->connector[i].work); |
| 1425 | ucsi_unregister_partner(&ucsi->connector[i]); | 1432 | ucsi_unregister_partner(&ucsi->connector[i]); |
| @@ -49,7 +49,6 @@ struct atmel_lcdfb_info { · 48 unmodified lines | |||
| 49 | struct clk *lcdc_clk; | 49 | struct clk *lcdc_clk; |
| 50 | 50 | ||
| 51 | struct backlight_device *backlight; | 51 | struct backlight_device *backlight; |
| 52 | u8 bl_power; | ||
| 53 | u8 saved_lcdcon; | 52 | u8 saved_lcdcon; |
| 54 | 53 | ||
| 55 | u32 pseudo_palette[16]; | 54 | u32 pseudo_palette[16]; |
| @@ -109,22 +108,7 @@ static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 · 53 unmodified lines | |||
| 109 | static int atmel_bl_update_status(struct backlight_device *bl) | 108 | static int atmel_bl_update_status(struct backlight_device *bl) |
| 110 | { | 109 | { |
| 111 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | 110 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); |
| 112 | int power = sinfo->bl_power; | 111 | int brightness = backlight_get_brightness(bl); |
| 113 | int brightness = bl->props.brightness; | ||
| 114 | |||
| 115 | /* REVISIT there may be a meaningful difference between | ||
| 116 | * fb_blank and power ... there seem to be some cases | ||
| 117 | * this doesn't handle correctly. | ||
| 118 | */ | ||
| 119 | if (bl->props.fb_blank != sinfo->bl_power) | ||
| 120 | power = bl->props.fb_blank; | ||
| 121 | else if (bl->props.power != sinfo->bl_power) | ||
| 122 | power = bl->props.power; | ||
| 123 | |||
| 124 | if (brightness < 0 && power == FB_BLANK_UNBLANK) | ||
| 125 | brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
| 126 | else if (power != FB_BLANK_UNBLANK) | ||
| 127 | brightness = 0; | ||
| 128 | 112 | ||
| 129 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); | 113 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); |
| 130 | if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE) | 114 | if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE) |
| @@ -133,8 +117,6 @@ static int atmel_bl_update_status(struct backlight_device *bl) · 2 unmodified lines | |||
| 133 | else | 117 | else |
| 134 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); | 118 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); |
| 135 | 119 | ||
| 136 | bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; | ||
| 137 | |||
| 138 | return 0; | 120 | return 0; |
| 139 | } | 121 | } |
| 140 | 122 | ||
| @@ -155,8 +137,6 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) · 14 unmodified lines | |||
| 155 | struct backlight_properties props; | 137 | struct backlight_properties props; |
| 156 | struct backlight_device *bl; | 138 | struct backlight_device *bl; |
| 157 | 139 | ||
| 158 | sinfo->bl_power = FB_BLANK_UNBLANK; | ||
| 159 | |||
| 160 | if (sinfo->backlight) | 140 | if (sinfo->backlight) |
| 161 | return; | 141 | return; |
| 162 | 142 | ||
| @@ -1766,12 +1766,10 @@ static int aty128_bl_update_status(struct backlight_device *bd) · 1765 unmodified lines | |||
| 1766 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); | 1766 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1767 | int level; | 1767 | int level; |
| 1768 | 1768 | ||
| 1769 | if (bd->props.power != FB_BLANK_UNBLANK || | 1769 | if (!par->lcd_on) |
| 1770 | bd->props.fb_blank != FB_BLANK_UNBLANK || | ||
| 1771 | !par->lcd_on) | ||
| 1772 | level = 0; | 1770 | level = 0; |
| 1773 | else | 1771 | else |
| 1774 | level = bd->props.brightness; | 1772 | level = backlight_get_brightness(bd); |
| 1775 | 1773 | ||
| 1776 | reg |= LVDS_BL_MOD_EN | LVDS_BLON; | 1774 | reg |= LVDS_BL_MOD_EN | LVDS_BLON; |
| 1777 | if (level > 0) { | 1775 | if (level > 0) { |
| @@ -2219,13 +2219,7 @@ static int aty_bl_update_status(struct backlight_device *bd) · 2218 unmodified lines | |||
| 2219 | { | 2219 | { |
| 2220 | struct atyfb_par *par = bl_get_data(bd); | 2220 | struct atyfb_par *par = bl_get_data(bd); |
| 2221 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); | 2221 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); |
| 2222 | int level; | 2222 | int level = backlight_get_brightness(bd); |
| 2223 | |||
| 2224 | if (bd->props.power != FB_BLANK_UNBLANK || | ||
| 2225 | bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 2226 | level = 0; | ||
| 2227 | else | ||
| 2228 | level = bd->props.brightness; | ||
| 2229 | 2223 | ||
| 2230 | reg |= (BLMOD_EN | BIASMOD_EN); | 2224 | reg |= (BLMOD_EN | BIASMOD_EN); |
| 2231 | if (level > 0) { | 2225 | if (level > 0) { |
| @@ -57,11 +57,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) · 56 unmodified lines | |||
| 57 | * backlight. This provides some greater power saving and the display | 57 | * backlight. This provides some greater power saving and the display |
| 58 | * is useless without backlight anyway. | 58 | * is useless without backlight anyway. |
| 59 | */ | 59 | */ |
| 60 | if (bd->props.power != FB_BLANK_UNBLANK || | 60 | level = backlight_get_brightness(bd); |
| 61 | bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 62 | level = 0; | ||
| 63 | else | ||
| 64 | level = bd->props.brightness; | ||
| 65 | 61 | ||
| 66 | del_timer_sync(&rinfo->lvds_timer); | 62 | del_timer_sync(&rinfo->lvds_timer); |
| 67 | radeon_engine_idle(); | 63 | radeon_engine_idle(); |
| @@ -2495,9 +2495,12 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, · 2494 unmodified lines | |||
| 2495 | h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) | 2495 | h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) |
| 2496 | return -EINVAL; | 2496 | return -EINVAL; |
| 2497 | 2497 | ||
| 2498 | if (font->width > 32 || font->height > 32) | ||
| 2499 | return -EINVAL; | ||
| 2500 | |||
| 2498 | /* Make sure drawing engine can handle the font */ | 2501 | /* Make sure drawing engine can handle the font */ |
| 2499 | if (!(info->pixmap.blit_x & (1 << (font->width - 1))) || | 2502 | if (!(info->pixmap.blit_x & BIT(font->width - 1)) || |
| 2500 | !(info->pixmap.blit_y & (1 << (font->height - 1)))) | 2503 | !(info->pixmap.blit_y & BIT(font->height - 1))) |
| 2501 | return -EINVAL; | 2504 | return -EINVAL; |
| 2502 | 2505 | ||
| 2503 | /* Make sure driver can handle the font length */ | 2506 | /* Make sure driver can handle the font length */ |
| @@ -1050,7 +1050,7 @@ static u32 fb_get_vblank(u32 hfreq) · 1049 unmodified lines | |||
| 1050 | } | 1050 | } |
| 1051 | 1051 | ||
| 1052 | /** | 1052 | /** |
| 1053 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq | 1053 | * fb_get_hblank_by_hfreq - get horizontal blank time given hfreq |
| 1054 | * @hfreq: horizontal freq | 1054 | * @hfreq: horizontal freq |
| 1055 | * @xres: horizontal resolution in pixels | 1055 | * @xres: horizontal resolution in pixels |
| 1056 | * | 1056 | * |
| @@ -283,12 +283,7 @@ static int mx3fb_bl_get_brightness(struct backlight_device *bl) · 282 unmodified lines | |||
| 283 | static int mx3fb_bl_update_status(struct backlight_device *bl) | 283 | static int mx3fb_bl_update_status(struct backlight_device *bl) |
| 284 | { | 284 | { |
| 285 | struct mx3fb_data *fbd = bl_get_data(bl); | 285 | struct mx3fb_data *fbd = bl_get_data(bl); |
| 286 | int brightness = bl->props.brightness; | 286 | int brightness = backlight_get_brightness(bl); |
| 287 | |||
| 288 | if (bl->props.power != FB_BLANK_UNBLANK) | ||
| 289 | brightness = 0; | ||
| 290 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 291 | brightness = 0; | ||
| 292 | 287 | ||
| 293 | fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness; | 288 | fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness; |
| 294 | 289 | ||
| @@ -49,17 +49,11 @@ static int nvidia_bl_update_status(struct backlight_device *bd) · 48 unmodified lines | |||
| 49 | { | 49 | { |
| 50 | struct nvidia_par *par = bl_get_data(bd); | 50 | struct nvidia_par *par = bl_get_data(bd); |
| 51 | u32 tmp_pcrt, tmp_pmc, fpcontrol; | 51 | u32 tmp_pcrt, tmp_pmc, fpcontrol; |
| 52 | int level; | 52 | int level = backlight_get_brightness(bd); |
| 53 | 53 | ||
| 54 | if (!par->FlatPanel) | 54 | if (!par->FlatPanel) |
| 55 | return 0; | 55 | return 0; |
| 56 | 56 | ||
| 57 | if (bd->props.power != FB_BLANK_UNBLANK || | ||
| 58 | bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 59 | level = 0; | ||
| 60 | else | ||
| 61 | level = bd->props.brightness; | ||
| 62 | |||
| 63 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; | 57 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; |
| 64 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; | 58 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; |
| 65 | fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; | 59 | fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; |
| @@ -331,13 +331,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev) · 330 unmodified lines | |||
| 331 | struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); | 331 | struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); |
| 332 | struct omap_dss_device *in = ddata->in; | 332 | struct omap_dss_device *in = ddata->in; |
| 333 | int r; | 333 | int r; |
| 334 | int level; | 334 | int level = backlight_get_brightness(dev); |
| 335 | |||
| 336 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
| 337 | dev->props.power == FB_BLANK_UNBLANK) | ||
| 338 | level = dev->props.brightness; | ||
| 339 | else | ||
| 340 | level = 0; | ||
| 341 | 335 | ||
| 342 | dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level); | 336 | dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level); |
| 343 | 337 | ||
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #define DSS_SUBSYS_NAME "DISPLAY" | 10 | #define DSS_SUBSYS_NAME "DISPLAY" |
| 11 | 11 | ||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/kstrtox.h> | ||
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 15 | #include <linux/sysfs.h> | 16 | #include <linux/sysfs.h> |
| @@ -36,7 +37,7 @@ static ssize_t display_enabled_store(struct omap_dss_device *dssdev, · 20 unmodified lines | |||
| 36 | int r; | 37 | int r; |
| 37 | bool enable; | 38 | bool enable; |
| 38 | 39 | ||
| 39 | r = strtobool(buf, &enable); | 40 | r = kstrtobool(buf, &enable); |
| 40 | if (r) | 41 | if (r) |
| 41 | return r; | 42 | return r; |
| 42 | 43 | ||
| @@ -73,7 +74,7 @@ static ssize_t display_tear_store(struct omap_dss_device *dssdev, · 30 unmodified lines | |||
| 73 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | 74 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
| 74 | return -ENOENT; | 75 | return -ENOENT; |
| 75 | 76 | ||
| 76 | r = strtobool(buf, &te); | 77 | r = kstrtobool(buf, &te); |
| 77 | if (r) | 78 | if (r) |
| 78 | return r; | 79 | return r; |
| 79 | 80 | ||
| @@ -183,7 +184,7 @@ static ssize_t display_mirror_store(struct omap_dss_device *dssdev, · 103 unmodified lines | |||
| 183 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | 184 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
| 184 | return -ENOENT; | 185 | return -ENOENT; |
| 185 | 186 | ||
| 186 | r = strtobool(buf, &mirror); | 187 | r = kstrtobool(buf, &mirror); |
| 187 | if (r) | 188 | if (r) |
| 188 | return r; | 189 | return r; |
| 189 | 190 | ||
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #define DSS_SUBSYS_NAME "MANAGER" | 10 | #define DSS_SUBSYS_NAME "MANAGER" |
| 11 | 11 | ||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/kstrtox.h> | ||
| 13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| @@ -246,7 +247,7 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, · 230 unmodified lines | |||
| 246 | bool enable; | 247 | bool enable; |
| 247 | int r; | 248 | int r; |
| 248 | 249 | ||
| 249 | r = strtobool(buf, &enable); | 250 | r = kstrtobool(buf, &enable); |
| 250 | if (r) | 251 | if (r) |
| 251 | return r; | 252 | return r; |
| 252 | 253 | ||
| @@ -290,7 +291,7 @@ static ssize_t manager_alpha_blending_enabled_store( · 37 unmodified lines | |||
| 290 | if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) | 291 | if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
| 291 | return -ENODEV; | 292 | return -ENODEV; |
| 292 | 293 | ||
| 293 | r = strtobool(buf, &enable); | 294 | r = kstrtobool(buf, &enable); |
| 294 | if (r) | 295 | if (r) |
| 295 | return r; | 296 | return r; |
| 296 | 297 | ||
| @@ -329,7 +330,7 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, · 32 unmodified lines | |||
| 329 | if (!dss_has_feature(FEAT_CPR)) | 330 | if (!dss_has_feature(FEAT_CPR)) |
| 330 | return -ENODEV; | 331 | return -ENODEV; |
| 331 | 332 | ||
| 332 | r = strtobool(buf, &enable); | 333 | r = kstrtobool(buf, &enable); |
| 333 | if (r) | 334 | if (r) |
| 334 | return r; | 335 | return r; |
| 335 | 336 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/sysfs.h> | 14 | #include <linux/sysfs.h> |
| 15 | #include <linux/kobject.h> | 15 | #include <linux/kobject.h> |
| 16 | #include <linux/kstrtox.h> | ||
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | 18 | ||
| 18 | #include <video/omapfb_dss.h> | 19 | #include <video/omapfb_dss.h> |
| @@ -210,7 +211,7 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, · 191 unmodified lines | |||
| 210 | int r; | 211 | int r; |
| 211 | bool enable; | 212 | bool enable; |
| 212 | 213 | ||
| 213 | r = strtobool(buf, &enable); | 214 | r = kstrtobool(buf, &enable); |
| 214 | if (r) | 215 | if (r) |
| 215 | return r; | 216 | return r; |
| 216 | 217 | ||
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/kstrtox.h> | ||
| 18 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
| 19 | #include <linux/omapfb.h> | 20 | #include <linux/omapfb.h> |
| 20 | 21 | ||
| @@ -96,7 +97,7 @@ static ssize_t store_mirror(struct device *dev, · 75 unmodified lines | |||
| 96 | int r; | 97 | int r; |
| 97 | struct fb_var_screeninfo new_var; | 98 | struct fb_var_screeninfo new_var; |
| 98 | 99 | ||
| 99 | r = strtobool(buf, &mirror); | 100 | r = kstrtobool(buf, &mirror); |
| 100 | if (r) | 101 | if (r) |
| 101 | return r; | 102 | return r; |
| 102 | 103 | ||
| @@ -293,13 +293,7 @@ static int riva_bl_update_status(struct backlight_device *bd) · 292 unmodified lines | |||
| 293 | { | 293 | { |
| 294 | struct riva_par *par = bl_get_data(bd); | 294 | struct riva_par *par = bl_get_data(bd); |
| 295 | U032 tmp_pcrt, tmp_pmc; | 295 | U032 tmp_pcrt, tmp_pmc; |
| 296 | int level; | 296 | int level = backlight_get_brightness(bd); |
| 297 | |||
| 298 | if (bd->props.power != FB_BLANK_UNBLANK || | ||
| 299 | bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 300 | level = 0; | ||
| 301 | else | ||
| 302 | level = bd->props.brightness; | ||
| 303 | 297 | ||
| 304 | tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF; | 298 | tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF; |
| 305 | tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC; | 299 | tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC; |
| @@ -1426,12 +1426,20 @@ static void rbio_update_error_bitmap(struct btrfs_raid_bio *rbio, struct bio *bi · 1425 unmodified lines | |||
| 1426 | u32 bio_size = 0; | 1426 | u32 bio_size = 0; |
| 1427 | struct bio_vec *bvec; | 1427 | struct bio_vec *bvec; |
| 1428 | struct bvec_iter_all iter_all; | 1428 | struct bvec_iter_all iter_all; |
| 1429 | int i; | ||
| 1429 | 1430 | ||
| 1430 | bio_for_each_segment_all(bvec, bio, iter_all) | 1431 | bio_for_each_segment_all(bvec, bio, iter_all) |
| 1431 | bio_size += bvec->bv_len; | 1432 | bio_size += bvec->bv_len; |
| 1432 | 1433 | ||
| 1433 | bitmap_set(rbio->error_bitmap, total_sector_nr, | 1434 | /* |
| 1434 | bio_size >> rbio->bioc->fs_info->sectorsize_bits); | 1435 | * Since we can have multiple bios touching the error_bitmap, we cannot |
| 1436 | * call bitmap_set() without protection. | ||
| 1437 | * | ||
| 1438 | * Instead use set_bit() for each bit, as set_bit() itself is atomic. | ||
| 1439 | */ | ||
| 1440 | for (i = total_sector_nr; i < total_sector_nr + | ||
| 1441 | (bio_size >> rbio->bioc->fs_info->sectorsize_bits); i++) | ||
| 1442 | set_bit(i, rbio->error_bitmap); | ||
| 1435 | } | 1443 | } |
| 1436 | 1444 | ||
| 1437 | /* Verify the data sectors at read time. */ | 1445 | /* Verify the data sectors at read time. */ |
| @@ -1886,7 +1894,7 @@ pstripe: · 448 unmodified lines | |||
| 1886 | sector->uptodate = 1; | 1894 | sector->uptodate = 1; |
| 1887 | } | 1895 | } |
| 1888 | if (failb >= 0) { | 1896 | if (failb >= 0) { |
| 1889 | ret = verify_one_sector(rbio, faila, sector_nr); | 1897 | ret = verify_one_sector(rbio, failb, sector_nr); |
| 1890 | if (ret < 0) | 1898 | if (ret < 0) |
| 1891 | goto cleanup; | 1899 | goto cleanup; |
| 1892 | 1900 | ||
| @@ -8073,10 +8073,10 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg) · 8072 unmodified lines | |||
| 8073 | /* | 8073 | /* |
| 8074 | * Check that we don't overflow at later allocations, we request | 8074 | * Check that we don't overflow at later allocations, we request |
| 8075 | * clone_sources_count + 1 items, and compare to unsigned long inside | 8075 | * clone_sources_count + 1 items, and compare to unsigned long inside |
| 8076 | * access_ok. | 8076 | * access_ok. Also set an upper limit for allocation size so this can't |
| 8077 | * easily exhaust memory. Max number of clone sources is about 200K. | ||
| 8077 | */ | 8078 | */ |
| 8078 | if (arg->clone_sources_count > | 8079 | if (arg->clone_sources_count > SZ_8M / sizeof(struct clone_root)) { |
| 8079 | ULONG_MAX / sizeof(struct clone_root) - 1) { | ||
| 8080 | ret = -EINVAL; | 8080 | ret = -EINVAL; |
| 8081 | goto out; | 8081 | goto out; |
| 8082 | } | 8082 | } |
| @@ -1600,7 +1600,7 @@ again: · 1599 unmodified lines | |||
| 1600 | if (ret < 0) | 1600 | if (ret < 0) |
| 1601 | goto out; | 1601 | goto out; |
| 1602 | 1602 | ||
| 1603 | while (1) { | 1603 | while (search_start < search_end) { |
| 1604 | l = path->nodes[0]; | 1604 | l = path->nodes[0]; |
| 1605 | slot = path->slots[0]; | 1605 | slot = path->slots[0]; |
| 1606 | if (slot >= btrfs_header_nritems(l)) { | 1606 | if (slot >= btrfs_header_nritems(l)) { |
| @@ -1623,6 +1623,9 @@ again: · 16 unmodified lines | |||
| 1623 | if (key.type != BTRFS_DEV_EXTENT_KEY) | 1623 | if (key.type != BTRFS_DEV_EXTENT_KEY) |
| 1624 | goto next; | 1624 | goto next; |
| 1625 | 1625 | ||
| 1626 | if (key.offset > search_end) | ||
| 1627 | break; | ||
| 1628 | |||
| 1626 | if (key.offset > search_start) { | 1629 | if (key.offset > search_start) { |
| 1627 | hole_size = key.offset - search_start; | 1630 | hole_size = key.offset - search_start; |
| 1628 | dev_extent_hole_check(device, &search_start, &hole_size, | 1631 | dev_extent_hole_check(device, &search_start, &hole_size, |
| @@ -1683,6 +1686,7 @@ next: · 54 unmodified lines | |||
| 1683 | else | 1686 | else |
| 1684 | ret = 0; | 1687 | ret = 0; |
| 1685 | 1688 | ||
| 1689 | ASSERT(max_hole_start + max_hole_size <= search_end); | ||
| 1686 | out: | 1690 | out: |
| 1687 | btrfs_free_path(path); | 1691 | btrfs_free_path(path); |
| 1688 | *start = max_hole_start; | 1692 | *start = max_hole_start; |
| @@ -63,7 +63,7 @@ struct list_head *zlib_alloc_workspace(unsigned int level) · 62 unmodified lines | |||
| 63 | 63 | ||
| 64 | workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), | 64 | workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), |
| 65 | zlib_inflate_workspacesize()); | 65 | zlib_inflate_workspacesize()); |
| 66 | workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL); | 66 | workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL); |
| 67 | workspace->level = level; | 67 | workspace->level = level; |
| 68 | workspace->buf = NULL; | 68 | workspace->buf = NULL; |
| 69 | /* | 69 | /* |
| @@ -305,7 +305,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) · 304 unmodified lines | |||
| 305 | struct inode *inode = rreq->inode; | 305 | struct inode *inode = rreq->inode; |
| 306 | struct ceph_inode_info *ci = ceph_inode(inode); | 306 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 307 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 307 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 308 | struct ceph_osd_request *req; | 308 | struct ceph_osd_request *req = NULL; |
| 309 | struct ceph_vino vino = ceph_vino(inode); | 309 | struct ceph_vino vino = ceph_vino(inode); |
| 310 | struct iov_iter iter; | 310 | struct iov_iter iter; |
| 311 | struct page **pages; | 311 | struct page **pages; |
| @@ -313,6 +313,11 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) · 1 unmodified line | |||
| 313 | int err = 0; | 313 | int err = 0; |
| 314 | u64 len = subreq->len; | 314 | u64 len = subreq->len; |
| 315 | 315 | ||
| 316 | if (ceph_inode_is_shutdown(inode)) { | ||
| 317 | err = -EIO; | ||
| 318 | goto out; | ||
| 319 | } | ||
| 320 | |||
| 316 | if (ceph_has_inline_data(ci) && ceph_netfs_issue_op_inline(subreq)) | 321 | if (ceph_has_inline_data(ci) && ceph_netfs_issue_op_inline(subreq)) |
| 317 | return; | 322 | return; |
| 318 | 323 | ||
| @@ -563,6 +568,9 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) · 244 unmodified lines | |||
| 563 | 568 | ||
| 564 | dout("writepage %p idx %lu\n", page, page->index); | 569 | dout("writepage %p idx %lu\n", page, page->index); |
| 565 | 570 | ||
| 571 | if (ceph_inode_is_shutdown(inode)) | ||
| 572 | return -EIO; | ||
| 573 | |||
| 566 | /* verify this is a writeable snap context */ | 574 | /* verify this is a writeable snap context */ |
| 567 | snapc = page_snap_context(page); | 575 | snapc = page_snap_context(page); |
| 568 | if (!snapc) { | 576 | if (!snapc) { |
| @@ -1643,7 +1651,7 @@ int ceph_uninline_data(struct file *file) · 1074 unmodified lines | |||
| 1643 | struct ceph_inode_info *ci = ceph_inode(inode); | 1651 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1644 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 1652 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 1645 | struct ceph_osd_request *req = NULL; | 1653 | struct ceph_osd_request *req = NULL; |
| 1646 | struct ceph_cap_flush *prealloc_cf; | 1654 | struct ceph_cap_flush *prealloc_cf = NULL; |
| 1647 | struct folio *folio = NULL; | 1655 | struct folio *folio = NULL; |
| 1648 | u64 inline_version = CEPH_INLINE_NONE; | 1656 | u64 inline_version = CEPH_INLINE_NONE; |
| 1649 | struct page *pages[1]; | 1657 | struct page *pages[1]; |
| @@ -1657,6 +1665,11 @@ int ceph_uninline_data(struct file *file) · 7 unmodified lines | |||
| 1657 | dout("uninline_data %p %llx.%llx inline_version %llu\n", | 1665 | dout("uninline_data %p %llx.%llx inline_version %llu\n", |
| 1658 | inode, ceph_vinop(inode), inline_version); | 1666 | inode, ceph_vinop(inode), inline_version); |
| 1659 | 1667 | ||
| 1668 | if (ceph_inode_is_shutdown(inode)) { | ||
| 1669 | err = -EIO; | ||
| 1670 | goto out; | ||
| 1671 | } | ||
| 1672 | |||
| 1660 | if (inline_version == CEPH_INLINE_NONE) | 1673 | if (inline_version == CEPH_INLINE_NONE) |
| 1661 | return 0; | 1674 | return 0; |
| 1662 | 1675 | ||
| @@ -4078,6 +4078,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 4077 unmodified lines | |||
| 4078 | void *p, *end; | 4078 | void *p, *end; |
| 4079 | struct cap_extra_info extra_info = {}; | 4079 | struct cap_extra_info extra_info = {}; |
| 4080 | bool queue_trunc; | 4080 | bool queue_trunc; |
| 4081 | bool close_sessions = false; | ||
| 4081 | 4082 | ||
| 4082 | dout("handle_caps from mds%d\n", session->s_mds); | 4083 | dout("handle_caps from mds%d\n", session->s_mds); |
| 4083 | 4084 | ||
| @@ -4215,9 +4216,13 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 131 unmodified lines | |||
| 4215 | realm = NULL; | 4216 | realm = NULL; |
| 4216 | if (snaptrace_len) { | 4217 | if (snaptrace_len) { |
| 4217 | down_write(&mdsc->snap_rwsem); | 4218 | down_write(&mdsc->snap_rwsem); |
| 4218 | ceph_update_snap_trace(mdsc, snaptrace, | 4219 | if (ceph_update_snap_trace(mdsc, snaptrace, |
| 4219 | snaptrace + snaptrace_len, | 4220 | snaptrace + snaptrace_len, |
| 4220 | false, &realm); | 4221 | false, &realm)) { |
| 4222 | up_write(&mdsc->snap_rwsem); | ||
| 4223 | close_sessions = true; | ||
| 4224 | goto done; | ||
| 4225 | } | ||
| 4221 | downgrade_write(&mdsc->snap_rwsem); | 4226 | downgrade_write(&mdsc->snap_rwsem); |
| 4222 | } else { | 4227 | } else { |
| 4223 | down_read(&mdsc->snap_rwsem); | 4228 | down_read(&mdsc->snap_rwsem); |
| @@ -4277,6 +4282,11 @@ done_unlocked: · 53 unmodified lines | |||
| 4277 | iput(inode); | 4282 | iput(inode); |
| 4278 | out: | 4283 | out: |
| 4279 | ceph_put_string(extra_info.pool_ns); | 4284 | ceph_put_string(extra_info.pool_ns); |
| 4285 | |||
| 4286 | /* Defer closing the sessions after s_mutex lock being released */ | ||
| 4287 | if (close_sessions) | ||
| 4288 | ceph_mdsc_close_sessions(mdsc); | ||
| 4289 | |||
| 4280 | return; | 4290 | return; |
| 4281 | 4291 | ||
| 4282 | flush_cap_releases: | 4292 | flush_cap_releases: |
| @@ -2011,6 +2011,9 @@ static int ceph_zero_partial_object(struct inode *inode, · 2010 unmodified lines | |||
| 2011 | loff_t zero = 0; | 2011 | loff_t zero = 0; |
| 2012 | int op; | 2012 | int op; |
| 2013 | 2013 | ||
| 2014 | if (ceph_inode_is_shutdown(inode)) | ||
| 2015 | return -EIO; | ||
| 2016 | |||
| 2014 | if (!length) { | 2017 | if (!length) { |
| 2015 | op = offset ? CEPH_OSD_OP_DELETE : CEPH_OSD_OP_TRUNCATE; | 2018 | op = offset ? CEPH_OSD_OP_DELETE : CEPH_OSD_OP_TRUNCATE; |
| 2016 | length = &zero; | 2019 | length = &zero; |
| @@ -806,6 +806,9 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, · 805 unmodified lines | |||
| 806 | { | 806 | { |
| 807 | struct ceph_mds_session *s; | 807 | struct ceph_mds_session *s; |
| 808 | 808 | ||
| 809 | if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) | ||
| 810 | return ERR_PTR(-EIO); | ||
| 811 | |||
| 809 | if (mds >= mdsc->mdsmap->possible_max_rank) | 812 | if (mds >= mdsc->mdsmap->possible_max_rank) |
| 810 | return ERR_PTR(-EINVAL); | 813 | return ERR_PTR(-EINVAL); |
| 811 | 814 | ||
| @@ -1478,6 +1481,9 @@ static int __open_session(struct ceph_mds_client *mdsc, · 666 unmodified lines | |||
| 1478 | int mstate; | 1481 | int mstate; |
| 1479 | int mds = session->s_mds; | 1482 | int mds = session->s_mds; |
| 1480 | 1483 | ||
| 1484 | if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) | ||
| 1485 | return -EIO; | ||
| 1486 | |||
| 1481 | /* wait for mds to go active? */ | 1487 | /* wait for mds to go active? */ |
| 1482 | mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds); | 1488 | mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds); |
| 1483 | dout("open_session to mds%d (%s)\n", mds, | 1489 | dout("open_session to mds%d (%s)\n", mds, |
| @@ -2860,6 +2866,11 @@ static void __do_request(struct ceph_mds_client *mdsc, · 1376 unmodified lines | |||
| 2860 | return; | 2866 | return; |
| 2861 | } | 2867 | } |
| 2862 | 2868 | ||
| 2869 | if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) { | ||
| 2870 | dout("do_request metadata corrupted\n"); | ||
| 2871 | err = -EIO; | ||
| 2872 | goto finish; | ||
| 2873 | } | ||
| 2863 | if (req->r_timeout && | 2874 | if (req->r_timeout && |
| 2864 | time_after_eq(jiffies, req->r_started + req->r_timeout)) { | 2875 | time_after_eq(jiffies, req->r_started + req->r_timeout)) { |
| 2865 | dout("do_request timed out\n"); | 2876 | dout("do_request timed out\n"); |
| @@ -3245,6 +3256,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 379 unmodified lines | |||
| 3245 | u64 tid; | 3256 | u64 tid; |
| 3246 | int err, result; | 3257 | int err, result; |
| 3247 | int mds = session->s_mds; | 3258 | int mds = session->s_mds; |
| 3259 | bool close_sessions = false; | ||
| 3248 | 3260 | ||
| 3249 | if (msg->front.iov_len < sizeof(*head)) { | 3261 | if (msg->front.iov_len < sizeof(*head)) { |
| 3250 | pr_err("mdsc_handle_reply got corrupt (short) reply\n"); | 3262 | pr_err("mdsc_handle_reply got corrupt (short) reply\n"); |
| @@ -3351,10 +3363,17 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 100 unmodified lines | |||
| 3351 | realm = NULL; | 3363 | realm = NULL; |
| 3352 | if (rinfo->snapblob_len) { | 3364 | if (rinfo->snapblob_len) { |
| 3353 | down_write(&mdsc->snap_rwsem); | 3365 | down_write(&mdsc->snap_rwsem); |
| 3354 | ceph_update_snap_trace(mdsc, rinfo->snapblob, | 3366 | err = ceph_update_snap_trace(mdsc, rinfo->snapblob, |
| 3355 | rinfo->snapblob + rinfo->snapblob_len, | 3367 | rinfo->snapblob + rinfo->snapblob_len, |
| 3356 | le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP, | 3368 | le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP, |
| 3357 | &realm); | 3369 | &realm); |
| 3370 | if (err) { | ||
| 3371 | up_write(&mdsc->snap_rwsem); | ||
| 3372 | close_sessions = true; | ||
| 3373 | if (err == -EIO) | ||
| 3374 | ceph_msg_dump(msg); | ||
| 3375 | goto out_err; | ||
| 3376 | } | ||
| 3358 | downgrade_write(&mdsc->snap_rwsem); | 3377 | downgrade_write(&mdsc->snap_rwsem); |
| 3359 | } else { | 3378 | } else { |
| 3360 | down_read(&mdsc->snap_rwsem); | 3379 | down_read(&mdsc->snap_rwsem); |
| @@ -3412,6 +3431,10 @@ out_err: · 51 unmodified lines | |||
| 3412 | req->r_end_latency, err); | 3431 | req->r_end_latency, err); |
| 3413 | out: | 3432 | out: |
| 3414 | ceph_mdsc_put_request(req); | 3433 | ceph_mdsc_put_request(req); |
| 3434 | |||
| 3435 | /* Defer closing the sessions after s_mutex lock being released */ | ||
| 3436 | if (close_sessions) | ||
| 3437 | ceph_mdsc_close_sessions(mdsc); | ||
| 3415 | return; | 3438 | return; |
| 3416 | } | 3439 | } |
| 3417 | 3440 | ||
| @@ -5011,7 +5034,7 @@ static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped) · 1593 unmodified lines | |||
| 5011 | } | 5034 | } |
| 5012 | 5035 | ||
| 5013 | /* | 5036 | /* |
| 5014 | * called after sb is ro. | 5037 | * called after sb is ro or when metadata corrupted. |
| 5015 | */ | 5038 | */ |
| 5016 | void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc) | 5039 | void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc) |
| 5017 | { | 5040 | { |
| @@ -5301,7 +5324,8 @@ static void mds_peer_reset(struct ceph_connection *con) · 283 unmodified lines | |||
| 5301 | struct ceph_mds_client *mdsc = s->s_mdsc; | 5324 | struct ceph_mds_client *mdsc = s->s_mdsc; |
| 5302 | 5325 | ||
| 5303 | pr_warn("mds%d closed our session\n", s->s_mds); | 5326 | pr_warn("mds%d closed our session\n", s->s_mds); |
| 5304 | send_mds_reconnect(mdsc, s); | 5327 | if (READ_ONCE(mdsc->fsc->mount_state) != CEPH_MOUNT_FENCE_IO) |
| 5328 | send_mds_reconnect(mdsc, s); | ||
| 5305 | } | 5329 | } |
| 5306 | 5330 | ||
| 5307 | static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg) | 5331 | static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg) |
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <linux/ceph/ceph_debug.h> | 2 | #include <linux/ceph/ceph_debug.h> |
| 3 | 3 | ||
| 4 | #include <linux/fs.h> | ||
| 4 | #include <linux/sort.h> | 5 | #include <linux/sort.h> |
| 5 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
| 6 | #include <linux/iversion.h> | 7 | #include <linux/iversion.h> |
| @@ -766,8 +767,10 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, · 759 unmodified lines | |||
| 766 | struct ceph_snap_realm *realm; | 767 | struct ceph_snap_realm *realm; |
| 767 | struct ceph_snap_realm *first_realm = NULL; | 768 | struct ceph_snap_realm *first_realm = NULL; |
| 768 | struct ceph_snap_realm *realm_to_rebuild = NULL; | 769 | struct ceph_snap_realm *realm_to_rebuild = NULL; |
| 770 | struct ceph_client *client = mdsc->fsc->client; | ||
| 769 | int rebuild_snapcs; | 771 | int rebuild_snapcs; |
| 770 | int err = -ENOMEM; | 772 | int err = -ENOMEM; |
| 773 | int ret; | ||
| 771 | LIST_HEAD(dirty_realms); | 774 | LIST_HEAD(dirty_realms); |
| 772 | 775 | ||
| 773 | lockdep_assert_held_write(&mdsc->snap_rwsem); | 776 | lockdep_assert_held_write(&mdsc->snap_rwsem); |
| @@ -884,6 +887,27 @@ fail: · 110 unmodified lines | |||
| 884 | if (first_realm) | 887 | if (first_realm) |
| 885 | ceph_put_snap_realm(mdsc, first_realm); | 888 | ceph_put_snap_realm(mdsc, first_realm); |
| 886 | pr_err("%s error %d\n", __func__, err); | 889 | pr_err("%s error %d\n", __func__, err); |
| 890 | |||
| 891 | /* | ||
| 892 | * When receiving a corrupted snap trace we don't know what | ||
| 893 | * exactly has happened in MDS side. And we shouldn't continue | ||
| 894 | * writing to OSD, which may corrupt the snapshot contents. | ||
| 895 | * | ||
| 896 | * Just try to blocklist this kclient and then this kclient | ||
| 897 | * must be remounted to continue after the corrupted metadata | ||
| 898 | * fixed in the MDS side. | ||
| 899 | */ | ||
| 900 | WRITE_ONCE(mdsc->fsc->mount_state, CEPH_MOUNT_FENCE_IO); | ||
| 901 | ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr); | ||
| 902 | if (ret) | ||
| 903 | pr_err("%s failed to blocklist %s: %d\n", __func__, | ||
| 904 | ceph_pr_addr(&client->msgr.inst.addr), ret); | ||
| 905 | |||
| 906 | WARN(1, "%s: %s%sdo remount to continue%s", | ||
| 907 | __func__, ret ? "" : ceph_pr_addr(&client->msgr.inst.addr), | ||
| 908 | ret ? "" : " was blocklisted, ", | ||
| 909 | err == -EIO ? " after corrupted snaptrace is fixed" : ""); | ||
| 910 | |||
| 887 | return err; | 911 | return err; |
| 888 | } | 912 | } |
| 889 | 913 | ||
| @@ -984,6 +1008,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, · 94 unmodified lines | |||
| 984 | __le64 *split_inos = NULL, *split_realms = NULL; | 1008 | __le64 *split_inos = NULL, *split_realms = NULL; |
| 985 | int i; | 1009 | int i; |
| 986 | int locked_rwsem = 0; | 1010 | int locked_rwsem = 0; |
| 1011 | bool close_sessions = false; | ||
| 987 | 1012 | ||
| 988 | /* decode */ | 1013 | /* decode */ |
| 989 | if (msg->front.iov_len < sizeof(*h)) | 1014 | if (msg->front.iov_len < sizeof(*h)) |
| @@ -1092,8 +1117,12 @@ skip_inode: · 102 unmodified lines | |||
| 1092 | * update using the provided snap trace. if we are deleting a | 1117 | * update using the provided snap trace. if we are deleting a |
| 1093 | * snap, we can avoid queueing cap_snaps. | 1118 | * snap, we can avoid queueing cap_snaps. |
| 1094 | */ | 1119 | */ |
| 1095 | ceph_update_snap_trace(mdsc, p, e, | 1120 | if (ceph_update_snap_trace(mdsc, p, e, |
| 1096 | op == CEPH_SNAP_OP_DESTROY, NULL); | 1121 | op == CEPH_SNAP_OP_DESTROY, |
| 1122 | NULL)) { | ||
| 1123 | close_sessions = true; | ||
| 1124 | goto bad; | ||
| 1125 | } | ||
| 1097 | 1126 | ||
| 1098 | if (op == CEPH_SNAP_OP_SPLIT) | 1127 | if (op == CEPH_SNAP_OP_SPLIT) |
| 1099 | /* we took a reference when we created the realm, above */ | 1128 | /* we took a reference when we created the realm, above */ |
| @@ -1112,6 +1141,9 @@ bad: · 12 unmodified lines | |||
| 1112 | out: | 1141 | out: |
| 1113 | if (locked_rwsem) | 1142 | if (locked_rwsem) |
| 1114 | up_write(&mdsc->snap_rwsem); | 1143 | up_write(&mdsc->snap_rwsem); |
| 1144 | |||
| 1145 | if (close_sessions) | ||
| 1146 | ceph_mdsc_close_sessions(mdsc); | ||
| 1115 | return; | 1147 | return; |
| 1116 | } | 1148 | } |
| 1117 | 1149 | ||
| @@ -100,6 +100,17 @@ struct ceph_mount_options { · 99 unmodified lines | |||
| 100 | char *mon_addr; | 100 | char *mon_addr; |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | /* mount state */ | ||
| 104 | enum { | ||
| 105 | CEPH_MOUNT_MOUNTING, | ||
| 106 | CEPH_MOUNT_MOUNTED, | ||
| 107 | CEPH_MOUNT_UNMOUNTING, | ||
| 108 | CEPH_MOUNT_UNMOUNTED, | ||
| 109 | CEPH_MOUNT_SHUTDOWN, | ||
| 110 | CEPH_MOUNT_RECOVER, | ||
| 111 | CEPH_MOUNT_FENCE_IO, | ||
| 112 | }; | ||
| 113 | |||
| 103 | #define CEPH_ASYNC_CREATE_CONFLICT_BITS 8 | 114 | #define CEPH_ASYNC_CREATE_CONFLICT_BITS 8 |
| 104 | 115 | ||
| 105 | struct ceph_fs_client { | 116 | struct ceph_fs_client { |
| @@ -3889,7 +3889,7 @@ uncached_fill_pages(struct TCP_Server_Info *server, · 3888 unmodified lines | |||
| 3889 | rdata->got_bytes += result; | 3889 | rdata->got_bytes += result; |
| 3890 | } | 3890 | } |
| 3891 | 3891 | ||
| 3892 | return rdata->got_bytes > 0 && result != -ECONNABORTED ? | 3892 | return result != -ECONNABORTED && rdata->got_bytes > 0 ? |
| 3893 | rdata->got_bytes : result; | 3893 | rdata->got_bytes : result; |
| 3894 | } | 3894 | } |
| 3895 | 3895 | ||
| @@ -4665,7 +4665,7 @@ readpages_fill_pages(struct TCP_Server_Info *server, · 769 unmodified lines | |||
| 4665 | rdata->got_bytes += result; | 4665 | rdata->got_bytes += result; |
| 4666 | } | 4666 | } |
| 4667 | 4667 | ||
| 4668 | return rdata->got_bytes > 0 && result != -ECONNABORTED ? | 4668 | return result != -ECONNABORTED && rdata->got_bytes > 0 ? |
| 4669 | rdata->got_bytes : result; | 4669 | rdata->got_bytes : result; |
| 4670 | } | 4670 | } |
| 4671 | 4671 | ||
| @@ -838,6 +838,30 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr) · 837 unmodified lines | |||
| 838 | } | 838 | } |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | int dump_emit(struct coredump_params *cprm, const void *addr, int nr) | ||
| 842 | { | ||
| 843 | if (cprm->to_skip) { | ||
| 844 | if (!__dump_skip(cprm, cprm->to_skip)) | ||
| 845 | return 0; | ||
| 846 | cprm->to_skip = 0; | ||
| 847 | } | ||
| 848 | return __dump_emit(cprm, addr, nr); | ||
| 849 | } | ||
| 850 | EXPORT_SYMBOL(dump_emit); | ||
| 851 | |||
| 852 | void dump_skip_to(struct coredump_params *cprm, unsigned long pos) | ||
| 853 | { | ||
| 854 | cprm->to_skip = pos - cprm->pos; | ||
| 855 | } | ||
| 856 | EXPORT_SYMBOL(dump_skip_to); | ||
| 857 | |||
| 858 | void dump_skip(struct coredump_params *cprm, size_t nr) | ||
| 859 | { | ||
| 860 | cprm->to_skip += nr; | ||
| 861 | } | ||
| 862 | EXPORT_SYMBOL(dump_skip); | ||
| 863 | |||
| 864 | #ifdef CONFIG_ELF_CORE | ||
| 841 | static int dump_emit_page(struct coredump_params *cprm, struct page *page) | 865 | static int dump_emit_page(struct coredump_params *cprm, struct page *page) |
| 842 | { | 866 | { |
| 843 | struct bio_vec bvec = { | 867 | struct bio_vec bvec = { |
| @@ -871,30 +895,6 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page) · 27 unmodified lines | |||
| 871 | return 1; | 895 | return 1; |
| 872 | } | 896 | } |
| 873 | 897 | ||
| 874 | int dump_emit(struct coredump_params *cprm, const void *addr, int nr) | ||
| 875 | { | ||
| 876 | if (cprm->to_skip) { | ||
| 877 | if (!__dump_skip(cprm, cprm->to_skip)) | ||
| 878 | return 0; | ||
| 879 | cprm->to_skip = 0; | ||
| 880 | } | ||
| 881 | return __dump_emit(cprm, addr, nr); | ||
| 882 | } | ||
| 883 | EXPORT_SYMBOL(dump_emit); | ||
| 884 | |||
| 885 | void dump_skip_to(struct coredump_params *cprm, unsigned long pos) | ||
| 886 | { | ||
| 887 | cprm->to_skip = pos - cprm->pos; | ||
| 888 | } | ||
| 889 | EXPORT_SYMBOL(dump_skip_to); | ||
| 890 | |||
| 891 | void dump_skip(struct coredump_params *cprm, size_t nr) | ||
| 892 | { | ||
| 893 | cprm->to_skip += nr; | ||
| 894 | } | ||
| 895 | EXPORT_SYMBOL(dump_skip); | ||
| 896 | |||
| 897 | #ifdef CONFIG_ELF_CORE | ||
| 898 | int dump_user_range(struct coredump_params *cprm, unsigned long start, | 898 | int dump_user_range(struct coredump_params *cprm, unsigned long start, |
| 899 | unsigned long len) | 899 | unsigned long len) |
| 900 | { | 900 | { |
| @@ -8,7 +8,7 @@ config VXFS_FS · 7 unmodified lines | |||
| 8 | of SCO UnixWare (and possibly others) and optionally available | 8 | of SCO UnixWare (and possibly others) and optionally available |
| 9 | for Sunsoft Solaris, HP-UX and many other operating systems. However | 9 | for Sunsoft Solaris, HP-UX and many other operating systems. However |
| 10 | these particular OS implementations of vxfs may differ in on-disk | 10 | these particular OS implementations of vxfs may differ in on-disk |
| 11 | data endianess and/or superblock offset. The vxfs module has been | 11 | data endianness and/or superblock offset. The vxfs module has been |
| 12 | tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) | 12 | tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) |
| 13 | Currently only readonly access is supported and VxFX versions | 13 | Currently only readonly access is supported and VxFX versions |
| 14 | 2, 3 and 4. Tests were performed with HP-UX VxFS version 3. | 14 | 2, 3 and 4. Tests were performed with HP-UX VxFS version 3. |
| @@ -745,9 +745,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, · 744 unmodified lines | |||
| 745 | page = pfn_swap_entry_to_page(swpent); | 745 | page = pfn_swap_entry_to_page(swpent); |
| 746 | } | 746 | } |
| 747 | if (page) { | 747 | if (page) { |
| 748 | int mapcount = page_mapcount(page); | 748 | if (page_mapcount(page) >= 2 || hugetlb_pmd_shared(pte)) |
| 749 | |||
| 750 | if (mapcount >= 2) | ||
| 751 | mss->shared_hugetlb += huge_page_size(hstate_vma(vma)); | 749 | mss->shared_hugetlb += huge_page_size(hstate_vma(vma)); |
| 752 | else | 750 | else |
| 753 | mss->private_hugetlb += huge_page_size(hstate_vma(vma)); | 751 | mss->private_hugetlb += huge_page_size(hstate_vma(vma)); |
| @@ -183,7 +183,7 @@ static inline int squashfs_block_size(__le32 raw) · 182 unmodified lines | |||
| 183 | #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ | 183 | #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ |
| 184 | sizeof(u64)) | 184 | sizeof(u64)) |
| 185 | /* xattr id lookup table defines */ | 185 | /* xattr id lookup table defines */ |
| 186 | #define SQUASHFS_XATTR_BYTES(A) ((A) * sizeof(struct squashfs_xattr_id)) | 186 | #define SQUASHFS_XATTR_BYTES(A) (((u64) (A)) * sizeof(struct squashfs_xattr_id)) |
| 187 | 187 | ||
| 188 | #define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \ | 188 | #define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \ |
| 189 | SQUASHFS_METADATA_SIZE) | 189 | SQUASHFS_METADATA_SIZE) |
| @@ -63,7 +63,7 @@ struct squashfs_sb_info { · 62 unmodified lines | |||
| 63 | long long bytes_used; | 63 | long long bytes_used; |
| 64 | unsigned int inodes; | 64 | unsigned int inodes; |
| 65 | unsigned int fragments; | 65 | unsigned int fragments; |
| 66 | int xattr_ids; | 66 | unsigned int xattr_ids; |
| 67 | unsigned int ids; | 67 | unsigned int ids; |
| 68 | bool panic_on_errors; | 68 | bool panic_on_errors; |
| 69 | const struct squashfs_decompressor_thread_ops *thread_ops; | 69 | const struct squashfs_decompressor_thread_ops *thread_ops; |
| @@ -10,12 +10,12 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #ifdef CONFIG_SQUASHFS_XATTR | 11 | #ifdef CONFIG_SQUASHFS_XATTR |
| 12 | extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64, | 12 | extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64, |
| 13 | u64 *, int *); | 13 | u64 *, unsigned int *); |
| 14 | extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *, | 14 | extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *, |
| 15 | unsigned int *, unsigned long long *); | 15 | unsigned int *, unsigned long long *); |
| 16 | #else | 16 | #else |
| 17 | static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb, | 17 | static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb, |
| 18 | u64 start, u64 *xattr_table_start, int *xattr_ids) | 18 | u64 start, u64 *xattr_table_start, unsigned int *xattr_ids) |
| 19 | { | 19 | { |
| 20 | struct squashfs_xattr_id_table *id_table; | 20 | struct squashfs_xattr_id_table *id_table; |
| 21 | 21 | ||
| @@ -56,7 +56,7 @@ int squashfs_xattr_lookup(struct super_block *sb, unsigned int index, · 55 unmodified lines | |||
| 56 | * Read uncompressed xattr id lookup table indexes from disk into memory | 56 | * Read uncompressed xattr id lookup table indexes from disk into memory |
| 57 | */ | 57 | */ |
| 58 | __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, | 58 | __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, |
| 59 | u64 *xattr_table_start, int *xattr_ids) | 59 | u64 *xattr_table_start, unsigned int *xattr_ids) |
| 60 | { | 60 | { |
| 61 | struct squashfs_sb_info *msblk = sb->s_fs_info; | 61 | struct squashfs_sb_info *msblk = sb->s_fs_info; |
| 62 | unsigned int len, indexes; | 62 | unsigned int len, indexes; |
| @@ -76,7 +76,7 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, · 13 unmodified lines | |||
| 76 | /* Sanity check values */ | 76 | /* Sanity check values */ |
| 77 | 77 | ||
| 78 | /* there is always at least one xattr id */ | 78 | /* there is always at least one xattr id */ |
| 79 | if (*xattr_ids == 0) | 79 | if (*xattr_ids <= 0) |
| 80 | return ERR_PTR(-EINVAL); | 80 | return ERR_PTR(-EINVAL); |
| 81 | 81 | ||
| 82 | len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); | 82 | len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); |
| @@ -263,7 +263,7 @@ struct vgic_dist { · 262 unmodified lines | |||
| 263 | struct vgic_io_device dist_iodev; | 263 | struct vgic_io_device dist_iodev; |
| 264 | 264 | ||
| 265 | bool has_its; | 265 | bool has_its; |
| 266 | bool save_its_tables_in_progress; | 266 | bool table_write_in_progress; |
| 267 | 267 | ||
| 268 | /* | 268 | /* |
| 269 | * Contains the attributes and gpa of the LPI configuration table. | 269 | * Contains the attributes and gpa of the LPI configuration table. |
| @@ -99,16 +99,6 @@ struct ceph_options { · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | #define CEPH_AUTH_NAME_DEFAULT "guest" | 100 | #define CEPH_AUTH_NAME_DEFAULT "guest" |
| 101 | 101 | ||
| 102 | /* mount state */ | ||
| 103 | enum { | ||
| 104 | CEPH_MOUNT_MOUNTING, | ||
| 105 | CEPH_MOUNT_MOUNTED, | ||
| 106 | CEPH_MOUNT_UNMOUNTING, | ||
| 107 | CEPH_MOUNT_UNMOUNTED, | ||
| 108 | CEPH_MOUNT_SHUTDOWN, | ||
| 109 | CEPH_MOUNT_RECOVER, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static inline unsigned long ceph_timeout_jiffies(unsigned long timeout) | 102 | static inline unsigned long ceph_timeout_jiffies(unsigned long timeout) |
| 113 | { | 103 | { |
| 114 | return timeout ?: MAX_SCHEDULE_TIMEOUT; | 104 | return timeout ?: MAX_SCHEDULE_TIMEOUT; |
| @@ -668,7 +668,8 @@ extern struct efi { · 667 unmodified lines | |||
| 668 | 668 | ||
| 669 | #define EFI_RT_SUPPORTED_ALL 0x3fff | 669 | #define EFI_RT_SUPPORTED_ALL 0x3fff |
| 670 | 670 | ||
| 671 | #define EFI_RT_SUPPORTED_TIME_SERVICES 0x000f | 671 | #define EFI_RT_SUPPORTED_TIME_SERVICES 0x0003 |
| 672 | #define EFI_RT_SUPPORTED_WAKEUP_SERVICES 0x000c | ||
| 672 | #define EFI_RT_SUPPORTED_VARIABLE_SERVICES 0x0070 | 673 | #define EFI_RT_SUPPORTED_VARIABLE_SERVICES 0x0070 |
| 673 | 674 | ||
| 674 | extern struct mm_struct efi_mm; | 675 | extern struct mm_struct efi_mm; |
| @@ -200,7 +200,7 @@ static inline void *kmap_local_pfn(unsigned long pfn) · 199 unmodified lines | |||
| 200 | static inline void __kunmap_local(const void *addr) | 200 | static inline void __kunmap_local(const void *addr) |
| 201 | { | 201 | { |
| 202 | #ifdef ARCH_HAS_FLUSH_ON_KUNMAP | 202 | #ifdef ARCH_HAS_FLUSH_ON_KUNMAP |
| 203 | kunmap_flush_on_unmap(addr); | 203 | kunmap_flush_on_unmap(PTR_ALIGN_DOWN(addr, PAGE_SIZE)); |
| 204 | #endif | 204 | #endif |
| 205 | } | 205 | } |
| 206 | 206 | ||
| @@ -227,7 +227,7 @@ static inline void *kmap_atomic_pfn(unsigned long pfn) · 20 unmodified lines | |||
| 227 | static inline void __kunmap_atomic(const void *addr) | 227 | static inline void __kunmap_atomic(const void *addr) |
| 228 | { | 228 | { |
| 229 | #ifdef ARCH_HAS_FLUSH_ON_KUNMAP | 229 | #ifdef ARCH_HAS_FLUSH_ON_KUNMAP |
| 230 | kunmap_flush_on_unmap(addr); | 230 | kunmap_flush_on_unmap(PTR_ALIGN_DOWN(addr, PAGE_SIZE)); |
| 231 | #endif | 231 | #endif |
| 232 | pagefault_enable(); | 232 | pagefault_enable(); |
| 233 | if (IS_ENABLED(CONFIG_PREEMPT_RT)) | 233 | if (IS_ENABLED(CONFIG_PREEMPT_RT)) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
| 8 | #include <linux/hugetlb_inline.h> | 8 | #include <linux/hugetlb_inline.h> |
| 9 | #include <linux/cgroup.h> | 9 | #include <linux/cgroup.h> |
| 10 | #include <linux/page_ref.h> | ||
| 10 | #include <linux/list.h> | 11 | #include <linux/list.h> |
| 11 | #include <linux/kref.h> | 12 | #include <linux/kref.h> |
| 12 | #include <linux/pgtable.h> | 13 | #include <linux/pgtable.h> |
| @@ -1187,6 +1188,18 @@ static inline __init void hugetlb_cma_reserve(int order) · 1174 unmodified lines | |||
| 1187 | } | 1188 | } |
| 1188 | #endif | 1189 | #endif |
| 1189 | 1190 | ||
| 1191 | #ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE | ||
| 1192 | static inline bool hugetlb_pmd_shared(pte_t *pte) | ||
| 1193 | { | ||
| 1194 | return page_count(virt_to_page(pte)) > 1; | ||
| 1195 | } | ||
| 1196 | #else | ||
| 1197 | static inline bool hugetlb_pmd_shared(pte_t *pte) | ||
| 1198 | { | ||
| 1199 | return false; | ||
| 1200 | } | ||
| 1201 | #endif | ||
| 1202 | |||
| 1190 | bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr); | 1203 | bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr); |
| 1191 | 1204 | ||
| 1192 | #ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE | 1205 | #ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE |
| @@ -1666,10 +1666,13 @@ void mem_cgroup_track_foreign_dirty_slowpath(struct folio *folio, · 1665 unmodified lines | |||
| 1666 | static inline void mem_cgroup_track_foreign_dirty(struct folio *folio, | 1666 | static inline void mem_cgroup_track_foreign_dirty(struct folio *folio, |
| 1667 | struct bdi_writeback *wb) | 1667 | struct bdi_writeback *wb) |
| 1668 | { | 1668 | { |
| 1669 | struct mem_cgroup *memcg; | ||
| 1670 | |||
| 1669 | if (mem_cgroup_disabled()) | 1671 | if (mem_cgroup_disabled()) |
| 1670 | return; | 1672 | return; |
| 1671 | 1673 | ||
| 1672 | if (unlikely(&folio_memcg(folio)->css != wb->memcg_css)) | 1674 | memcg = folio_memcg(folio); |
| 1675 | if (unlikely(memcg && &memcg->css != wb->memcg_css)) | ||
| 1673 | mem_cgroup_track_foreign_dirty_slowpath(folio, wb); | 1676 | mem_cgroup_track_foreign_dirty_slowpath(folio, wb); |
| 1674 | } | 1677 | } |
| 1675 | 1678 | ||
| @@ -572,6 +572,14 @@ struct mlx5_debugfs_entries { · 571 unmodified lines | |||
| 572 | struct dentry *lag_debugfs; | 572 | struct dentry *lag_debugfs; |
| 573 | }; | 573 | }; |
| 574 | 574 | ||
| 575 | enum mlx5_func_type { | ||
| 576 | MLX5_PF, | ||
| 577 | MLX5_VF, | ||
| 578 | MLX5_SF, | ||
| 579 | MLX5_HOST_PF, | ||
| 580 | MLX5_FUNC_TYPE_NUM, | ||
| 581 | }; | ||
| 582 | |||
| 575 | struct mlx5_ft_pool; | 583 | struct mlx5_ft_pool; |
| 576 | struct mlx5_priv { | 584 | struct mlx5_priv { |
| 577 | /* IRQ table valid only for real pci devices PF or VF */ | 585 | /* IRQ table valid only for real pci devices PF or VF */ |
| @@ -582,11 +590,10 @@ struct mlx5_priv { · 4 unmodified lines | |||
| 582 | struct mlx5_nb pg_nb; | 590 | struct mlx5_nb pg_nb; |
| 583 | struct workqueue_struct *pg_wq; | 591 | struct workqueue_struct *pg_wq; |
| 584 | struct xarray page_root_xa; | 592 | struct xarray page_root_xa; |
| 585 | u32 fw_pages; | ||
| 586 | atomic_t reg_pages; | 593 | atomic_t reg_pages; |
| 587 | struct list_head free_list; | 594 | struct list_head free_list; |
| 588 | u32 vfs_pages; | 595 | u32 fw_pages; |
| 589 | u32 host_pf_pages; | 596 | u32 page_counters[MLX5_FUNC_TYPE_NUM]; |
| 590 | u32 fw_pages_alloc_failed; | 597 | u32 fw_pages_alloc_failed; |
| 591 | u32 give_pages_dropped; | 598 | u32 give_pages_dropped; |
| 592 | u32 reclaim_pages_discard; | 599 | u32 reclaim_pages_discard; |
| @@ -70,7 +70,6 @@ struct nvmem_keepout { · 69 unmodified lines | |||
| 70 | * @word_size: Minimum read/write access granularity. | 70 | * @word_size: Minimum read/write access granularity. |
| 71 | * @stride: Minimum read/write access stride. | 71 | * @stride: Minimum read/write access stride. |
| 72 | * @priv: User context passed to read/write callbacks. | 72 | * @priv: User context passed to read/write callbacks. |
| 73 | * @wp-gpio: Write protect pin | ||
| 74 | * @ignore_wp: Write Protect pin is managed by the provider. | 73 | * @ignore_wp: Write Protect pin is managed by the provider. |
| 75 | * | 74 | * |
| 76 | * Note: A default "nvmem<id>" name will be assigned to the device if | 75 | * Note: A default "nvmem<id>" name will be assigned to the device if |
| @@ -85,7 +84,6 @@ struct nvmem_config { · 8 unmodified lines | |||
| 85 | const char *name; | 84 | const char *name; |
| 86 | int id; | 85 | int id; |
| 87 | struct module *owner; | 86 | struct module *owner; |
| 88 | struct gpio_desc *wp_gpio; | ||
| 89 | const struct nvmem_cell_info *cells; | 87 | const struct nvmem_cell_info *cells; |
| 90 | int ncells; | 88 | int ncells; |
| 91 | const struct nvmem_keepout *keepout; | 89 | const struct nvmem_keepout *keepout; |
| @@ -476,6 +476,15 @@ extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, · 475 unmodified lines | |||
| 476 | #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ | 476 | #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ |
| 477 | __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) | 477 | __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) |
| 478 | 478 | ||
| 479 | extern int _atomic_dec_and_raw_lock(atomic_t *atomic, raw_spinlock_t *lock); | ||
| 480 | #define atomic_dec_and_raw_lock(atomic, lock) \ | ||
| 481 | __cond_lock(lock, _atomic_dec_and_raw_lock(atomic, lock)) | ||
| 482 | |||
| 483 | extern int _atomic_dec_and_raw_lock_irqsave(atomic_t *atomic, raw_spinlock_t *lock, | ||
| 484 | unsigned long *flags); | ||
| 485 | #define atomic_dec_and_raw_lock_irqsave(atomic, lock, flags) \ | ||
| 486 | __cond_lock(lock, _atomic_dec_and_raw_lock_irqsave(atomic, lock, &(flags))) | ||
| 487 | |||
| 479 | int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, | 488 | int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, |
| 480 | size_t max_size, unsigned int cpu_mult, | 489 | size_t max_size, unsigned int cpu_mult, |
| 481 | gfp_t gfp, const char *name, | 490 | gfp_t gfp, const char *name, |
| @@ -418,8 +418,7 @@ extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, · 417 unmodified lines | |||
| 418 | extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, | 418 | extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, |
| 419 | unsigned long nr_pages, | 419 | unsigned long nr_pages, |
| 420 | gfp_t gfp_mask, | 420 | gfp_t gfp_mask, |
| 421 | unsigned int reclaim_options, | 421 | unsigned int reclaim_options); |
| 422 | nodemask_t *nodemask); | ||
| 423 | extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem, | 422 | extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem, |
| 424 | gfp_t gfp_mask, bool noswap, | 423 | gfp_t gfp_mask, bool noswap, |
| 425 | pg_data_t *pgdat, | 424 | pg_data_t *pgdat, |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #ifndef _UAPI_LINUX_IP_H | 18 | #ifndef _UAPI_LINUX_IP_H |
| 19 | #define _UAPI_LINUX_IP_H | 19 | #define _UAPI_LINUX_IP_H |
| 20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
| 21 | #include <linux/stddef.h> | ||
| 21 | #include <asm/byteorder.h> | 22 | #include <asm/byteorder.h> |
| 22 | 23 | ||
| 23 | #define IPTOS_TOS_MASK 0x1E | 24 | #define IPTOS_TOS_MASK 0x1E |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/libc-compat.h> | 5 | #include <linux/libc-compat.h> |
| 6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
| 7 | #include <linux/stddef.h> | ||
| 7 | #include <linux/in6.h> | 8 | #include <linux/in6.h> |
| 8 | #include <asm/byteorder.h> | 9 | #include <asm/byteorder.h> |
| 9 | 10 | ||
| @@ -1205,12 +1205,13 @@ void rebuild_sched_domains(void) · 1204 unmodified lines | |||
| 1205 | /** | 1205 | /** |
| 1206 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. | 1206 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. |
| 1207 | * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed | 1207 | * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed |
| 1208 | * @new_cpus: the temp variable for the new effective_cpus mask | ||
| 1208 | * | 1209 | * |
| 1209 | * Iterate through each task of @cs updating its cpus_allowed to the | 1210 | * Iterate through each task of @cs updating its cpus_allowed to the |
| 1210 | * effective cpuset's. As this function is called with cpuset_rwsem held, | 1211 | * effective cpuset's. As this function is called with cpuset_rwsem held, |
| 1211 | * cpuset membership stays stable. | 1212 | * cpuset membership stays stable. |
| 1212 | */ | 1213 | */ |
| 1213 | static void update_tasks_cpumask(struct cpuset *cs) | 1214 | static void update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus) |
| 1214 | { | 1215 | { |
| 1215 | struct css_task_iter it; | 1216 | struct css_task_iter it; |
| 1216 | struct task_struct *task; | 1217 | struct task_struct *task; |
| @@ -1224,7 +1225,10 @@ static void update_tasks_cpumask(struct cpuset *cs) · 7 unmodified lines | |||
| 1224 | if (top_cs && (task->flags & PF_KTHREAD) && | 1225 | if (top_cs && (task->flags & PF_KTHREAD) && |
| 1225 | kthread_is_per_cpu(task)) | 1226 | kthread_is_per_cpu(task)) |
| 1226 | continue; | 1227 | continue; |
| 1227 | set_cpus_allowed_ptr(task, cs->effective_cpus); | 1228 | |
| 1229 | cpumask_and(new_cpus, cs->effective_cpus, | ||
| 1230 | task_cpu_possible_mask(task)); | ||
| 1231 | set_cpus_allowed_ptr(task, new_cpus); | ||
| 1228 | } | 1232 | } |
| 1229 | css_task_iter_end(&it); | 1233 | css_task_iter_end(&it); |
| 1230 | } | 1234 | } |
| @@ -1509,7 +1513,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd, · 278 unmodified lines | |||
| 1509 | spin_unlock_irq(&callback_lock); | 1513 | spin_unlock_irq(&callback_lock); |
| 1510 | 1514 | ||
| 1511 | if (adding || deleting) | 1515 | if (adding || deleting) |
| 1512 | update_tasks_cpumask(parent); | 1516 | update_tasks_cpumask(parent, tmp->new_cpus); |
| 1513 | 1517 | ||
| 1514 | /* | 1518 | /* |
| 1515 | * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary. | 1519 | * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary. |
| @@ -1661,7 +1665,7 @@ update_parent_subparts: · 145 unmodified lines | |||
| 1661 | WARN_ON(!is_in_v2_mode() && | 1665 | WARN_ON(!is_in_v2_mode() && |
| 1662 | !cpumask_equal(cp->cpus_allowed, cp->effective_cpus)); | 1666 | !cpumask_equal(cp->cpus_allowed, cp->effective_cpus)); |
| 1663 | 1667 | ||
| 1664 | update_tasks_cpumask(cp); | 1668 | update_tasks_cpumask(cp, tmp->new_cpus); |
| 1665 | 1669 | ||
| 1666 | /* | 1670 | /* |
| 1667 | * On legacy hierarchy, if the effective cpumask of any non- | 1671 | * On legacy hierarchy, if the effective cpumask of any non- |
| @@ -2309,7 +2313,7 @@ static int update_prstate(struct cpuset *cs, int new_prs) · 641 unmodified lines | |||
| 2309 | } | 2313 | } |
| 2310 | } | 2314 | } |
| 2311 | 2315 | ||
| 2312 | update_tasks_cpumask(parent); | 2316 | update_tasks_cpumask(parent, tmpmask.new_cpus); |
| 2313 | 2317 | ||
| 2314 | if (parent->child_ecpus_count) | 2318 | if (parent->child_ecpus_count) |
| 2315 | update_sibling_cpumasks(parent, cs, &tmpmask); | 2319 | update_sibling_cpumasks(parent, cs, &tmpmask); |
| @@ -3348,7 +3352,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs, · 1032 unmodified lines | |||
| 3348 | * as the tasks will be migrated to an ancestor. | 3352 | * as the tasks will be migrated to an ancestor. |
| 3349 | */ | 3353 | */ |
| 3350 | if (cpus_updated && !cpumask_empty(cs->cpus_allowed)) | 3354 | if (cpus_updated && !cpumask_empty(cs->cpus_allowed)) |
| 3351 | update_tasks_cpumask(cs); | 3355 | update_tasks_cpumask(cs, new_cpus); |
| 3352 | if (mems_updated && !nodes_empty(cs->mems_allowed)) | 3356 | if (mems_updated && !nodes_empty(cs->mems_allowed)) |
| 3353 | update_tasks_nodemask(cs); | 3357 | update_tasks_nodemask(cs); |
| 3354 | 3358 | ||
| @@ -3385,7 +3389,7 @@ hotplug_update_tasks(struct cpuset *cs, · 30 unmodified lines | |||
| 3385 | spin_unlock_irq(&callback_lock); | 3389 | spin_unlock_irq(&callback_lock); |
| 3386 | 3390 | ||
| 3387 | if (cpus_updated) | 3391 | if (cpus_updated) |
| 3388 | update_tasks_cpumask(cs); | 3392 | update_tasks_cpumask(cs, new_cpus); |
| 3389 | if (mems_updated) | 3393 | if (mems_updated) |
| 3390 | update_tasks_nodemask(cs); | 3394 | update_tasks_nodemask(cs); |
| 3391 | } | 3395 | } |
| @@ -3692,15 +3696,38 @@ void __init cpuset_init_smp(void) · 300 unmodified lines | |||
| 3692 | * Description: Returns the cpumask_var_t cpus_allowed of the cpuset | 3696 | * Description: Returns the cpumask_var_t cpus_allowed of the cpuset |
| 3693 | * attached to the specified @tsk. Guaranteed to return some non-empty | 3697 | * attached to the specified @tsk. Guaranteed to return some non-empty |
| 3694 | * subset of cpu_online_mask, even if this means going outside the | 3698 | * subset of cpu_online_mask, even if this means going outside the |
| 3695 | * tasks cpuset. | 3699 | * tasks cpuset, except when the task is in the top cpuset. |
| 3696 | **/ | 3700 | **/ |
| 3697 | 3701 | ||
| 3698 | void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) | 3702 | void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) |
| 3699 | { | 3703 | { |
| 3700 | unsigned long flags; | 3704 | unsigned long flags; |
| 3705 | struct cpuset *cs; | ||
| 3701 | 3706 | ||
| 3702 | spin_lock_irqsave(&callback_lock, flags); | 3707 | spin_lock_irqsave(&callback_lock, flags); |
| 3703 | guarantee_online_cpus(tsk, pmask); | 3708 | rcu_read_lock(); |
| 3709 | |||
| 3710 | cs = task_cs(tsk); | ||
| 3711 | if (cs != &top_cpuset) | ||
| 3712 | guarantee_online_cpus(tsk, pmask); | ||
| 3713 | /* | ||
| 3714 | * Tasks in the top cpuset won't get update to their cpumasks | ||
| 3715 | * when a hotplug online/offline event happens. So we include all | ||
| 3716 | * offline cpus in the allowed cpu list. | ||
| 3717 | */ | ||
| 3718 | if ((cs == &top_cpuset) || cpumask_empty(pmask)) { | ||
| 3719 | const struct cpumask *possible_mask = task_cpu_possible_mask(tsk); | ||
| 3720 | |||
| 3721 | /* | ||
| 3722 | * We first exclude cpus allocated to partitions. If there is no | ||
| 3723 | * allowable online cpu left, we fall back to all possible cpus. | ||
| 3724 | */ | ||
| 3725 | cpumask_andnot(pmask, possible_mask, top_cpuset.subparts_cpus); | ||
| 3726 | if (!cpumask_intersects(pmask, cpu_online_mask)) | ||
| 3727 | cpumask_copy(pmask, possible_mask); | ||
| 3728 | } | ||
| 3729 | |||
| 3730 | rcu_read_unlock(); | ||
| 3704 | spin_unlock_irqrestore(&callback_lock, flags); | 3731 | spin_unlock_irqrestore(&callback_lock, flags); |
| 3705 | } | 3732 | } |
| 3706 | 3733 | ||
| @@ -4813,19 +4813,17 @@ find_get_pmu_context(struct pmu *pmu, struct perf_event_context *ctx, · 4812 unmodified lines | |||
| 4813 | 4813 | ||
| 4814 | cpc = per_cpu_ptr(pmu->cpu_pmu_context, event->cpu); | 4814 | cpc = per_cpu_ptr(pmu->cpu_pmu_context, event->cpu); |
| 4815 | epc = &cpc->epc; | 4815 | epc = &cpc->epc; |
| 4816 | 4816 | raw_spin_lock_irq(&ctx->lock); | |
| 4817 | if (!epc->ctx) { | 4817 | if (!epc->ctx) { |
| 4818 | atomic_set(&epc->refcount, 1); | 4818 | atomic_set(&epc->refcount, 1); |
| 4819 | epc->embedded = 1; | 4819 | epc->embedded = 1; |
| 4820 | raw_spin_lock_irq(&ctx->lock); | ||
| 4821 | list_add(&epc->pmu_ctx_entry, &ctx->pmu_ctx_list); | 4820 | list_add(&epc->pmu_ctx_entry, &ctx->pmu_ctx_list); |
| 4822 | epc->ctx = ctx; | 4821 | epc->ctx = ctx; |
| 4823 | raw_spin_unlock_irq(&ctx->lock); | ||
| 4824 | } else { | 4822 | } else { |
| 4825 | WARN_ON_ONCE(epc->ctx != ctx); | 4823 | WARN_ON_ONCE(epc->ctx != ctx); |
| 4826 | atomic_inc(&epc->refcount); | 4824 | atomic_inc(&epc->refcount); |
| 4827 | } | 4825 | } |
| 4828 | 4826 | raw_spin_unlock_irq(&ctx->lock); | |
| 4829 | return epc; | 4827 | return epc; |
| 4830 | } | 4828 | } |
| 4831 | 4829 | ||
| @@ -4896,33 +4894,30 @@ static void free_epc_rcu(struct rcu_head *head) · 64 unmodified lines | |||
| 4896 | 4894 | ||
| 4897 | static void put_pmu_ctx(struct perf_event_pmu_context *epc) | 4895 | static void put_pmu_ctx(struct perf_event_pmu_context *epc) |
| 4898 | { | 4896 | { |
| 4897 | struct perf_event_context *ctx = epc->ctx; | ||
| 4899 | unsigned long flags; | 4898 | unsigned long flags; |
| 4900 | 4899 | ||
| 4901 | if (!atomic_dec_and_test(&epc->refcount)) | 4900 | /* |
| 4901 | * XXX | ||
| 4902 | * | ||
| 4903 | * lockdep_assert_held(&ctx->mutex); | ||
| 4904 | * | ||
| 4905 | * can't because of the call-site in _free_event()/put_event() | ||
| 4906 | * which isn't always called under ctx->mutex. | ||
| 4907 | */ | ||
| 4908 | if (!atomic_dec_and_raw_lock_irqsave(&epc->refcount, &ctx->lock, flags)) | ||
| 4902 | return; | 4909 | return; |
| 4903 | 4910 | ||
| 4904 | if (epc->ctx) { | 4911 | WARN_ON_ONCE(list_empty(&epc->pmu_ctx_entry)); |
| 4905 | struct perf_event_context *ctx = epc->ctx; | ||
| 4906 | 4912 | ||
| 4907 | /* | 4913 | list_del_init(&epc->pmu_ctx_entry); |
| 4908 | * XXX | 4914 | epc->ctx = NULL; |
| 4909 | * | ||
| 4910 | * lockdep_assert_held(&ctx->mutex); | ||
| 4911 | * | ||
| 4912 | * can't because of the call-site in _free_event()/put_event() | ||
| 4913 | * which isn't always called under ctx->mutex. | ||
| 4914 | */ | ||
| 4915 | |||
| 4916 | WARN_ON_ONCE(list_empty(&epc->pmu_ctx_entry)); | ||
| 4917 | raw_spin_lock_irqsave(&ctx->lock, flags); | ||
| 4918 | list_del_init(&epc->pmu_ctx_entry); | ||
| 4919 | epc->ctx = NULL; | ||
| 4920 | raw_spin_unlock_irqrestore(&ctx->lock, flags); | ||
| 4921 | } | ||
| 4922 | 4915 | ||
| 4923 | WARN_ON_ONCE(!list_empty(&epc->pinned_active)); | 4916 | WARN_ON_ONCE(!list_empty(&epc->pinned_active)); |
| 4924 | WARN_ON_ONCE(!list_empty(&epc->flexible_active)); | 4917 | WARN_ON_ONCE(!list_empty(&epc->flexible_active)); |
| 4925 | 4918 | ||
| 4919 | raw_spin_unlock_irqrestore(&ctx->lock, flags); | ||
| 4920 | |||
| 4926 | if (epc->embedded) | 4921 | if (epc->embedded) |
| 4927 | return; | 4922 | return; |
| 4928 | 4923 | ||
| @@ -1915,7 +1915,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d) · 1914 unmodified lines | |||
| 1915 | 1915 | ||
| 1916 | static void debugfs_remove_domain_dir(struct irq_domain *d) | 1916 | static void debugfs_remove_domain_dir(struct irq_domain *d) |
| 1917 | { | 1917 | { |
| 1918 | debugfs_remove(debugfs_lookup(d->name, domain_dir)); | 1918 | debugfs_lookup_and_remove(d->name, domain_dir); |
| 1919 | } | 1919 | } |
| 1920 | 1920 | ||
| 1921 | void __init irq_domain_debugfs_init(struct dentry *root) | 1921 | void __init irq_domain_debugfs_init(struct dentry *root) |
| @@ -9148,9 +9148,6 @@ buffer_percent_write(struct file *filp, const char __user *ubuf, · 9147 unmodified lines | |||
| 9148 | if (val > 100) | 9148 | if (val > 100) |
| 9149 | return -EINVAL; | 9149 | return -EINVAL; |
| 9150 | 9150 | ||
| 9151 | if (!val) | ||
| 9152 | val = 1; | ||
| 9153 | |||
| 9154 | tr->buffer_percent = val; | 9151 | tr->buffer_percent = val; |
| 9155 | 9152 | ||
| 9156 | (*ppos)++; | 9153 | (*ppos)++; |
| @@ -763,6 +763,7 @@ config DEBUG_KMEMLEAK · 762 unmodified lines | |||
| 763 | select KALLSYMS | 763 | select KALLSYMS |
| 764 | select CRC32 | 764 | select CRC32 |
| 765 | select STACKDEPOT | 765 | select STACKDEPOT |
| 766 | select STACKDEPOT_ALWAYS_INIT if !DEBUG_KMEMLEAK_DEFAULT_OFF | ||
| 766 | help | 767 | help |
| 767 | Say Y here if you want to enable the memory leak | 768 | Say Y here if you want to enable the memory leak |
| 768 | detector. The memory allocation/freeing is traced in a way | 769 | detector. The memory allocation/freeing is traced in a way |
| @@ -1216,7 +1217,7 @@ config SCHED_DEBUG · 447 unmodified lines | |||
| 1216 | depends on DEBUG_KERNEL && PROC_FS | 1217 | depends on DEBUG_KERNEL && PROC_FS |
| 1217 | default y | 1218 | default y |
| 1218 | help | 1219 | help |
| 1219 | If you say Y here, the /proc/sched_debug file will be provided | 1220 | If you say Y here, the /sys/kernel/debug/sched file will be provided |
| 1220 | that can help debug the scheduler. The runtime overhead of this | 1221 | that can help debug the scheduler. The runtime overhead of this |
| 1221 | option is minimal. | 1222 | option is minimal. |
| 1222 | 1223 | ||
| @@ -49,3 +49,34 @@ int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, · 48 unmodified lines | |||
| 49 | return 0; | 49 | return 0; |
| 50 | } | 50 | } |
| 51 | EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave); | 51 | EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave); |
| 52 | |||
| 53 | int _atomic_dec_and_raw_lock(atomic_t *atomic, raw_spinlock_t *lock) | ||
| 54 | { | ||
| 55 | /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ | ||
| 56 | if (atomic_add_unless(atomic, -1, 1)) | ||
| 57 | return 0; | ||
| 58 | |||
| 59 | /* Otherwise do it the slow way */ | ||
| 60 | raw_spin_lock(lock); | ||
| 61 | if (atomic_dec_and_test(atomic)) | ||
| 62 | return 1; | ||
| 63 | raw_spin_unlock(lock); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | EXPORT_SYMBOL(_atomic_dec_and_raw_lock); | ||
| 67 | |||
| 68 | int _atomic_dec_and_raw_lock_irqsave(atomic_t *atomic, raw_spinlock_t *lock, | ||
| 69 | unsigned long *flags) | ||
| 70 | { | ||
| 71 | /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ | ||
| 72 | if (atomic_add_unless(atomic, -1, 1)) | ||
| 73 | return 0; | ||
| 74 | |||
| 75 | /* Otherwise do it the slow way */ | ||
| 76 | raw_spin_lock_irqsave(lock, *flags); | ||
| 77 | if (atomic_dec_and_test(atomic)) | ||
| 78 | return 1; | ||
| 79 | raw_spin_unlock_irqrestore(lock, *flags); | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | EXPORT_SYMBOL(_atomic_dec_and_raw_lock_irqsave); | ||
| @@ -670,12 +670,13 @@ static inline unsigned long mte_pivot(const struct maple_enode *mn, · 669 unmodified lines | |||
| 670 | unsigned char piv) | 670 | unsigned char piv) |
| 671 | { | 671 | { |
| 672 | struct maple_node *node = mte_to_node(mn); | 672 | struct maple_node *node = mte_to_node(mn); |
| 673 | enum maple_type type = mte_node_type(mn); | ||
| 673 | 674 | ||
| 674 | if (piv >= mt_pivots[piv]) { | 675 | if (piv >= mt_pivots[type]) { |
| 675 | WARN_ON(1); | 676 | WARN_ON(1); |
| 676 | return 0; | 677 | return 0; |
| 677 | } | 678 | } |
| 678 | switch (mte_node_type(mn)) { | 679 | switch (type) { |
| 679 | case maple_arange_64: | 680 | case maple_arange_64: |
| 680 | return node->ma64.pivot[piv]; | 681 | return node->ma64.pivot[piv]; |
| 681 | case maple_range_64: | 682 | case maple_range_64: |
| @@ -4887,7 +4888,7 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 4205 unmodified lines | |||
| 4887 | unsigned long *pivots, *gaps; | 4888 | unsigned long *pivots, *gaps; |
| 4888 | void __rcu **slots; | 4889 | void __rcu **slots; |
| 4889 | unsigned long gap = 0; | 4890 | unsigned long gap = 0; |
| 4890 | unsigned long max, min, index; | 4891 | unsigned long max, min; |
| 4891 | unsigned char offset; | 4892 | unsigned char offset; |
| 4892 | 4893 | ||
| 4893 | if (unlikely(mas_is_err(mas))) | 4894 | if (unlikely(mas_is_err(mas))) |
| @@ -4909,8 +4910,7 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 15 unmodified lines | |||
| 4909 | min = mas_safe_min(mas, pivots, --offset); | 4910 | min = mas_safe_min(mas, pivots, --offset); |
| 4910 | 4911 | ||
| 4911 | max = mas_safe_pivot(mas, pivots, offset, type); | 4912 | max = mas_safe_pivot(mas, pivots, offset, type); |
| 4912 | index = mas->index; | 4913 | while (mas->index <= max) { |
| 4913 | while (index <= max) { | ||
| 4914 | gap = 0; | 4914 | gap = 0; |
| 4915 | if (gaps) | 4915 | if (gaps) |
| 4916 | gap = gaps[offset]; | 4916 | gap = gaps[offset]; |
| @@ -4941,10 +4941,8 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 24 unmodified lines | |||
| 4941 | min = mas_safe_min(mas, pivots, offset); | 4941 | min = mas_safe_min(mas, pivots, offset); |
| 4942 | } | 4942 | } |
| 4943 | 4943 | ||
| 4944 | if (unlikely(index > max)) { | 4944 | if (unlikely((mas->index > max) || (size - 1 > max - mas->index))) |
| 4945 | mas_set_err(mas, -EBUSY); | 4945 | goto no_space; |
| 4946 | return false; | ||
| 4947 | } | ||
| 4948 | 4946 | ||
| 4949 | if (unlikely(ma_is_leaf(type))) { | 4947 | if (unlikely(ma_is_leaf(type))) { |
| 4950 | mas->offset = offset; | 4948 | mas->offset = offset; |
| @@ -4961,9 +4959,11 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 10 unmodified lines | |||
| 4961 | return false; | 4959 | return false; |
| 4962 | 4960 | ||
| 4963 | ascend: | 4961 | ascend: |
| 4964 | if (mte_is_root(mas->node)) | 4962 | if (!mte_is_root(mas->node)) |
| 4965 | mas_set_err(mas, -EBUSY); | 4963 | return false; |
| 4966 | 4964 | ||
| 4965 | no_space: | ||
| 4966 | mas_set_err(mas, -EBUSY); | ||
| 4967 | return false; | 4967 | return false; |
| 4968 | } | 4968 | } |
| 4969 | 4969 | ||
| @@ -2517,6 +2517,91 @@ static noinline void check_bnode_min_spanning(struct maple_tree *mt) · 2516 unmodified lines | |||
| 2517 | mt_set_non_kernel(0); | 2517 | mt_set_non_kernel(0); |
| 2518 | } | 2518 | } |
| 2519 | 2519 | ||
| 2520 | static noinline void check_empty_area_window(struct maple_tree *mt) | ||
| 2521 | { | ||
| 2522 | unsigned long i, nr_entries = 20; | ||
| 2523 | MA_STATE(mas, mt, 0, 0); | ||
| 2524 | |||
| 2525 | for (i = 1; i <= nr_entries; i++) | ||
| 2526 | mtree_store_range(mt, i*10, i*10 + 9, | ||
| 2527 | xa_mk_value(i), GFP_KERNEL); | ||
| 2528 | |||
| 2529 | /* Create another hole besides the one at 0 */ | ||
| 2530 | mtree_store_range(mt, 160, 169, NULL, GFP_KERNEL); | ||
| 2531 | |||
| 2532 | /* Check lower bounds that don't fit */ | ||
| 2533 | rcu_read_lock(); | ||
| 2534 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 10) != -EBUSY); | ||
| 2535 | |||
| 2536 | mas_reset(&mas); | ||
| 2537 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 6, 90, 5) != -EBUSY); | ||
| 2538 | |||
| 2539 | /* Check lower bound that does fit */ | ||
| 2540 | mas_reset(&mas); | ||
| 2541 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 5) != 0); | ||
| 2542 | MT_BUG_ON(mt, mas.index != 5); | ||
| 2543 | MT_BUG_ON(mt, mas.last != 9); | ||
| 2544 | rcu_read_unlock(); | ||
| 2545 | |||
| 2546 | /* Check one gap that doesn't fit and one that does */ | ||
| 2547 | rcu_read_lock(); | ||
| 2548 | mas_reset(&mas); | ||
| 2549 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 217, 9) != 0); | ||
| 2550 | MT_BUG_ON(mt, mas.index != 161); | ||
| 2551 | MT_BUG_ON(mt, mas.last != 169); | ||
| 2552 | |||
| 2553 | /* Check one gap that does fit above the min */ | ||
| 2554 | mas_reset(&mas); | ||
| 2555 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 3) != 0); | ||
| 2556 | MT_BUG_ON(mt, mas.index != 216); | ||
| 2557 | MT_BUG_ON(mt, mas.last != 218); | ||
| 2558 | |||
| 2559 | /* Check size that doesn't fit any gap */ | ||
| 2560 | mas_reset(&mas); | ||
| 2561 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 16) != -EBUSY); | ||
| 2562 | |||
| 2563 | /* | ||
| 2564 | * Check size that doesn't fit the lower end of the window but | ||
| 2565 | * does fit the gap | ||
| 2566 | */ | ||
| 2567 | mas_reset(&mas); | ||
| 2568 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 167, 200, 4) != -EBUSY); | ||
| 2569 | |||
| 2570 | /* | ||
| 2571 | * Check size that doesn't fit the upper end of the window but | ||
| 2572 | * does fit the gap | ||
| 2573 | */ | ||
| 2574 | mas_reset(&mas); | ||
| 2575 | MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 162, 4) != -EBUSY); | ||
| 2576 | |||
| 2577 | /* Check mas_empty_area forward */ | ||
| 2578 | mas_reset(&mas); | ||
| 2579 | MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 9) != 0); | ||
| 2580 | MT_BUG_ON(mt, mas.index != 0); | ||
| 2581 | MT_BUG_ON(mt, mas.last != 8); | ||
| 2582 | |||
| 2583 | mas_reset(&mas); | ||
| 2584 | MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 4) != 0); | ||
| 2585 | MT_BUG_ON(mt, mas.index != 0); | ||
| 2586 | MT_BUG_ON(mt, mas.last != 3); | ||
| 2587 | |||
| 2588 | mas_reset(&mas); | ||
| 2589 | MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 11) != -EBUSY); | ||
| 2590 | |||
| 2591 | mas_reset(&mas); | ||
| 2592 | MT_BUG_ON(mt, mas_empty_area(&mas, 5, 100, 6) != -EBUSY); | ||
| 2593 | |||
| 2594 | mas_reset(&mas); | ||
| 2595 | MT_BUG_ON(mt, mas_empty_area(&mas, 0, 8, 10) != -EBUSY); | ||
| 2596 | |||
| 2597 | mas_reset(&mas); | ||
| 2598 | mas_empty_area(&mas, 100, 165, 3); | ||
| 2599 | |||
| 2600 | mas_reset(&mas); | ||
| 2601 | MT_BUG_ON(mt, mas_empty_area(&mas, 100, 163, 6) != -EBUSY); | ||
| 2602 | rcu_read_unlock(); | ||
| 2603 | } | ||
| 2604 | |||
| 2520 | static DEFINE_MTREE(tree); | 2605 | static DEFINE_MTREE(tree); |
| 2521 | static int maple_tree_seed(void) | 2606 | static int maple_tree_seed(void) |
| 2522 | { | 2607 | { |
| @@ -2765,6 +2850,10 @@ static int maple_tree_seed(void) · 242 unmodified lines | |||
| 2765 | check_bnode_min_spanning(&tree); | 2850 | check_bnode_min_spanning(&tree); |
| 2766 | mtree_destroy(&tree); | 2851 | mtree_destroy(&tree); |
| 2767 | 2852 | ||
| 2853 | mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); | ||
| 2854 | check_empty_area_window(&tree); | ||
| 2855 | mtree_destroy(&tree); | ||
| 2856 | |||
| 2768 | #if defined(BENCH) | 2857 | #if defined(BENCH) |
| 2769 | skip: | 2858 | skip: |
| 2770 | #endif | 2859 | #endif |
| @@ -5051,6 +5051,9 @@ again: · 5050 unmodified lines | |||
| 5051 | entry = huge_pte_clear_uffd_wp(entry); | 5051 | entry = huge_pte_clear_uffd_wp(entry); |
| 5052 | set_huge_pte_at(dst, addr, dst_pte, entry); | 5052 | set_huge_pte_at(dst, addr, dst_pte, entry); |
| 5053 | } else if (unlikely(is_pte_marker(entry))) { | 5053 | } else if (unlikely(is_pte_marker(entry))) { |
| 5054 | /* No swap on hugetlb */ | ||
| 5055 | WARN_ON_ONCE( | ||
| 5056 | is_swapin_error_entry(pte_to_swp_entry(entry))); | ||
| 5054 | /* | 5057 | /* |
| 5055 | * We copy the pte marker only if the dst vma has | 5058 | * We copy the pte marker only if the dst vma has |
| 5056 | * uffd-wp enabled. | 5059 | * uffd-wp enabled. |
| @@ -847,6 +847,10 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address, · 846 unmodified lines | |||
| 847 | return SCAN_SUCCEED; | 847 | return SCAN_SUCCEED; |
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | /* | ||
| 851 | * See pmd_trans_unstable() for how the result may change out from | ||
| 852 | * underneath us, even if we hold mmap_lock in read. | ||
| 853 | */ | ||
| 850 | static int find_pmd_or_thp_or_none(struct mm_struct *mm, | 854 | static int find_pmd_or_thp_or_none(struct mm_struct *mm, |
| 851 | unsigned long address, | 855 | unsigned long address, |
| 852 | pmd_t **pmd) | 856 | pmd_t **pmd) |
| @@ -865,8 +869,12 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm, · 12 unmodified lines | |||
| 865 | #endif | 869 | #endif |
| 866 | if (pmd_none(pmde)) | 870 | if (pmd_none(pmde)) |
| 867 | return SCAN_PMD_NONE; | 871 | return SCAN_PMD_NONE; |
| 872 | if (!pmd_present(pmde)) | ||
| 873 | return SCAN_PMD_NULL; | ||
| 868 | if (pmd_trans_huge(pmde)) | 874 | if (pmd_trans_huge(pmde)) |
| 869 | return SCAN_PMD_MAPPED; | 875 | return SCAN_PMD_MAPPED; |
| 876 | if (pmd_devmap(pmde)) | ||
| 877 | return SCAN_PMD_NULL; | ||
| 870 | if (pmd_bad(pmde)) | 878 | if (pmd_bad(pmde)) |
| 871 | return SCAN_PMD_NULL; | 879 | return SCAN_PMD_NULL; |
| 872 | return SCAN_SUCCEED; | 880 | return SCAN_SUCCEED; |
| @@ -1642,7 +1650,7 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, · 769 unmodified lines | |||
| 1642 | * has higher cost too. It would also probably require locking | 1650 | * has higher cost too. It would also probably require locking |
| 1643 | * the anon_vma. | 1651 | * the anon_vma. |
| 1644 | */ | 1652 | */ |
| 1645 | if (vma->anon_vma) { | 1653 | if (READ_ONCE(vma->anon_vma)) { |
| 1646 | result = SCAN_PAGE_ANON; | 1654 | result = SCAN_PAGE_ANON; |
| 1647 | goto next; | 1655 | goto next; |
| 1648 | } | 1656 | } |
| @@ -1670,6 +1678,18 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, · 21 unmodified lines | |||
| 1670 | result = SCAN_PTE_MAPPED_HUGEPAGE; | 1678 | result = SCAN_PTE_MAPPED_HUGEPAGE; |
| 1671 | if ((cc->is_khugepaged || is_target) && | 1679 | if ((cc->is_khugepaged || is_target) && |
| 1672 | mmap_write_trylock(mm)) { | 1680 | mmap_write_trylock(mm)) { |
| 1681 | /* | ||
| 1682 | * Re-check whether we have an ->anon_vma, because | ||
| 1683 | * collapse_and_free_pmd() requires that either no | ||
| 1684 | * ->anon_vma exists or the anon_vma is locked. | ||
| 1685 | * We already checked ->anon_vma above, but that check | ||
| 1686 | * is racy because ->anon_vma can be populated under the | ||
| 1687 | * mmap lock in read mode. | ||
| 1688 | */ | ||
| 1689 | if (vma->anon_vma) { | ||
| 1690 | result = SCAN_PAGE_ANON; | ||
| 1691 | goto unlock_next; | ||
| 1692 | } | ||
| 1673 | /* | 1693 | /* |
| 1674 | * When a vma is registered with uffd-wp, we can't | 1694 | * When a vma is registered with uffd-wp, we can't |
| 1675 | * recycle the pmd pgtable because there can be pte | 1695 | * recycle the pmd pgtable because there can be pte |
| @@ -2070,8 +2070,10 @@ static int __init kmemleak_boot_config(char *str) · 2069 unmodified lines | |||
| 2070 | return -EINVAL; | 2070 | return -EINVAL; |
| 2071 | if (strcmp(str, "off") == 0) | 2071 | if (strcmp(str, "off") == 0) |
| 2072 | kmemleak_disable(); | 2072 | kmemleak_disable(); |
| 2073 | else if (strcmp(str, "on") == 0) | 2073 | else if (strcmp(str, "on") == 0) { |
| 2074 | kmemleak_skip_disable = 1; | 2074 | kmemleak_skip_disable = 1; |
| 2075 | stack_depot_want_early_init(); | ||
| 2076 | } | ||
| 2075 | else | 2077 | else |
| 2076 | return -EINVAL; | 2078 | return -EINVAL; |
| 2077 | return 0; | 2079 | return 0; |
| @@ -2093,7 +2095,6 @@ void __init kmemleak_init(void) · 15 unmodified lines | |||
| 2093 | if (kmemleak_error) | 2095 | if (kmemleak_error) |
| 2094 | return; | 2096 | return; |
| 2095 | 2097 | ||
| 2096 | stack_depot_init(); | ||
| 2097 | jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE); | 2098 | jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE); |
| 2098 | jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000); | 2099 | jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000); |
| 2099 | 2100 | ||
| @@ -63,7 +63,6 @@ · 62 unmodified lines | |||
| 63 | #include <linux/resume_user_mode.h> | 63 | #include <linux/resume_user_mode.h> |
| 64 | #include <linux/psi.h> | 64 | #include <linux/psi.h> |
| 65 | #include <linux/seq_buf.h> | 65 | #include <linux/seq_buf.h> |
| 66 | #include <linux/parser.h> | ||
| 67 | #include "internal.h" | 66 | #include "internal.h" |
| 68 | #include <net/sock.h> | 67 | #include <net/sock.h> |
| 69 | #include <net/ip.h> | 68 | #include <net/ip.h> |
| @@ -2393,8 +2392,7 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg, · 2323 unmodified lines | |||
| 2393 | psi_memstall_enter(&pflags); | 2392 | psi_memstall_enter(&pflags); |
| 2394 | nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages, | 2393 | nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages, |
| 2395 | gfp_mask, | 2394 | gfp_mask, |
| 2396 | MEMCG_RECLAIM_MAY_SWAP, | 2395 | MEMCG_RECLAIM_MAY_SWAP); |
| 2397 | NULL); | ||
| 2398 | psi_memstall_leave(&pflags); | 2396 | psi_memstall_leave(&pflags); |
| 2399 | } while ((memcg = parent_mem_cgroup(memcg)) && | 2397 | } while ((memcg = parent_mem_cgroup(memcg)) && |
| 2400 | !mem_cgroup_is_root(memcg)); | 2398 | !mem_cgroup_is_root(memcg)); |
| @@ -2685,8 +2683,7 @@ retry: · 284 unmodified lines | |||
| 2685 | 2683 | ||
| 2686 | psi_memstall_enter(&pflags); | 2684 | psi_memstall_enter(&pflags); |
| 2687 | nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages, | 2685 | nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages, |
| 2688 | gfp_mask, reclaim_options, | 2686 | gfp_mask, reclaim_options); |
| 2689 | NULL); | ||
| 2690 | psi_memstall_leave(&pflags); | 2687 | psi_memstall_leave(&pflags); |
| 2691 | 2688 | ||
| 2692 | if (mem_cgroup_margin(mem_over_limit) >= nr_pages) | 2689 | if (mem_cgroup_margin(mem_over_limit) >= nr_pages) |
| @@ -3506,8 +3503,7 @@ static int mem_cgroup_resize_max(struct mem_cgroup *memcg, · 813 unmodified lines | |||
| 3506 | } | 3503 | } |
| 3507 | 3504 | ||
| 3508 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, | 3505 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, |
| 3509 | memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP, | 3506 | memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP)) { |
| 3510 | NULL)) { | ||
| 3511 | ret = -EBUSY; | 3507 | ret = -EBUSY; |
| 3512 | break; | 3508 | break; |
| 3513 | } | 3509 | } |
| @@ -3618,8 +3614,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg) · 104 unmodified lines | |||
| 3618 | return -EINTR; | 3614 | return -EINTR; |
| 3619 | 3615 | ||
| 3620 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, | 3616 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, |
| 3621 | MEMCG_RECLAIM_MAY_SWAP, | 3617 | MEMCG_RECLAIM_MAY_SWAP)) |
| 3622 | NULL)) | ||
| 3623 | nr_retries--; | 3618 | nr_retries--; |
| 3624 | } | 3619 | } |
| 3625 | 3620 | ||
| @@ -6429,8 +6424,7 @@ static ssize_t memory_high_write(struct kernfs_open_file *of, · 2803 unmodified lines | |||
| 6429 | } | 6424 | } |
| 6430 | 6425 | ||
| 6431 | reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high, | 6426 | reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high, |
| 6432 | GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP, | 6427 | GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP); |
| 6433 | NULL); | ||
| 6434 | 6428 | ||
| 6435 | if (!reclaimed && !nr_retries--) | 6429 | if (!reclaimed && !nr_retries--) |
| 6436 | break; | 6430 | break; |
| @@ -6479,8 +6473,7 @@ static ssize_t memory_max_write(struct kernfs_open_file *of, · 42 unmodified lines | |||
| 6479 | 6473 | ||
| 6480 | if (nr_reclaims) { | 6474 | if (nr_reclaims) { |
| 6481 | if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max, | 6475 | if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max, |
| 6482 | GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP, | 6476 | GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP)) |
| 6483 | NULL)) | ||
| 6484 | nr_reclaims--; | 6477 | nr_reclaims--; |
| 6485 | continue; | 6478 | continue; |
| 6486 | } | 6479 | } |
| @@ -6603,54 +6596,21 @@ static ssize_t memory_oom_group_write(struct kernfs_open_file *of, · 116 unmodified lines | |||
| 6603 | return nbytes; | 6596 | return nbytes; |
| 6604 | } | 6597 | } |
| 6605 | 6598 | ||
| 6606 | enum { | ||
| 6607 | MEMORY_RECLAIM_NODES = 0, | ||
| 6608 | MEMORY_RECLAIM_NULL, | ||
| 6609 | }; | ||
| 6610 | |||
| 6611 | static const match_table_t if_tokens = { | ||
| 6612 | { MEMORY_RECLAIM_NODES, "nodes=%s" }, | ||
| 6613 | { MEMORY_RECLAIM_NULL, NULL }, | ||
| 6614 | }; | ||
| 6615 | |||
| 6616 | static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, | 6599 | static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, |
| 6617 | size_t nbytes, loff_t off) | 6600 | size_t nbytes, loff_t off) |
| 6618 | { | 6601 | { |
| 6619 | struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); | 6602 | struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); |
| 6620 | unsigned int nr_retries = MAX_RECLAIM_RETRIES; | 6603 | unsigned int nr_retries = MAX_RECLAIM_RETRIES; |
| 6621 | unsigned long nr_to_reclaim, nr_reclaimed = 0; | 6604 | unsigned long nr_to_reclaim, nr_reclaimed = 0; |
| 6622 | unsigned int reclaim_options = MEMCG_RECLAIM_MAY_SWAP | | 6605 | unsigned int reclaim_options; |
| 6623 | MEMCG_RECLAIM_PROACTIVE; | 6606 | int err; |
| 6624 | char *old_buf, *start; | ||
| 6625 | substring_t args[MAX_OPT_ARGS]; | ||
| 6626 | int token; | ||
| 6627 | char value[256]; | ||
| 6628 | nodemask_t nodemask = NODE_MASK_ALL; | ||
| 6629 | |||
| 6630 | buf = strstrip(buf); | ||
| 6631 | |||
| 6632 | old_buf = buf; | ||
| 6633 | nr_to_reclaim = memparse(buf, &buf) / PAGE_SIZE; | ||
| 6634 | if (buf == old_buf) | ||
| 6635 | return -EINVAL; | ||
| 6636 | 6607 | ||
| 6637 | buf = strstrip(buf); | 6608 | buf = strstrip(buf); |
| 6609 | err = page_counter_memparse(buf, "", &nr_to_reclaim); | ||
| 6610 | if (err) | ||
| 6611 | return err; | ||
| 6638 | 6612 | ||
| 6639 | while ((start = strsep(&buf, " ")) != NULL) { | 6613 | reclaim_options = MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_PROACTIVE; |
| 6640 | if (!strlen(start)) | ||
| 6641 | continue; | ||
| 6642 | token = match_token(start, if_tokens, args); | ||
| 6643 | match_strlcpy(value, args, sizeof(value)); | ||
| 6644 | switch (token) { | ||
| 6645 | case MEMORY_RECLAIM_NODES: | ||
| 6646 | if (nodelist_parse(value, nodemask) < 0) | ||
| 6647 | return -EINVAL; | ||
| 6648 | break; | ||
| 6649 | default: | ||
| 6650 | return -EINVAL; | ||
| 6651 | } | ||
| 6652 | } | ||
| 6653 | |||
| 6654 | while (nr_reclaimed < nr_to_reclaim) { | 6614 | while (nr_reclaimed < nr_to_reclaim) { |
| 6655 | unsigned long reclaimed; | 6615 | unsigned long reclaimed; |
| 6656 | 6616 | ||
| @@ -6667,8 +6627,7 @@ static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, · 10 unmodified lines | |||
| 6667 | 6627 | ||
| 6668 | reclaimed = try_to_free_mem_cgroup_pages(memcg, | 6628 | reclaimed = try_to_free_mem_cgroup_pages(memcg, |
| 6669 | nr_to_reclaim - nr_reclaimed, | 6629 | nr_to_reclaim - nr_reclaimed, |
| 6670 | GFP_KERNEL, reclaim_options, | 6630 | GFP_KERNEL, reclaim_options); |
| 6671 | &nodemask); | ||
| 6672 | 6631 | ||
| 6673 | if (!reclaimed && !nr_retries--) | 6632 | if (!reclaimed && !nr_retries--) |
| 6674 | return -EAGAIN; | 6633 | return -EAGAIN; |
| @@ -828,12 +828,8 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, · 827 unmodified lines | |||
| 828 | return -EBUSY; | 828 | return -EBUSY; |
| 829 | return -ENOENT; | 829 | return -ENOENT; |
| 830 | } else if (is_pte_marker_entry(entry)) { | 830 | } else if (is_pte_marker_entry(entry)) { |
| 831 | /* | 831 | if (is_swapin_error_entry(entry) || userfaultfd_wp(dst_vma)) |
| 832 | * We're copying the pgtable should only because dst_vma has | 832 | set_pte_at(dst_mm, addr, dst_pte, pte); |
| 833 | * uffd-wp enabled, do sanity check. | ||
| 834 | */ | ||
| 835 | WARN_ON_ONCE(!userfaultfd_wp(dst_vma)); | ||
| 836 | set_pte_at(dst_mm, addr, dst_pte, pte); | ||
| 837 | return 0; | 833 | return 0; |
| 838 | } | 834 | } |
| 839 | if (!userfaultfd_wp(dst_vma)) | 835 | if (!userfaultfd_wp(dst_vma)) |
| @@ -3629,8 +3625,12 @@ static vm_fault_t pte_marker_clear(struct vm_fault *vmf) · 2789 unmodified lines | |||
| 3629 | /* | 3625 | /* |
| 3630 | * Be careful so that we will only recover a special uffd-wp pte into a | 3626 | * Be careful so that we will only recover a special uffd-wp pte into a |
| 3631 | * none pte. Otherwise it means the pte could have changed, so retry. | 3627 | * none pte. Otherwise it means the pte could have changed, so retry. |
| 3628 | * | ||
| 3629 | * This should also cover the case where e.g. the pte changed | ||
| 3630 | * quickly from a PTE_MARKER_UFFD_WP into PTE_MARKER_SWAPIN_ERROR. | ||
| 3631 | * So is_pte_marker() check is not enough to safely drop the pte. | ||
| 3632 | */ | 3632 | */ |
| 3633 | if (is_pte_marker(*vmf->pte)) | 3633 | if (pte_same(vmf->orig_pte, *vmf->pte)) |
| 3634 | pte_clear(vmf->vma->vm_mm, vmf->address, vmf->pte); | 3634 | pte_clear(vmf->vma->vm_mm, vmf->address, vmf->pte); |
| 3635 | pte_unmap_unlock(vmf->pte, vmf->ptl); | 3635 | pte_unmap_unlock(vmf->pte, vmf->ptl); |
| 3636 | return 0; | 3636 | return 0; |
| @@ -600,7 +600,8 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask, · 599 unmodified lines | |||
| 600 | 600 | ||
| 601 | /* With MPOL_MF_MOVE, we migrate only unshared hugepage. */ | 601 | /* With MPOL_MF_MOVE, we migrate only unshared hugepage. */ |
| 602 | if (flags & (MPOL_MF_MOVE_ALL) || | 602 | if (flags & (MPOL_MF_MOVE_ALL) || |
| 603 | (flags & MPOL_MF_MOVE && page_mapcount(page) == 1)) { | 603 | (flags & MPOL_MF_MOVE && page_mapcount(page) == 1 && |
| 604 | !hugetlb_pmd_shared(pte))) { | ||
| 604 | if (isolate_hugetlb(page, qp->pagelist) && | 605 | if (isolate_hugetlb(page, qp->pagelist) && |
| 605 | (flags & MPOL_MF_STRICT)) | 606 | (flags & MPOL_MF_STRICT)) |
| 606 | /* | 607 | /* |
| @@ -245,7 +245,13 @@ static unsigned long change_pte_range(struct mmu_gather *tlb, · 244 unmodified lines | |||
| 245 | newpte = pte_swp_mksoft_dirty(newpte); | 245 | newpte = pte_swp_mksoft_dirty(newpte); |
| 246 | if (pte_swp_uffd_wp(oldpte)) | 246 | if (pte_swp_uffd_wp(oldpte)) |
| 247 | newpte = pte_swp_mkuffd_wp(newpte); | 247 | newpte = pte_swp_mkuffd_wp(newpte); |
| 248 | } else if (pte_marker_entry_uffd_wp(entry)) { | 248 | } else if (is_pte_marker_entry(entry)) { |
| 249 | /* | ||
| 250 | * Ignore swapin errors unconditionally, | ||
| 251 | * because any access should sigbus anyway. | ||
| 252 | */ | ||
| 253 | if (is_swapin_error_entry(entry)) | ||
| 254 | continue; | ||
| 249 | /* | 255 | /* |
| 250 | * If this is uffd-wp pte marker and we'd like | 256 | * If this is uffd-wp pte marker and we'd like |
| 251 | * to unprotect it, drop it; the next page | 257 | * to unprotect it, drop it; the next page |
| @@ -1027,16 +1027,29 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, · 1026 unmodified lines | |||
| 1027 | } | 1027 | } |
| 1028 | 1028 | ||
| 1029 | /* | 1029 | /* |
| 1030 | * Function vma_merge() is called on the extension we are adding to | 1030 | * Function vma_merge() is called on the extension we |
| 1031 | * the already existing vma, vma_merge() will merge this extension with | 1031 | * are adding to the already existing vma, vma_merge() |
| 1032 | * the already existing vma (expand operation itself) and possibly also | 1032 | * will merge this extension with the already existing |
| 1033 | * with the next vma if it becomes adjacent to the expanded vma and | 1033 | * vma (expand operation itself) and possibly also with |
| 1034 | * otherwise compatible. | 1034 | * the next vma if it becomes adjacent to the expanded |
| 1035 | * vma and otherwise compatible. | ||
| 1036 | * | ||
| 1037 | * However, vma_merge() can currently fail due to | ||
| 1038 | * is_mergeable_vma() check for vm_ops->close (see the | ||
| 1039 | * comment there). Yet this should not prevent vma | ||
| 1040 | * expanding, so perform a simple expand for such vma. | ||
| 1041 | * Ideally the check for close op should be only done | ||
| 1042 | * when a vma would be actually removed due to a merge. | ||
| 1035 | */ | 1043 | */ |
| 1036 | vma = vma_merge(mm, vma, extension_start, extension_end, | 1044 | if (!vma->vm_ops || !vma->vm_ops->close) { |
| 1045 | vma = vma_merge(mm, vma, extension_start, extension_end, | ||
| 1037 | vma->vm_flags, vma->anon_vma, vma->vm_file, | 1046 | vma->vm_flags, vma->anon_vma, vma->vm_file, |
| 1038 | extension_pgoff, vma_policy(vma), | 1047 | extension_pgoff, vma_policy(vma), |
| 1039 | vma->vm_userfaultfd_ctx, anon_vma_name(vma)); | 1048 | vma->vm_userfaultfd_ctx, anon_vma_name(vma)); |
| 1049 | } else if (vma_adjust(vma, vma->vm_start, addr + new_len, | ||
| 1050 | vma->vm_pgoff, NULL)) { | ||
| 1051 | vma = NULL; | ||
| 1052 | } | ||
| 1040 | if (!vma) { | 1053 | if (!vma) { |
| 1041 | vm_unacct_memory(pages); | 1054 | vm_unacct_memory(pages); |
| 1042 | ret = -ENOMEM; | 1055 | ret = -ENOMEM; |
| @@ -1100,6 +1100,7 @@ start_over: · 1099 unmodified lines | |||
| 1100 | goto check_out; | 1100 | goto check_out; |
| 1101 | pr_debug("scan_swap_map of si %d failed to find offset\n", | 1101 | pr_debug("scan_swap_map of si %d failed to find offset\n", |
| 1102 | si->type); | 1102 | si->type); |
| 1103 | cond_resched(); | ||
| 1103 | 1104 | ||
| 1104 | spin_lock(&swap_avail_lock); | 1105 | spin_lock(&swap_avail_lock); |
| 1105 | nextsi: | 1106 | nextsi: |
| @@ -3323,13 +3323,16 @@ void lru_gen_migrate_mm(struct mm_struct *mm) · 3322 unmodified lines | |||
| 3323 | if (mem_cgroup_disabled()) | 3323 | if (mem_cgroup_disabled()) |
| 3324 | return; | 3324 | return; |
| 3325 | 3325 | ||
| 3326 | /* migration can happen before addition */ | ||
| 3327 | if (!mm->lru_gen.memcg) | ||
| 3328 | return; | ||
| 3329 | |||
| 3326 | rcu_read_lock(); | 3330 | rcu_read_lock(); |
| 3327 | memcg = mem_cgroup_from_task(task); | 3331 | memcg = mem_cgroup_from_task(task); |
| 3328 | rcu_read_unlock(); | 3332 | rcu_read_unlock(); |
| 3329 | if (memcg == mm->lru_gen.memcg) | 3333 | if (memcg == mm->lru_gen.memcg) |
| 3330 | return; | 3334 | return; |
| 3331 | 3335 | ||
| 3332 | VM_WARN_ON_ONCE(!mm->lru_gen.memcg); | ||
| 3333 | VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list)); | 3336 | VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list)); |
| 3334 | 3337 | ||
| 3335 | lru_gen_del_mm(mm); | 3338 | lru_gen_del_mm(mm); |
| @@ -6754,8 +6757,7 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg, · 3418 unmodified lines | |||
| 6754 | unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, | 6757 | unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, |
| 6755 | unsigned long nr_pages, | 6758 | unsigned long nr_pages, |
| 6756 | gfp_t gfp_mask, | 6759 | gfp_t gfp_mask, |
| 6757 | unsigned int reclaim_options, | 6760 | unsigned int reclaim_options) |
| 6758 | nodemask_t *nodemask) | ||
| 6759 | { | 6761 | { |
| 6760 | unsigned long nr_reclaimed; | 6762 | unsigned long nr_reclaimed; |
| 6761 | unsigned int noreclaim_flag; | 6763 | unsigned int noreclaim_flag; |
| @@ -6770,7 +6772,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, · 8 unmodified lines | |||
| 6770 | .may_unmap = 1, | 6772 | .may_unmap = 1, |
| 6771 | .may_swap = !!(reclaim_options & MEMCG_RECLAIM_MAY_SWAP), | 6773 | .may_swap = !!(reclaim_options & MEMCG_RECLAIM_MAY_SWAP), |
| 6772 | .proactive = !!(reclaim_options & MEMCG_RECLAIM_PROACTIVE), | 6774 | .proactive = !!(reclaim_options & MEMCG_RECLAIM_PROACTIVE), |
| 6773 | .nodemask = nodemask, | ||
| 6774 | }; | 6775 | }; |
| 6775 | /* | 6776 | /* |
| 6776 | * Traverse the ZONELIST_FALLBACK zonelist of the current node to put | 6777 | * Traverse the ZONELIST_FALLBACK zonelist of the current node to put |
| @@ -113,7 +113,23 @@ · 112 unmodified lines | |||
| 113 | * have room for two bit at least. | 113 | * have room for two bit at least. |
| 114 | */ | 114 | */ |
| 115 | #define OBJ_ALLOCATED_TAG 1 | 115 | #define OBJ_ALLOCATED_TAG 1 |
| 116 | #define OBJ_TAG_BITS 1 | 116 | |
| 117 | #ifdef CONFIG_ZPOOL | ||
| 118 | /* | ||
| 119 | * The second least-significant bit in the object's header identifies if the | ||
| 120 | * value stored at the header is a deferred handle from the last reclaim | ||
| 121 | * attempt. | ||
| 122 | * | ||
| 123 | * As noted above, this is valid because we have room for two bits. | ||
| 124 | */ | ||
| 125 | #define OBJ_DEFERRED_HANDLE_TAG 2 | ||
| 126 | #define OBJ_TAG_BITS 2 | ||
| 127 | #define OBJ_TAG_MASK (OBJ_ALLOCATED_TAG | OBJ_DEFERRED_HANDLE_TAG) | ||
| 128 | #else | ||
| 129 | #define OBJ_TAG_BITS 1 | ||
| 130 | #define OBJ_TAG_MASK OBJ_ALLOCATED_TAG | ||
| 131 | #endif /* CONFIG_ZPOOL */ | ||
| 132 | |||
| 117 | #define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS - OBJ_TAG_BITS) | 133 | #define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS - OBJ_TAG_BITS) |
| 118 | #define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1) | 134 | #define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1) |
| 119 | 135 | ||
| @@ -222,6 +238,12 @@ struct link_free { · 102 unmodified lines | |||
| 222 | * Handle of allocated object. | 238 | * Handle of allocated object. |
| 223 | */ | 239 | */ |
| 224 | unsigned long handle; | 240 | unsigned long handle; |
| 241 | #ifdef CONFIG_ZPOOL | ||
| 242 | /* | ||
| 243 | * Deferred handle of a reclaimed object. | ||
| 244 | */ | ||
| 245 | unsigned long deferred_handle; | ||
| 246 | #endif | ||
| 225 | }; | 247 | }; |
| 226 | }; | 248 | }; |
| 227 | 249 | ||
| @@ -272,8 +294,6 @@ struct zspage { · 44 unmodified lines | |||
| 272 | /* links the zspage to the lru list in the pool */ | 294 | /* links the zspage to the lru list in the pool */ |
| 273 | struct list_head lru; | 295 | struct list_head lru; |
| 274 | bool under_reclaim; | 296 | bool under_reclaim; |
| 275 | /* list of unfreed handles whose objects have been reclaimed */ | ||
| 276 | unsigned long *deferred_handles; | ||
| 277 | #endif | 297 | #endif |
| 278 | 298 | ||
| 279 | struct zs_pool *pool; | 299 | struct zs_pool *pool; |
| @@ -897,7 +917,8 @@ static unsigned long handle_to_obj(unsigned long handle) · 617 unmodified lines | |||
| 897 | return *(unsigned long *)handle; | 917 | return *(unsigned long *)handle; |
| 898 | } | 918 | } |
| 899 | 919 | ||
| 900 | static bool obj_allocated(struct page *page, void *obj, unsigned long *phandle) | 920 | static bool obj_tagged(struct page *page, void *obj, unsigned long *phandle, |
| 921 | int tag) | ||
| 901 | { | 922 | { |
| 902 | unsigned long handle; | 923 | unsigned long handle; |
| 903 | struct zspage *zspage = get_zspage(page); | 924 | struct zspage *zspage = get_zspage(page); |
| @@ -908,13 +929,27 @@ static bool obj_allocated(struct page *page, void *obj, unsigned long *phandle) · 4 unmodified lines | |||
| 908 | } else | 929 | } else |
| 909 | handle = *(unsigned long *)obj; | 930 | handle = *(unsigned long *)obj; |
| 910 | 931 | ||
| 911 | if (!(handle & OBJ_ALLOCATED_TAG)) | 932 | if (!(handle & tag)) |
| 912 | return false; | 933 | return false; |
| 913 | 934 | ||
| 914 | *phandle = handle & ~OBJ_ALLOCATED_TAG; | 935 | /* Clear all tags before returning the handle */ |
| 936 | *phandle = handle & ~OBJ_TAG_MASK; | ||
| 915 | return true; | 937 | return true; |
| 916 | } | 938 | } |
| 917 | 939 | ||
| 940 | static inline bool obj_allocated(struct page *page, void *obj, unsigned long *phandle) | ||
| 941 | { | ||
| 942 | return obj_tagged(page, obj, phandle, OBJ_ALLOCATED_TAG); | ||
| 943 | } | ||
| 944 | |||
| 945 | #ifdef CONFIG_ZPOOL | ||
| 946 | static bool obj_stores_deferred_handle(struct page *page, void *obj, | ||
| 947 | unsigned long *phandle) | ||
| 948 | { | ||
| 949 | return obj_tagged(page, obj, phandle, OBJ_DEFERRED_HANDLE_TAG); | ||
| 950 | } | ||
| 951 | #endif | ||
| 952 | |||
| 918 | static void reset_page(struct page *page) | 953 | static void reset_page(struct page *page) |
| 919 | { | 954 | { |
| 920 | __ClearPageMovable(page); | 955 | __ClearPageMovable(page); |
| @@ -946,22 +981,36 @@ unlock: · 25 unmodified lines | |||
| 946 | } | 981 | } |
| 947 | 982 | ||
| 948 | #ifdef CONFIG_ZPOOL | 983 | #ifdef CONFIG_ZPOOL |
| 984 | static unsigned long find_deferred_handle_obj(struct size_class *class, | ||
| 985 | struct page *page, int *obj_idx); | ||
| 986 | |||
| 949 | /* | 987 | /* |
| 950 | * Free all the deferred handles whose objects are freed in zs_free. | 988 | * Free all the deferred handles whose objects are freed in zs_free. |
| 951 | */ | 989 | */ |
| 952 | static void free_handles(struct zs_pool *pool, struct zspage *zspage) | 990 | static void free_handles(struct zs_pool *pool, struct size_class *class, |
| 991 | struct zspage *zspage) | ||
| 953 | { | 992 | { |
| 954 | unsigned long handle = (unsigned long)zspage->deferred_handles; | 993 | int obj_idx = 0; |
| 994 | struct page *page = get_first_page(zspage); | ||
| 995 | unsigned long handle; | ||
| 955 | 996 | ||
| 956 | while (handle) { | 997 | while (1) { |
| 957 | unsigned long nxt_handle = handle_to_obj(handle); | 998 | handle = find_deferred_handle_obj(class, page, &obj_idx); |
| 999 | if (!handle) { | ||
| 1000 | page = get_next_page(page); | ||
| 1001 | if (!page) | ||
| 1002 | break; | ||
| 1003 | obj_idx = 0; | ||
| 1004 | continue; | ||
| 1005 | } | ||
| 958 | 1006 | ||
| 959 | cache_free_handle(pool, handle); | 1007 | cache_free_handle(pool, handle); |
| 960 | handle = nxt_handle; | 1008 | obj_idx++; |
| 961 | } | 1009 | } |
| 962 | } | 1010 | } |
| 963 | #else | 1011 | #else |
| 964 | static inline void free_handles(struct zs_pool *pool, struct zspage *zspage) {} | 1012 | static inline void free_handles(struct zs_pool *pool, struct size_class *class, |
| 1013 | struct zspage *zspage) {} | ||
| 965 | #endif | 1014 | #endif |
| 966 | 1015 | ||
| 967 | static void __free_zspage(struct zs_pool *pool, struct size_class *class, | 1016 | static void __free_zspage(struct zs_pool *pool, struct size_class *class, |
| @@ -979,7 +1028,7 @@ static void __free_zspage(struct zs_pool *pool, struct size_class *class, · 11 unmodified lines | |||
| 979 | VM_BUG_ON(fg != ZS_EMPTY); | 1028 | VM_BUG_ON(fg != ZS_EMPTY); |
| 980 | 1029 | ||
| 981 | /* Free all deferred handles from zs_free */ | 1030 | /* Free all deferred handles from zs_free */ |
| 982 | free_handles(pool, zspage); | 1031 | free_handles(pool, class, zspage); |
| 983 | 1032 | ||
| 984 | next = page = get_first_page(zspage); | 1033 | next = page = get_first_page(zspage); |
| 985 | do { | 1034 | do { |
| @@ -1067,7 +1116,6 @@ static void init_zspage(struct size_class *class, struct zspage *zspage) · 81 unmodified lines | |||
| 1067 | #ifdef CONFIG_ZPOOL | 1116 | #ifdef CONFIG_ZPOOL |
| 1068 | INIT_LIST_HEAD(&zspage->lru); | 1117 | INIT_LIST_HEAD(&zspage->lru); |
| 1069 | zspage->under_reclaim = false; | 1118 | zspage->under_reclaim = false; |
| 1070 | zspage->deferred_handles = NULL; | ||
| 1071 | #endif | 1119 | #endif |
| 1072 | 1120 | ||
| 1073 | set_freeobj(zspage, 0); | 1121 | set_freeobj(zspage, 0); |
| @@ -1568,7 +1616,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp) · 494 unmodified lines | |||
| 1568 | } | 1616 | } |
| 1569 | EXPORT_SYMBOL_GPL(zs_malloc); | 1617 | EXPORT_SYMBOL_GPL(zs_malloc); |
| 1570 | 1618 | ||
| 1571 | static void obj_free(int class_size, unsigned long obj) | 1619 | static void obj_free(int class_size, unsigned long obj, unsigned long *handle) |
| 1572 | { | 1620 | { |
| 1573 | struct link_free *link; | 1621 | struct link_free *link; |
| 1574 | struct zspage *zspage; | 1622 | struct zspage *zspage; |
| @@ -1582,15 +1630,29 @@ static void obj_free(int class_size, unsigned long obj) · 7 unmodified lines | |||
| 1582 | zspage = get_zspage(f_page); | 1630 | zspage = get_zspage(f_page); |
| 1583 | 1631 | ||
| 1584 | vaddr = kmap_atomic(f_page); | 1632 | vaddr = kmap_atomic(f_page); |
| 1585 | |||
| 1586 | /* Insert this object in containing zspage's freelist */ | ||
| 1587 | link = (struct link_free *)(vaddr + f_offset); | 1633 | link = (struct link_free *)(vaddr + f_offset); |
| 1588 | if (likely(!ZsHugePage(zspage))) | 1634 | |
| 1589 | link->next = get_freeobj(zspage) << OBJ_TAG_BITS; | 1635 | if (handle) { |
| 1590 | else | 1636 | #ifdef CONFIG_ZPOOL |
| 1591 | f_page->index = 0; | 1637 | /* Stores the (deferred) handle in the object's header */ |
| 1638 | *handle |= OBJ_DEFERRED_HANDLE_TAG; | ||
| 1639 | *handle &= ~OBJ_ALLOCATED_TAG; | ||
| 1640 | |||
| 1641 | if (likely(!ZsHugePage(zspage))) | ||
| 1642 | link->deferred_handle = *handle; | ||
| 1643 | else | ||
| 1644 | f_page->index = *handle; | ||
| 1645 | #endif | ||
| 1646 | } else { | ||
| 1647 | /* Insert this object in containing zspage's freelist */ | ||
| 1648 | if (likely(!ZsHugePage(zspage))) | ||
| 1649 | link->next = get_freeobj(zspage) << OBJ_TAG_BITS; | ||
| 1650 | else | ||
| 1651 | f_page->index = 0; | ||
| 1652 | set_freeobj(zspage, f_objidx); | ||
| 1653 | } | ||
| 1654 | |||
| 1592 | kunmap_atomic(vaddr); | 1655 | kunmap_atomic(vaddr); |
| 1593 | set_freeobj(zspage, f_objidx); | ||
| 1594 | mod_zspage_inuse(zspage, -1); | 1656 | mod_zspage_inuse(zspage, -1); |
| 1595 | } | 1657 | } |
| 1596 | 1658 | ||
| @@ -1615,7 +1677,6 @@ void zs_free(struct zs_pool *pool, unsigned long handle) · 18 unmodified lines | |||
| 1615 | zspage = get_zspage(f_page); | 1677 | zspage = get_zspage(f_page); |
| 1616 | class = zspage_class(pool, zspage); | 1678 | class = zspage_class(pool, zspage); |
| 1617 | 1679 | ||
| 1618 | obj_free(class->size, obj); | ||
| 1619 | class_stat_dec(class, OBJ_USED, 1); | 1680 | class_stat_dec(class, OBJ_USED, 1); |
| 1620 | 1681 | ||
| 1621 | #ifdef CONFIG_ZPOOL | 1682 | #ifdef CONFIG_ZPOOL |
| @@ -1624,15 +1685,15 @@ void zs_free(struct zs_pool *pool, unsigned long handle) · 2 unmodified lines | |||
| 1624 | * Reclaim needs the handles during writeback. It'll free | 1685 | * Reclaim needs the handles during writeback. It'll free |
| 1625 | * them along with the zspage when it's done with them. | 1686 | * them along with the zspage when it's done with them. |
| 1626 | * | 1687 | * |
| 1627 | * Record current deferred handle at the memory location | 1688 | * Record current deferred handle in the object's header. |
| 1628 | * whose address is given by handle. | ||
| 1629 | */ | 1689 | */ |
| 1630 | record_obj(handle, (unsigned long)zspage->deferred_handles); | 1690 | obj_free(class->size, obj, &handle); |
| 1631 | zspage->deferred_handles = (unsigned long *)handle; | ||
| 1632 | spin_unlock(&pool->lock); | 1691 | spin_unlock(&pool->lock); |
| 1633 | return; | 1692 | return; |
| 1634 | } | 1693 | } |
| 1635 | #endif | 1694 | #endif |
| 1695 | obj_free(class->size, obj, NULL); | ||
| 1696 | |||
| 1636 | fullness = fix_fullness_group(class, zspage); | 1697 | fullness = fix_fullness_group(class, zspage); |
| 1637 | if (fullness == ZS_EMPTY) | 1698 | if (fullness == ZS_EMPTY) |
| 1638 | free_zspage(pool, class, zspage); | 1699 | free_zspage(pool, class, zspage); |
| @@ -1713,11 +1774,11 @@ static void zs_object_copy(struct size_class *class, unsigned long dst, · 74 unmodified lines | |||
| 1713 | } | 1774 | } |
| 1714 | 1775 | ||
| 1715 | /* | 1776 | /* |
| 1716 | * Find alloced object in zspage from index object and | 1777 | * Find object with a certain tag in zspage from index object and |
| 1717 | * return handle. | 1778 | * return handle. |
| 1718 | */ | 1779 | */ |
| 1719 | static unsigned long find_alloced_obj(struct size_class *class, | 1780 | static unsigned long find_tagged_obj(struct size_class *class, |
| 1720 | struct page *page, int *obj_idx) | 1781 | struct page *page, int *obj_idx, int tag) |
| 1721 | { | 1782 | { |
| 1722 | unsigned int offset; | 1783 | unsigned int offset; |
| 1723 | int index = *obj_idx; | 1784 | int index = *obj_idx; |
| @@ -1728,7 +1789,7 @@ static unsigned long find_alloced_obj(struct size_class *class, · 4 unmodified lines | |||
| 1728 | offset += class->size * index; | 1789 | offset += class->size * index; |
| 1729 | 1790 | ||
| 1730 | while (offset < PAGE_SIZE) { | 1791 | while (offset < PAGE_SIZE) { |
| 1731 | if (obj_allocated(page, addr + offset, &handle)) | 1792 | if (obj_tagged(page, addr + offset, &handle, tag)) |
| 1732 | break; | 1793 | break; |
| 1733 | 1794 | ||
| 1734 | offset += class->size; | 1795 | offset += class->size; |
| @@ -1742,6 +1803,28 @@ static unsigned long find_alloced_obj(struct size_class *class, · 7 unmodified lines | |||
| 1742 | return handle; | 1803 | return handle; |
| 1743 | } | 1804 | } |
| 1744 | 1805 | ||
| 1806 | /* | ||
| 1807 | * Find alloced object in zspage from index object and | ||
| 1808 | * return handle. | ||
| 1809 | */ | ||
| 1810 | static unsigned long find_alloced_obj(struct size_class *class, | ||
| 1811 | struct page *page, int *obj_idx) | ||
| 1812 | { | ||
| 1813 | return find_tagged_obj(class, page, obj_idx, OBJ_ALLOCATED_TAG); | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | #ifdef CONFIG_ZPOOL | ||
| 1817 | /* | ||
| 1818 | * Find object storing a deferred handle in header in zspage from index object | ||
| 1819 | * and return handle. | ||
| 1820 | */ | ||
| 1821 | static unsigned long find_deferred_handle_obj(struct size_class *class, | ||
| 1822 | struct page *page, int *obj_idx) | ||
| 1823 | { | ||
| 1824 | return find_tagged_obj(class, page, obj_idx, OBJ_DEFERRED_HANDLE_TAG); | ||
| 1825 | } | ||
| 1826 | #endif | ||
| 1827 | |||
| 1745 | struct zs_compact_control { | 1828 | struct zs_compact_control { |
| 1746 | /* Source spage for migration which could be a subpage of zspage */ | 1829 | /* Source spage for migration which could be a subpage of zspage */ |
| 1747 | struct page *s_page; | 1830 | struct page *s_page; |
| @@ -1784,7 +1867,7 @@ static int migrate_zspage(struct zs_pool *pool, struct size_class *class, · 36 unmodified lines | |||
| 1784 | zs_object_copy(class, free_obj, used_obj); | 1867 | zs_object_copy(class, free_obj, used_obj); |
| 1785 | obj_idx++; | 1868 | obj_idx++; |
| 1786 | record_obj(handle, free_obj); | 1869 | record_obj(handle, free_obj); |
| 1787 | obj_free(class->size, used_obj); | 1870 | obj_free(class->size, used_obj, NULL); |
| 1788 | } | 1871 | } |
| 1789 | 1872 | ||
| 1790 | /* Remember last position in this iteration */ | 1873 | /* Remember last position in this iteration */ |
| @@ -2478,6 +2561,90 @@ void zs_destroy_pool(struct zs_pool *pool) · 687 unmodified lines | |||
| 2478 | EXPORT_SYMBOL_GPL(zs_destroy_pool); | 2561 | EXPORT_SYMBOL_GPL(zs_destroy_pool); |
| 2479 | 2562 | ||
| 2480 | #ifdef CONFIG_ZPOOL | 2563 | #ifdef CONFIG_ZPOOL |
| 2564 | static void restore_freelist(struct zs_pool *pool, struct size_class *class, | ||
| 2565 | struct zspage *zspage) | ||
| 2566 | { | ||
| 2567 | unsigned int obj_idx = 0; | ||
| 2568 | unsigned long handle, off = 0; /* off is within-page offset */ | ||
| 2569 | struct page *page = get_first_page(zspage); | ||
| 2570 | struct link_free *prev_free = NULL; | ||
| 2571 | void *prev_page_vaddr = NULL; | ||
| 2572 | |||
| 2573 | /* in case no free object found */ | ||
| 2574 | set_freeobj(zspage, (unsigned int)(-1UL)); | ||
| 2575 | |||
| 2576 | while (page) { | ||
| 2577 | void *vaddr = kmap_atomic(page); | ||
| 2578 | struct page *next_page; | ||
| 2579 | |||
| 2580 | while (off < PAGE_SIZE) { | ||
| 2581 | void *obj_addr = vaddr + off; | ||
| 2582 | |||
| 2583 | /* skip allocated object */ | ||
| 2584 | if (obj_allocated(page, obj_addr, &handle)) { | ||
| 2585 | obj_idx++; | ||
| 2586 | off += class->size; | ||
| 2587 | continue; | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | /* free deferred handle from reclaim attempt */ | ||
| 2591 | if (obj_stores_deferred_handle(page, obj_addr, &handle)) | ||
| 2592 | cache_free_handle(pool, handle); | ||
| 2593 | |||
| 2594 | if (prev_free) | ||
| 2595 | prev_free->next = obj_idx << OBJ_TAG_BITS; | ||
| 2596 | else /* first free object found */ | ||
| 2597 | set_freeobj(zspage, obj_idx); | ||
| 2598 | |||
| 2599 | prev_free = (struct link_free *)vaddr + off / sizeof(*prev_free); | ||
| 2600 | /* if last free object in a previous page, need to unmap */ | ||
| 2601 | if (prev_page_vaddr) { | ||
| 2602 | kunmap_atomic(prev_page_vaddr); | ||
| 2603 | prev_page_vaddr = NULL; | ||
| 2604 | } | ||
| 2605 | |||
| 2606 | obj_idx++; | ||
| 2607 | off += class->size; | ||
| 2608 | } | ||
| 2609 | |||
| 2610 | /* | ||
| 2611 | * Handle the last (full or partial) object on this page. | ||
| 2612 | */ | ||
| 2613 | next_page = get_next_page(page); | ||
| 2614 | if (next_page) { | ||
| 2615 | if (!prev_free || prev_page_vaddr) { | ||
| 2616 | /* | ||
| 2617 | * There is no free object in this page, so we can safely | ||
| 2618 | * unmap it. | ||
| 2619 | */ | ||
| 2620 | kunmap_atomic(vaddr); | ||
| 2621 | } else { | ||
| 2622 | /* update prev_page_vaddr since prev_free is on this page */ | ||
| 2623 | prev_page_vaddr = vaddr; | ||
| 2624 | } | ||
| 2625 | } else { /* this is the last page */ | ||
| 2626 | if (prev_free) { | ||
| 2627 | /* | ||
| 2628 | * Reset OBJ_TAG_BITS bit to last link to tell | ||
| 2629 | * whether it's allocated object or not. | ||
| 2630 | */ | ||
| 2631 | prev_free->next = -1UL << OBJ_TAG_BITS; | ||
| 2632 | } | ||
| 2633 | |||
| 2634 | /* unmap previous page (if not done yet) */ | ||
| 2635 | if (prev_page_vaddr) { | ||
| 2636 | kunmap_atomic(prev_page_vaddr); | ||
| 2637 | prev_page_vaddr = NULL; | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | kunmap_atomic(vaddr); | ||
| 2641 | } | ||
| 2642 | |||
| 2643 | page = next_page; | ||
| 2644 | off %= PAGE_SIZE; | ||
| 2645 | } | ||
| 2646 | } | ||
| 2647 | |||
| 2481 | static int zs_reclaim_page(struct zs_pool *pool, unsigned int retries) | 2648 | static int zs_reclaim_page(struct zs_pool *pool, unsigned int retries) |
| 2482 | { | 2649 | { |
| 2483 | int i, obj_idx, ret = 0; | 2650 | int i, obj_idx, ret = 0; |
| @@ -2561,6 +2728,12 @@ next: · 77 unmodified lines | |||
| 2561 | return 0; | 2728 | return 0; |
| 2562 | } | 2729 | } |
| 2563 | 2730 | ||
| 2731 | /* | ||
| 2732 | * Eviction fails on one of the handles, so we need to restore zspage. | ||
| 2733 | * We need to rebuild its freelist (and free stored deferred handles), | ||
| 2734 | * put it back to the correct size class, and add it to the LRU list. | ||
| 2735 | */ | ||
| 2736 | restore_freelist(pool, class, zspage); | ||
| 2564 | putback_zspage(class, zspage); | 2737 | putback_zspage(class, zspage); |
| 2565 | list_add(&zspage->lru, &pool->lru); | 2738 | list_add(&zspage->lru, &pool->lru); |
| 2566 | unlock_zspage(zspage); | 2739 | unlock_zspage(zspage); |
| @@ -165,6 +165,46 @@ static void j1939_ac_process(struct j1939_priv *priv, struct sk_buff *skb) · 164 unmodified lines | |||
| 165 | * leaving this function. | 165 | * leaving this function. |
| 166 | */ | 166 | */ |
| 167 | ecu = j1939_ecu_get_by_name_locked(priv, name); | 167 | ecu = j1939_ecu_get_by_name_locked(priv, name); |
| 168 | |||
| 169 | if (ecu && ecu->addr == skcb->addr.sa) { | ||
| 170 | /* The ISO 11783-5 standard, in "4.5.2 - Address claim | ||
| 171 | * requirements", states: | ||
| 172 | * d) No CF shall begin, or resume, transmission on the | ||
| 173 | * network until 250 ms after it has successfully claimed | ||
| 174 | * an address except when responding to a request for | ||
| 175 | * address-claimed. | ||
| 176 | * | ||
| 177 | * But "Figure 6" and "Figure 7" in "4.5.4.2 - Address-claim | ||
| 178 | * prioritization" show that the CF begins the transmission | ||
| 179 | * after 250 ms from the first AC (address-claimed) message | ||
| 180 | * even if it sends another AC message during that time window | ||
| 181 | * to resolve the address contention with another CF. | ||
| 182 | * | ||
| 183 | * As stated in "4.4.2.3 - Address-claimed message": | ||
| 184 | * In order to successfully claim an address, the CF sending | ||
| 185 | * an address claimed message shall not receive a contending | ||
| 186 | * claim from another CF for at least 250 ms. | ||
| 187 | * | ||
| 188 | * As stated in "4.4.3.2 - NAME management (NM) message": | ||
| 189 | * 1) A commanding CF can | ||
| 190 | * d) request that a CF with a specified NAME transmit | ||
| 191 | * the address-claimed message with its current NAME. | ||
| 192 | * 2) A target CF shall | ||
| 193 | * d) send an address-claimed message in response to a | ||
| 194 | * request for a matching NAME | ||
| 195 | * | ||
| 196 | * Taking the above arguments into account, the 250 ms wait is | ||
| 197 | * requested only during network initialization. | ||
| 198 | * | ||
| 199 | * Do not restart the timer on AC message if both the NAME and | ||
| 200 | * the address match and so if the address has already been | ||
| 201 | * claimed (timer has expired) or the AC message has been sent | ||
| 202 | * to resolve the contention with another CF (timer is still | ||
| 203 | * running). | ||
| 204 | */ | ||
| 205 | goto out_ecu_put; | ||
| 206 | } | ||
| 207 | |||
| 168 | if (!ecu && j1939_address_is_unicast(skcb->addr.sa)) | 208 | if (!ecu && j1939_address_is_unicast(skcb->addr.sa)) |
| 169 | ecu = j1939_ecu_create_locked(priv, name); | 209 | ecu = j1939_ecu_create_locked(priv, name); |
| 170 | 210 | ||
| @@ -269,7 +269,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) · 268 unmodified lines | |||
| 269 | (n->nud_state == NUD_NOARP) || | 269 | (n->nud_state == NUD_NOARP) || |
| 270 | (tbl->is_multicast && | 270 | (tbl->is_multicast && |
| 271 | tbl->is_multicast(n->primary_key)) || | 271 | tbl->is_multicast(n->primary_key)) || |
| 272 | time_after(tref, n->updated)) | 272 | !time_in_range(n->updated, tref, jiffies)) |
| 273 | remove = true; | 273 | remove = true; |
| 274 | write_unlock(&n->lock); | 274 | write_unlock(&n->lock); |
| 275 | 275 | ||
| @@ -289,7 +289,17 @@ static int neigh_forced_gc(struct neigh_table *tbl) · 13 unmodified lines | |||
| 289 | 289 | ||
| 290 | static void neigh_add_timer(struct neighbour *n, unsigned long when) | 290 | static void neigh_add_timer(struct neighbour *n, unsigned long when) |
| 291 | { | 291 | { |
| 292 | /* Use safe distance from the jiffies - LONG_MAX point while timer | ||
| 293 | * is running in DELAY/PROBE state but still show to user space | ||
| 294 | * large times in the past. | ||
| 295 | */ | ||
| 296 | unsigned long mint = jiffies - (LONG_MAX - 86400 * HZ); | ||
| 297 | |||
| 292 | neigh_hold(n); | 298 | neigh_hold(n); |
| 299 | if (!time_in_range(n->confirmed, mint, jiffies)) | ||
| 300 | n->confirmed = mint; | ||
| 301 | if (time_before(n->used, n->confirmed)) | ||
| 302 | n->used = n->confirmed; | ||
| 293 | if (unlikely(mod_timer(&n->timer, when))) { | 303 | if (unlikely(mod_timer(&n->timer, when))) { |
| 294 | printk("NEIGH: BUG, double timer add, state is %x\n", | 304 | printk("NEIGH: BUG, double timer add, state is %x\n", |
| 295 | n->nud_state); | 305 | n->nud_state); |
| @@ -1001,12 +1011,14 @@ static void neigh_periodic_work(struct work_struct *work) · 705 unmodified lines | |||
| 1001 | goto next_elt; | 1011 | goto next_elt; |
| 1002 | } | 1012 | } |
| 1003 | 1013 | ||
| 1004 | if (time_before(n->used, n->confirmed)) | 1014 | if (time_before(n->used, n->confirmed) && |
| 1015 | time_is_before_eq_jiffies(n->confirmed)) | ||
| 1005 | n->used = n->confirmed; | 1016 | n->used = n->confirmed; |
| 1006 | 1017 | ||
| 1007 | if (refcount_read(&n->refcnt) == 1 && | 1018 | if (refcount_read(&n->refcnt) == 1 && |
| 1008 | (state == NUD_FAILED || | 1019 | (state == NUD_FAILED || |
| 1009 | time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { | 1020 | !time_in_range_open(jiffies, n->used, |
| 1021 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { | ||
| 1010 | *np = n->next; | 1022 | *np = n->next; |
| 1011 | neigh_mark_dead(n); | 1023 | neigh_mark_dead(n); |
| 1012 | write_unlock(&n->lock); | 1024 | write_unlock(&n->lock); |
| @@ -1531,6 +1531,8 @@ set_sndbuf: · 1530 unmodified lines | |||
| 1531 | ret = -EINVAL; | 1531 | ret = -EINVAL; |
| 1532 | break; | 1532 | break; |
| 1533 | } | 1533 | } |
| 1534 | if ((u8)val == SOCK_TXREHASH_DEFAULT) | ||
| 1535 | val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash); | ||
| 1534 | /* Paired with READ_ONCE() in tcp_rtx_synack() */ | 1536 | /* Paired with READ_ONCE() in tcp_rtx_synack() */ |
| 1535 | WRITE_ONCE(sk->sk_txrehash, (u8)val); | 1537 | WRITE_ONCE(sk->sk_txrehash, (u8)val); |
| 1536 | break; | 1538 | break; |
| @@ -3454,7 +3456,6 @@ void sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid) · 1917 unmodified lines | |||
| 3454 | sk->sk_pacing_rate = ~0UL; | 3456 | sk->sk_pacing_rate = ~0UL; |
| 3455 | WRITE_ONCE(sk->sk_pacing_shift, 10); | 3457 | WRITE_ONCE(sk->sk_pacing_shift, 10); |
| 3456 | sk->sk_incoming_cpu = -1; | 3458 | sk->sk_incoming_cpu = -1; |
| 3457 | sk->sk_txrehash = SOCK_TXREHASH_DEFAULT; | ||
| 3458 | 3459 | ||
| 3459 | sk_rx_queue_clear(sk); | 3460 | sk_rx_queue_clear(sk); |
| 3460 | /* | 3461 | /* |
| @@ -205,7 +205,7 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, · 204 unmodified lines | |||
| 205 | goto err_xa_alloc; | 205 | goto err_xa_alloc; |
| 206 | 206 | ||
| 207 | devlink->netdevice_nb.notifier_call = devlink_port_netdevice_event; | 207 | devlink->netdevice_nb.notifier_call = devlink_port_netdevice_event; |
| 208 | ret = register_netdevice_notifier_net(net, &devlink->netdevice_nb); | 208 | ret = register_netdevice_notifier(&devlink->netdevice_nb); |
| 209 | if (ret) | 209 | if (ret) |
| 210 | goto err_register_netdevice_notifier; | 210 | goto err_register_netdevice_notifier; |
| 211 | 211 | ||
| @@ -266,8 +266,7 @@ void devlink_free(struct devlink *devlink) · 54 unmodified lines | |||
| 266 | xa_destroy(&devlink->snapshot_ids); | 266 | xa_destroy(&devlink->snapshot_ids); |
| 267 | xa_destroy(&devlink->ports); | 267 | xa_destroy(&devlink->ports); |
| 268 | 268 | ||
| 269 | WARN_ON_ONCE(unregister_netdevice_notifier_net(devlink_net(devlink), | 269 | WARN_ON_ONCE(unregister_netdevice_notifier(&devlink->netdevice_nb)); |
| 270 | &devlink->netdevice_nb)); | ||
| 271 | 270 | ||
| 272 | xa_erase(&devlinks, devlink->index); | 271 | xa_erase(&devlinks, devlink->index); |
| 273 | 272 | ||
| @@ -8430,6 +8430,8 @@ int devlink_port_netdevice_event(struct notifier_block *nb, · 8429 unmodified lines | |||
| 8430 | break; | 8430 | break; |
| 8431 | case NETDEV_REGISTER: | 8431 | case NETDEV_REGISTER: |
| 8432 | case NETDEV_CHANGENAME: | 8432 | case NETDEV_CHANGENAME: |
| 8433 | if (devlink_net(devlink) != dev_net(netdev)) | ||
| 8434 | return NOTIFY_OK; | ||
| 8433 | /* Set the netdev on top of previously set type. Note this | 8435 | /* Set the netdev on top of previously set type. Note this |
| 8434 | * event happens also during net namespace change so here | 8436 | * event happens also during net namespace change so here |
| 8435 | * we take into account netdev pointer appearing in this | 8437 | * we take into account netdev pointer appearing in this |
| @@ -8439,6 +8441,8 @@ int devlink_port_netdevice_event(struct notifier_block *nb, · 3 unmodified lines | |||
| 8439 | netdev); | 8441 | netdev); |
| 8440 | break; | 8442 | break; |
| 8441 | case NETDEV_UNREGISTER: | 8443 | case NETDEV_UNREGISTER: |
| 8444 | if (devlink_net(devlink) != dev_net(netdev)) | ||
| 8445 | return NOTIFY_OK; | ||
| 8442 | /* Clear netdev pointer, but not the type. This event happens | 8446 | /* Clear netdev pointer, but not the type. This event happens |
| 8443 | * also during net namespace change so we need to clear | 8447 | * also during net namespace change so we need to clear |
| 8444 | * pointer to netdev that is going to another net namespace. | 8448 | * pointer to netdev that is going to another net namespace. |
| @@ -347,6 +347,7 @@ lookup_protocol: · 346 unmodified lines | |||
| 347 | sk->sk_destruct = inet_sock_destruct; | 347 | sk->sk_destruct = inet_sock_destruct; |
| 348 | sk->sk_protocol = protocol; | 348 | sk->sk_protocol = protocol; |
| 349 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | 349 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; |
| 350 | sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); | ||
| 350 | 351 | ||
| 351 | inet->uc_ttl = -1; | 352 | inet->uc_ttl = -1; |
| 352 | inet->mc_loop = 1; | 353 | inet->mc_loop = 1; |
| @@ -1246,9 +1246,6 @@ int inet_csk_listen_start(struct sock *sk) · 1245 unmodified lines | |||
| 1246 | sk->sk_ack_backlog = 0; | 1246 | sk->sk_ack_backlog = 0; |
| 1247 | inet_csk_delack_init(sk); | 1247 | inet_csk_delack_init(sk); |
| 1248 | 1248 | ||
| 1249 | if (sk->sk_txrehash == SOCK_TXREHASH_DEFAULT) | ||
| 1250 | sk->sk_txrehash = READ_ONCE(sock_net(sk)->core.sysctl_txrehash); | ||
| 1251 | |||
| 1252 | /* There is race window here: we announce ourselves listening, | 1249 | /* There is race window here: we announce ourselves listening, |
| 1253 | * but this transition is still not validated by get_port(). | 1250 | * but this transition is still not validated by get_port(). |
| 1254 | * It is OK, because this socket enters to hash table only | 1251 | * It is OK, because this socket enters to hash table only |
| @@ -222,6 +222,7 @@ lookup_protocol: · 221 unmodified lines | |||
| 222 | np->pmtudisc = IPV6_PMTUDISC_WANT; | 222 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
| 223 | np->repflow = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; | 223 | np->repflow = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; |
| 224 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; | 224 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; |
| 225 | sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); | ||
| 225 | 226 | ||
| 226 | /* Init the ipv4 part of the socket since we can have sockets | 227 | /* Init the ipv4 part of the socket since we can have sockets |
| 227 | * using v6 API for ipv4. | 228 | * using v6 API for ipv4. |
| @@ -1002,8 +1002,8 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, · 1001 unmodified lines | |||
| 1002 | { | 1002 | { |
| 1003 | int addrlen = sizeof(struct sockaddr_in); | 1003 | int addrlen = sizeof(struct sockaddr_in); |
| 1004 | struct sockaddr_storage addr; | 1004 | struct sockaddr_storage addr; |
| 1005 | struct mptcp_sock *msk; | ||
| 1006 | struct socket *ssock; | 1005 | struct socket *ssock; |
| 1006 | struct sock *newsk; | ||
| 1007 | int backlog = 1024; | 1007 | int backlog = 1024; |
| 1008 | int err; | 1008 | int err; |
| 1009 | 1009 | ||
| @@ -1012,11 +1012,13 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, · 2 unmodified lines | |||
| 1012 | if (err) | 1012 | if (err) |
| 1013 | return err; | 1013 | return err; |
| 1014 | 1014 | ||
| 1015 | msk = mptcp_sk(entry->lsk->sk); | 1015 | newsk = entry->lsk->sk; |
| 1016 | if (!msk) | 1016 | if (!newsk) |
| 1017 | return -EINVAL; | 1017 | return -EINVAL; |
| 1018 | 1018 | ||
| 1019 | ssock = __mptcp_nmpc_socket(msk); | 1019 | lock_sock(newsk); |
| 1020 | ssock = __mptcp_nmpc_socket(mptcp_sk(newsk)); | ||
| 1021 | release_sock(newsk); | ||
| 1020 | if (!ssock) | 1022 | if (!ssock) |
| 1021 | return -EINVAL; | 1023 | return -EINVAL; |
| 1022 | 1024 | ||
| @@ -2902,6 +2902,7 @@ bool __mptcp_close(struct sock *sk, long timeout) · 2901 unmodified lines | |||
| 2902 | struct mptcp_subflow_context *subflow; | 2902 | struct mptcp_subflow_context *subflow; |
| 2903 | struct mptcp_sock *msk = mptcp_sk(sk); | 2903 | struct mptcp_sock *msk = mptcp_sk(sk); |
| 2904 | bool do_cancel_work = false; | 2904 | bool do_cancel_work = false; |
| 2905 | int subflows_alive = 0; | ||
| 2905 | 2906 | ||
| 2906 | sk->sk_shutdown = SHUTDOWN_MASK; | 2907 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 2907 | 2908 | ||
| @@ -2928,6 +2929,8 @@ cleanup: · 20 unmodified lines | |||
| 2928 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 2929 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 2929 | bool slow = lock_sock_fast_nested(ssk); | 2930 | bool slow = lock_sock_fast_nested(ssk); |
| 2930 | 2931 | ||
| 2932 | subflows_alive += ssk->sk_state != TCP_CLOSE; | ||
| 2933 | |||
| 2931 | /* since the close timeout takes precedence on the fail one, | 2934 | /* since the close timeout takes precedence on the fail one, |
| 2932 | * cancel the latter | 2935 | * cancel the latter |
| 2933 | */ | 2936 | */ |
| @@ -2943,6 +2946,12 @@ cleanup: · 9 unmodified lines | |||
| 2943 | } | 2946 | } |
| 2944 | sock_orphan(sk); | 2947 | sock_orphan(sk); |
| 2945 | 2948 | ||
| 2949 | /* all the subflows are closed, only timeout can change the msk | ||
| 2950 | * state, let's not keep resources busy for no reasons | ||
| 2951 | */ | ||
| 2952 | if (subflows_alive == 0) | ||
| 2953 | inet_sk_state_store(sk, TCP_CLOSE); | ||
| 2954 | |||
| 2946 | sock_hold(sk); | 2955 | sock_hold(sk); |
| 2947 | pr_debug("msk=%p state=%d", sk, sk->sk_state); | 2956 | pr_debug("msk=%p state=%d", sk, sk->sk_state); |
| 2948 | if (msk->token) | 2957 | if (msk->token) |
| @@ -760,14 +760,21 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname, · 759 unmodified lines | |||
| 760 | static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int optname, | 760 | static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int optname, |
| 761 | sockptr_t optval, unsigned int optlen) | 761 | sockptr_t optval, unsigned int optlen) |
| 762 | { | 762 | { |
| 763 | struct sock *sk = (struct sock *)msk; | ||
| 763 | struct socket *sock; | 764 | struct socket *sock; |
| 765 | int ret = -EINVAL; | ||
| 764 | 766 | ||
| 765 | /* Limit to first subflow, before the connection establishment */ | 767 | /* Limit to first subflow, before the connection establishment */ |
| 768 | lock_sock(sk); | ||
| 766 | sock = __mptcp_nmpc_socket(msk); | 769 | sock = __mptcp_nmpc_socket(msk); |
| 767 | if (!sock) | 770 | if (!sock) |
| 768 | return -EINVAL; | 771 | goto unlock; |
| 769 | 772 | ||
| 770 | return tcp_setsockopt(sock->sk, level, optname, optval, optlen); | 773 | ret = tcp_setsockopt(sock->sk, level, optname, optval, optlen); |
| 774 | |||
| 775 | unlock: | ||
| 776 | release_sock(sk); | ||
| 777 | return ret; | ||
| 771 | } | 778 | } |
| 772 | 779 | ||
| 773 | static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname, | 780 | static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname, |
| @@ -1400,6 +1400,7 @@ void __mptcp_error_report(struct sock *sk) · 1399 unmodified lines | |||
| 1400 | mptcp_for_each_subflow(msk, subflow) { | 1400 | mptcp_for_each_subflow(msk, subflow) { |
| 1401 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 1401 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 1402 | int err = sock_error(ssk); | 1402 | int err = sock_error(ssk); |
| 1403 | int ssk_state; | ||
| 1403 | 1404 | ||
| 1404 | if (!err) | 1405 | if (!err) |
| 1405 | continue; | 1406 | continue; |
| @@ -1410,7 +1411,14 @@ void __mptcp_error_report(struct sock *sk) · 4 unmodified lines | |||
| 1410 | if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk)) | 1411 | if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk)) |
| 1411 | continue; | 1412 | continue; |
| 1412 | 1413 | ||
| 1413 | inet_sk_state_store(sk, inet_sk_state_load(ssk)); | 1414 | /* We need to propagate only transition to CLOSE state. |
| 1415 | * Orphaned socket will see such state change via | ||
| 1416 | * subflow_sched_work_if_closed() and that path will properly | ||
| 1417 | * destroy the msk as needed. | ||
| 1418 | */ | ||
| 1419 | ssk_state = inet_sk_state_load(ssk); | ||
| 1420 | if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD)) | ||
| 1421 | inet_sk_state_store(sk, ssk_state); | ||
| 1414 | sk->sk_err = -err; | 1422 | sk->sk_err = -err; |
| 1415 | 1423 | ||
| 1416 | /* This barrier is coupled with smp_rmb() in mptcp_poll() */ | 1424 | /* This barrier is coupled with smp_rmb() in mptcp_poll() */ |
| @@ -1682,7 +1690,7 @@ int mptcp_subflow_create_socket(struct sock *sk, unsigned short family, · 265 unmodified lines | |||
| 1682 | if (err) | 1690 | if (err) |
| 1683 | return err; | 1691 | return err; |
| 1684 | 1692 | ||
| 1685 | lock_sock(sf->sk); | 1693 | lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING); |
| 1686 | 1694 | ||
| 1687 | /* the newly created socket has to be in the same cgroup as its parent */ | 1695 | /* the newly created socket has to be in the same cgroup as its parent */ |
| 1688 | mptcp_attach_cgroup(sk, sf->sk); | 1696 | mptcp_attach_cgroup(sk, sf->sk); |
| @@ -104,9 +104,9 @@ static void rds_rm_zerocopy_callback(struct rds_sock *rs, · 103 unmodified lines | |||
| 104 | spin_lock_irqsave(&q->lock, flags); | 104 | spin_lock_irqsave(&q->lock, flags); |
| 105 | head = &q->zcookie_head; | 105 | head = &q->zcookie_head; |
| 106 | if (!list_empty(head)) { | 106 | if (!list_empty(head)) { |
| 107 | info = list_entry(head, struct rds_msg_zcopy_info, | 107 | info = list_first_entry(head, struct rds_msg_zcopy_info, |
| 108 | rs_zcookie_next); | 108 | rs_zcookie_next); |
| 109 | if (info && rds_zcookie_add(info, cookie)) { | 109 | if (rds_zcookie_add(info, cookie)) { |
| 110 | spin_unlock_irqrestore(&q->lock, flags); | 110 | spin_unlock_irqrestore(&q->lock, flags); |
| 111 | kfree(rds_info_from_znotifier(znotif)); | 111 | kfree(rds_info_from_znotifier(znotif)); |
| 112 | /* caller invokes rds_wake_sk_sleep() */ | 112 | /* caller invokes rds_wake_sk_sleep() */ |
| @@ -433,7 +433,7 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) · 432 unmodified lines | |||
| 433 | while (m) { | 433 | while (m) { |
| 434 | unsigned int prio = ffz(~m); | 434 | unsigned int prio = ffz(~m); |
| 435 | 435 | ||
| 436 | if (WARN_ON_ONCE(prio > ARRAY_SIZE(p->inner.clprio))) | 436 | if (WARN_ON_ONCE(prio >= ARRAY_SIZE(p->inner.clprio))) |
| 437 | break; | 437 | break; |
| 438 | m &= ~(1 << prio); | 438 | m &= ~(1 << prio); |
| 439 | 439 | ||
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | * Based on code and translator idea by: Florian Westphal <fw@strlen.de> | 5 | * Based on code and translator idea by: Florian Westphal <fw@strlen.de> |
| 6 | */ | 6 | */ |
| 7 | #include <linux/compat.h> | 7 | #include <linux/compat.h> |
| 8 | #include <linux/nospec.h> | ||
| 8 | #include <linux/xfrm.h> | 9 | #include <linux/xfrm.h> |
| 9 | #include <net/xfrm.h> | 10 | #include <net/xfrm.h> |
| 10 | 11 | ||
| @@ -302,7 +303,7 @@ static int xfrm_xlate64(struct sk_buff *dst, const struct nlmsghdr *nlh_src) · 291 unmodified lines | |||
| 302 | nla_for_each_attr(nla, attrs, len, remaining) { | 303 | nla_for_each_attr(nla, attrs, len, remaining) { |
| 303 | int err; | 304 | int err; |
| 304 | 305 | ||
| 305 | switch (type) { | 306 | switch (nlh_src->nlmsg_type) { |
| 306 | case XFRM_MSG_NEWSPDINFO: | 307 | case XFRM_MSG_NEWSPDINFO: |
| 307 | err = xfrm_nla_cpy(dst, nla, nla_len(nla)); | 308 | err = xfrm_nla_cpy(dst, nla, nla_len(nla)); |
| 308 | break; | 309 | break; |
| @@ -437,6 +438,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla, · 128 unmodified lines | |||
| 437 | NL_SET_ERR_MSG(extack, "Bad attribute"); | 438 | NL_SET_ERR_MSG(extack, "Bad attribute"); |
| 438 | return -EOPNOTSUPP; | 439 | return -EOPNOTSUPP; |
| 439 | } | 440 | } |
| 441 | type = array_index_nospec(type, XFRMA_MAX + 1); | ||
| 440 | if (nla_len(nla) < compat_policy[type].len) { | 442 | if (nla_len(nla) < compat_policy[type].len) { |
| 441 | NL_SET_ERR_MSG(extack, "Attribute bad length"); | 443 | NL_SET_ERR_MSG(extack, "Attribute bad length"); |
| 442 | return -EOPNOTSUPP; | 444 | return -EOPNOTSUPP; |
| @@ -279,8 +279,7 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) · 278 unmodified lines | |||
| 279 | goto out; | 279 | goto out; |
| 280 | 280 | ||
| 281 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | 281 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
| 282 | ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)), | 282 | ipv6_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipipv6_hdr(skb)); |
| 283 | ipipv6_hdr(skb)); | ||
| 284 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 283 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
| 285 | ipip6_ecn_decapsulate(skb); | 284 | ipip6_ecn_decapsulate(skb); |
| 286 | 285 | ||
| @@ -310,6 +310,52 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet) · 309 unmodified lines | |||
| 310 | skb->mark = 0; | 310 | skb->mark = 0; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi, | ||
| 314 | int encap_type, unsigned short family) | ||
| 315 | { | ||
| 316 | struct sec_path *sp; | ||
| 317 | |||
| 318 | sp = skb_sec_path(skb); | ||
| 319 | if (sp && (sp->len || sp->olen) && | ||
| 320 | !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) | ||
| 321 | goto discard; | ||
| 322 | |||
| 323 | XFRM_SPI_SKB_CB(skb)->family = family; | ||
| 324 | if (family == AF_INET) { | ||
| 325 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | ||
| 326 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | ||
| 327 | } else { | ||
| 328 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); | ||
| 329 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; | ||
| 330 | } | ||
| 331 | |||
| 332 | return xfrm_input(skb, nexthdr, spi, encap_type); | ||
| 333 | discard: | ||
| 334 | kfree_skb(skb); | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int xfrmi4_rcv(struct sk_buff *skb) | ||
| 339 | { | ||
| 340 | return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET); | ||
| 341 | } | ||
| 342 | |||
| 343 | static int xfrmi6_rcv(struct sk_buff *skb) | ||
| 344 | { | ||
| 345 | return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], | ||
| 346 | 0, 0, AF_INET6); | ||
| 347 | } | ||
| 348 | |||
| 349 | static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | ||
| 350 | { | ||
| 351 | return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET); | ||
| 352 | } | ||
| 353 | |||
| 354 | static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | ||
| 355 | { | ||
| 356 | return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6); | ||
| 357 | } | ||
| 358 | |||
| 313 | static int xfrmi_rcv_cb(struct sk_buff *skb, int err) | 359 | static int xfrmi_rcv_cb(struct sk_buff *skb, int err) |
| 314 | { | 360 | { |
| 315 | const struct xfrm_mode *inner_mode; | 361 | const struct xfrm_mode *inner_mode; |
| @@ -945,8 +991,8 @@ static struct pernet_operations xfrmi_net_ops = { · 629 unmodified lines | |||
| 945 | }; | 991 | }; |
| 946 | 992 | ||
| 947 | static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = { | 993 | static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = { |
| 948 | .handler = xfrm6_rcv, | 994 | .handler = xfrmi6_rcv, |
| 949 | .input_handler = xfrm_input, | 995 | .input_handler = xfrmi6_input, |
| 950 | .cb_handler = xfrmi_rcv_cb, | 996 | .cb_handler = xfrmi_rcv_cb, |
| 951 | .err_handler = xfrmi6_err, | 997 | .err_handler = xfrmi6_err, |
| 952 | .priority = 10, | 998 | .priority = 10, |
| @@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = { · 43 unmodified lines | |||
| 996 | #endif | 1042 | #endif |
| 997 | 1043 | ||
| 998 | static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = { | 1044 | static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = { |
| 999 | .handler = xfrm4_rcv, | 1045 | .handler = xfrmi4_rcv, |
| 1000 | .input_handler = xfrm_input, | 1046 | .input_handler = xfrmi4_input, |
| 1001 | .cb_handler = xfrmi_rcv_cb, | 1047 | .cb_handler = xfrmi_rcv_cb, |
| 1002 | .err_handler = xfrmi4_err, | 1048 | .err_handler = xfrmi4_err, |
| 1003 | .priority = 10, | 1049 | .priority = 10, |
| @@ -336,7 +336,7 @@ static void xfrm_policy_timer(struct timer_list *t) · 335 unmodified lines | |||
| 336 | } | 336 | } |
| 337 | if (xp->lft.hard_use_expires_seconds) { | 337 | if (xp->lft.hard_use_expires_seconds) { |
| 338 | time64_t tmo = xp->lft.hard_use_expires_seconds + | 338 | time64_t tmo = xp->lft.hard_use_expires_seconds + |
| 339 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; | 339 | (READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now; |
| 340 | if (tmo <= 0) | 340 | if (tmo <= 0) |
| 341 | goto expired; | 341 | goto expired; |
| 342 | if (tmo < next) | 342 | if (tmo < next) |
| @@ -354,7 +354,7 @@ static void xfrm_policy_timer(struct timer_list *t) · 11 unmodified lines | |||
| 354 | } | 354 | } |
| 355 | if (xp->lft.soft_use_expires_seconds) { | 355 | if (xp->lft.soft_use_expires_seconds) { |
| 356 | time64_t tmo = xp->lft.soft_use_expires_seconds + | 356 | time64_t tmo = xp->lft.soft_use_expires_seconds + |
| 357 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; | 357 | (READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now; |
| 358 | if (tmo <= 0) { | 358 | if (tmo <= 0) { |
| 359 | warn = 1; | 359 | warn = 1; |
| 360 | tmo = XFRM_KM_TIMEOUT; | 360 | tmo = XFRM_KM_TIMEOUT; |
| @@ -3661,7 +3661,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, · 3300 unmodified lines | |||
| 3661 | return 1; | 3661 | return 1; |
| 3662 | } | 3662 | } |
| 3663 | 3663 | ||
| 3664 | pol->curlft.use_time = ktime_get_real_seconds(); | 3664 | /* This lockless write can happen from different cpus. */ |
| 3665 | WRITE_ONCE(pol->curlft.use_time, ktime_get_real_seconds()); | ||
| 3665 | 3666 | ||
| 3666 | pols[0] = pol; | 3667 | pols[0] = pol; |
| 3667 | npols++; | 3668 | npols++; |
| @@ -3676,7 +3677,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, · 8 unmodified lines | |||
| 3676 | xfrm_pol_put(pols[0]); | 3677 | xfrm_pol_put(pols[0]); |
| 3677 | return 0; | 3678 | return 0; |
| 3678 | } | 3679 | } |
| 3679 | pols[1]->curlft.use_time = ktime_get_real_seconds(); | 3680 | /* This write can happen from different cpus. */ |
| 3681 | WRITE_ONCE(pols[1]->curlft.use_time, | ||
| 3682 | ktime_get_real_seconds()); | ||
| 3680 | npols++; | 3683 | npols++; |
| 3681 | } | 3684 | } |
| 3682 | } | 3685 | } |
| @@ -3742,6 +3745,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, · 59 unmodified lines | |||
| 3742 | goto reject; | 3745 | goto reject; |
| 3743 | } | 3746 | } |
| 3744 | 3747 | ||
| 3748 | if (if_id) | ||
| 3749 | secpath_reset(skb); | ||
| 3750 | |||
| 3745 | xfrm_pols_put(pols, npols); | 3751 | xfrm_pols_put(pols, npols); |
| 3746 | return 1; | 3752 | return 1; |
| 3747 | } | 3753 | } |
| @@ -577,7 +577,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 576 unmodified lines | |||
| 577 | if (x->km.state == XFRM_STATE_EXPIRED) | 577 | if (x->km.state == XFRM_STATE_EXPIRED) |
| 578 | goto expired; | 578 | goto expired; |
| 579 | if (x->lft.hard_add_expires_seconds) { | 579 | if (x->lft.hard_add_expires_seconds) { |
| 580 | long tmo = x->lft.hard_add_expires_seconds + | 580 | time64_t tmo = x->lft.hard_add_expires_seconds + |
| 581 | x->curlft.add_time - now; | 581 | x->curlft.add_time - now; |
| 582 | if (tmo <= 0) { | 582 | if (tmo <= 0) { |
| 583 | if (x->xflags & XFRM_SOFT_EXPIRE) { | 583 | if (x->xflags & XFRM_SOFT_EXPIRE) { |
| @@ -594,8 +594,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 10 unmodified lines | |||
| 594 | next = tmo; | 594 | next = tmo; |
| 595 | } | 595 | } |
| 596 | if (x->lft.hard_use_expires_seconds) { | 596 | if (x->lft.hard_use_expires_seconds) { |
| 597 | long tmo = x->lft.hard_use_expires_seconds + | 597 | time64_t tmo = x->lft.hard_use_expires_seconds + |
| 598 | (x->curlft.use_time ? : now) - now; | 598 | (READ_ONCE(x->curlft.use_time) ? : now) - now; |
| 599 | if (tmo <= 0) | 599 | if (tmo <= 0) |
| 600 | goto expired; | 600 | goto expired; |
| 601 | if (tmo < next) | 601 | if (tmo < next) |
| @@ -604,7 +604,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 2 unmodified lines | |||
| 604 | if (x->km.dying) | 604 | if (x->km.dying) |
| 605 | goto resched; | 605 | goto resched; |
| 606 | if (x->lft.soft_add_expires_seconds) { | 606 | if (x->lft.soft_add_expires_seconds) { |
| 607 | long tmo = x->lft.soft_add_expires_seconds + | 607 | time64_t tmo = x->lft.soft_add_expires_seconds + |
| 608 | x->curlft.add_time - now; | 608 | x->curlft.add_time - now; |
| 609 | if (tmo <= 0) { | 609 | if (tmo <= 0) { |
| 610 | warn = 1; | 610 | warn = 1; |
| @@ -616,8 +616,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 5 unmodified lines | |||
| 616 | } | 616 | } |
| 617 | } | 617 | } |
| 618 | if (x->lft.soft_use_expires_seconds) { | 618 | if (x->lft.soft_use_expires_seconds) { |
| 619 | long tmo = x->lft.soft_use_expires_seconds + | 619 | time64_t tmo = x->lft.soft_use_expires_seconds + |
| 620 | (x->curlft.use_time ? : now) - now; | 620 | (READ_ONCE(x->curlft.use_time) ? : now) - now; |
| 621 | if (tmo <= 0) | 621 | if (tmo <= 0) |
| 622 | warn = 1; | 622 | warn = 1; |
| 623 | else if (tmo < next) | 623 | else if (tmo < next) |
| @@ -1906,7 +1906,7 @@ out: · 1282 unmodified lines | |||
| 1906 | 1906 | ||
| 1907 | hrtimer_start(&x1->mtimer, ktime_set(1, 0), | 1907 | hrtimer_start(&x1->mtimer, ktime_set(1, 0), |
| 1908 | HRTIMER_MODE_REL_SOFT); | 1908 | HRTIMER_MODE_REL_SOFT); |
| 1909 | if (x1->curlft.use_time) | 1909 | if (READ_ONCE(x1->curlft.use_time)) |
| 1910 | xfrm_state_check_expire(x1); | 1910 | xfrm_state_check_expire(x1); |
| 1911 | 1911 | ||
| 1912 | if (x->props.smark.m || x->props.smark.v || x->if_id) { | 1912 | if (x->props.smark.m || x->props.smark.v || x->if_id) { |
| @@ -1940,8 +1940,8 @@ int xfrm_state_check_expire(struct xfrm_state *x) · 27 unmodified lines | |||
| 1940 | { | 1940 | { |
| 1941 | xfrm_dev_state_update_curlft(x); | 1941 | xfrm_dev_state_update_curlft(x); |
| 1942 | 1942 | ||
| 1943 | if (!x->curlft.use_time) | 1943 | if (!READ_ONCE(x->curlft.use_time)) |
| 1944 | x->curlft.use_time = ktime_get_real_seconds(); | 1944 | WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds()); |
| 1945 | 1945 | ||
| 1946 | if (x->curlft.bytes >= x->lft.hard_byte_limit || | 1946 | if (x->curlft.bytes >= x->lft.hard_byte_limit || |
| 1947 | x->curlft.packets >= x->lft.hard_packet_limit) { | 1947 | x->curlft.packets >= x->lft.hard_packet_limit) { |
| @@ -66,9 +66,13 @@ endif · 65 unmodified lines | |||
| 66 | # Don't stop modules_install even if we can't sign external modules. | 66 | # Don't stop modules_install even if we can't sign external modules. |
| 67 | # | 67 | # |
| 68 | ifeq ($(CONFIG_MODULE_SIG_ALL),y) | 68 | ifeq ($(CONFIG_MODULE_SIG_ALL),y) |
| 69 | ifeq ($(filter pkcs11:%, $(CONFIG_MODULE_SIG_KEY)),) | ||
| 69 | sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(srctree)/)$(CONFIG_MODULE_SIG_KEY) | 70 | sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(srctree)/)$(CONFIG_MODULE_SIG_KEY) |
| 71 | else | ||
| 72 | sig-key := $(CONFIG_MODULE_SIG_KEY) | ||
| 73 | endif | ||
| 70 | quiet_cmd_sign = SIGN $@ | 74 | quiet_cmd_sign = SIGN $@ |
| 71 | cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(sig-key) certs/signing_key.x509 $@ \ | 75 | cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) "$(sig-key)" certs/signing_key.x509 $@ \ |
| 72 | $(if $(KBUILD_EXTMOD),|| true) | 76 | $(if $(KBUILD_EXTMOD),|| true) |
| 73 | else | 77 | else |
| 74 | quiet_cmd_sign := | 78 | quiet_cmd_sign := |
| @@ -246,7 +246,7 @@ test_vlan_ingress_modify() · 245 unmodified lines | |||
| 246 | bridge vlan add dev $swp2 vid 300 | 246 | bridge vlan add dev $swp2 vid 300 |
| 247 | 247 | ||
| 248 | tc filter add dev $swp1 ingress chain $(IS1 2) pref 3 \ | 248 | tc filter add dev $swp1 ingress chain $(IS1 2) pref 3 \ |
| 249 | protocol 802.1Q flower skip_sw vlan_id 200 \ | 249 | protocol 802.1Q flower skip_sw vlan_id 200 src_mac $h1_mac \ |
| 250 | action vlan modify id 300 \ | 250 | action vlan modify id 300 \ |
| 251 | action goto chain $(IS2 0 0) | 251 | action goto chain $(IS2 0 0) |
| 252 | 252 | ||
File mode changed from 100644 to 100755.
| @@ -237,6 +237,11 @@ static void guest_check_s1ptw_wr_in_dirty_log(void) · 236 unmodified lines | |||
| 237 | GUEST_SYNC(CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG); | 237 | GUEST_SYNC(CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static void guest_check_no_s1ptw_wr_in_dirty_log(void) | ||
| 241 | { | ||
| 242 | GUEST_SYNC(CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG); | ||
| 243 | } | ||
| 244 | |||
| 240 | static void guest_exec(void) | 245 | static void guest_exec(void) |
| 241 | { | 246 | { |
| 242 | int (*code)(void) = (int (*)(void))TEST_EXEC_GVA; | 247 | int (*code)(void) = (int (*)(void))TEST_EXEC_GVA; |
| @@ -304,7 +309,7 @@ static struct uffd_args { · 61 unmodified lines | |||
| 304 | 309 | ||
| 305 | /* Returns true to continue the test, and false if it should be skipped. */ | 310 | /* Returns true to continue the test, and false if it should be skipped. */ |
| 306 | static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, | 311 | static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, |
| 307 | struct uffd_args *args, bool expect_write) | 312 | struct uffd_args *args) |
| 308 | { | 313 | { |
| 309 | uint64_t addr = msg->arg.pagefault.address; | 314 | uint64_t addr = msg->arg.pagefault.address; |
| 310 | uint64_t flags = msg->arg.pagefault.flags; | 315 | uint64_t flags = msg->arg.pagefault.flags; |
| @@ -313,7 +318,6 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, · 2 unmodified lines | |||
| 313 | 318 | ||
| 314 | TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, | 319 | TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, |
| 315 | "The only expected UFFD mode is MISSING"); | 320 | "The only expected UFFD mode is MISSING"); |
| 316 | ASSERT_EQ(!!(flags & UFFD_PAGEFAULT_FLAG_WRITE), expect_write); | ||
| 317 | ASSERT_EQ(addr, (uint64_t)args->hva); | 321 | ASSERT_EQ(addr, (uint64_t)args->hva); |
| 318 | 322 | ||
| 319 | pr_debug("uffd fault: addr=%p write=%d\n", | 323 | pr_debug("uffd fault: addr=%p write=%d\n", |
| @@ -337,19 +341,14 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, · 17 unmodified lines | |||
| 337 | return 0; | 341 | return 0; |
| 338 | } | 342 | } |
| 339 | 343 | ||
| 340 | static int uffd_pt_write_handler(int mode, int uffd, struct uffd_msg *msg) | 344 | static int uffd_pt_handler(int mode, int uffd, struct uffd_msg *msg) |
| 341 | { | ||
| 342 | return uffd_generic_handler(mode, uffd, msg, &pt_args, true); | ||
| 343 | } | ||
| 344 | |||
| 345 | static int uffd_data_write_handler(int mode, int uffd, struct uffd_msg *msg) | ||
| 346 | { | 345 | { |
| 347 | return uffd_generic_handler(mode, uffd, msg, &data_args, true); | 346 | return uffd_generic_handler(mode, uffd, msg, &pt_args); |
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | static int uffd_data_read_handler(int mode, int uffd, struct uffd_msg *msg) | 349 | static int uffd_data_handler(int mode, int uffd, struct uffd_msg *msg) |
| 351 | { | 350 | { |
| 352 | return uffd_generic_handler(mode, uffd, msg, &data_args, false); | 351 | return uffd_generic_handler(mode, uffd, msg, &data_args); |
| 353 | } | 352 | } |
| 354 | 353 | ||
| 355 | static void setup_uffd_args(struct userspace_mem_region *region, | 354 | static void setup_uffd_args(struct userspace_mem_region *region, |
| @@ -471,9 +470,12 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd) · 115 unmodified lines | |||
| 471 | { | 470 | { |
| 472 | struct userspace_mem_region *data_region, *pt_region; | 471 | struct userspace_mem_region *data_region, *pt_region; |
| 473 | bool continue_test = true; | 472 | bool continue_test = true; |
| 473 | uint64_t pte_gpa, pte_pg; | ||
| 474 | 474 | ||
| 475 | data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); | 475 | data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); |
| 476 | pt_region = vm_get_mem_region(vm, MEM_REGION_PT); | 476 | pt_region = vm_get_mem_region(vm, MEM_REGION_PT); |
| 477 | pte_gpa = addr_hva2gpa(vm, virt_get_pte_hva(vm, TEST_GVA)); | ||
| 478 | pte_pg = (pte_gpa - pt_region->region.guest_phys_addr) / getpagesize(); | ||
| 477 | 479 | ||
| 478 | if (cmd == CMD_SKIP_TEST) | 480 | if (cmd == CMD_SKIP_TEST) |
| 479 | continue_test = false; | 481 | continue_test = false; |
| @@ -486,13 +488,13 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd) · 6 unmodified lines | |||
| 486 | TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0), | 488 | TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0), |
| 487 | "Missing write in dirty log"); | 489 | "Missing write in dirty log"); |
| 488 | if (cmd & CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG) | 490 | if (cmd & CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG) |
| 489 | TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, 0), | 491 | TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, pte_pg), |
| 490 | "Missing s1ptw write in dirty log"); | 492 | "Missing s1ptw write in dirty log"); |
| 491 | if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG) | 493 | if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG) |
| 492 | TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0), | 494 | TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0), |
| 493 | "Unexpected write in dirty log"); | 495 | "Unexpected write in dirty log"); |
| 494 | if (cmd & CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG) | 496 | if (cmd & CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG) |
| 495 | TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, 0), | 497 | TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, pte_pg), |
| 496 | "Unexpected s1ptw write in dirty log"); | 498 | "Unexpected s1ptw write in dirty log"); |
| 497 | 499 | ||
| 498 | return continue_test; | 500 | return continue_test; |
| @@ -797,7 +799,7 @@ static void help(char *name) · 298 unmodified lines | |||
| 797 | .expected_events = { .uffd_faults = _uffd_faults, }, \ | 799 | .expected_events = { .uffd_faults = _uffd_faults, }, \ |
| 798 | } | 800 | } |
| 799 | 801 | ||
| 800 | #define TEST_DIRTY_LOG(_access, _with_af, _test_check) \ | 802 | #define TEST_DIRTY_LOG(_access, _with_af, _test_check, _pt_check) \ |
| 801 | { \ | 803 | { \ |
| 802 | .name = SCAT3(dirty_log, _access, _with_af), \ | 804 | .name = SCAT3(dirty_log, _access, _with_af), \ |
| 803 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 805 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -805,13 +807,12 @@ static void help(char *name) · 1 unmodified line | |||
| 805 | .guest_prepare = { _PREPARE(_with_af), \ | 807 | .guest_prepare = { _PREPARE(_with_af), \ |
| 806 | _PREPARE(_access) }, \ | 808 | _PREPARE(_access) }, \ |
| 807 | .guest_test = _access, \ | 809 | .guest_test = _access, \ |
| 808 | .guest_test_check = { _CHECK(_with_af), _test_check, \ | 810 | .guest_test_check = { _CHECK(_with_af), _test_check, _pt_check }, \ |
| 809 | guest_check_s1ptw_wr_in_dirty_log}, \ | ||
| 810 | .expected_events = { 0 }, \ | 811 | .expected_events = { 0 }, \ |
| 811 | } | 812 | } |
| 812 | 813 | ||
| 813 | #define TEST_UFFD_AND_DIRTY_LOG(_access, _with_af, _uffd_data_handler, \ | 814 | #define TEST_UFFD_AND_DIRTY_LOG(_access, _with_af, _uffd_data_handler, \ |
| 814 | _uffd_faults, _test_check) \ | 815 | _uffd_faults, _test_check, _pt_check) \ |
| 815 | { \ | 816 | { \ |
| 816 | .name = SCAT3(uffd_and_dirty_log, _access, _with_af), \ | 817 | .name = SCAT3(uffd_and_dirty_log, _access, _with_af), \ |
| 817 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 818 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -820,16 +821,17 @@ static void help(char *name) · 2 unmodified lines | |||
| 820 | _PREPARE(_access) }, \ | 821 | _PREPARE(_access) }, \ |
| 821 | .guest_test = _access, \ | 822 | .guest_test = _access, \ |
| 822 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 823 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 823 | .guest_test_check = { _CHECK(_with_af), _test_check }, \ | 824 | .guest_test_check = { _CHECK(_with_af), _test_check, _pt_check }, \ |
| 824 | .uffd_data_handler = _uffd_data_handler, \ | 825 | .uffd_data_handler = _uffd_data_handler, \ |
| 825 | .uffd_pt_handler = uffd_pt_write_handler, \ | 826 | .uffd_pt_handler = uffd_pt_handler, \ |
| 826 | .expected_events = { .uffd_faults = _uffd_faults, }, \ | 827 | .expected_events = { .uffd_faults = _uffd_faults, }, \ |
| 827 | } | 828 | } |
| 828 | 829 | ||
| 829 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ | 830 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ |
| 830 | { \ | 831 | { \ |
| 831 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 832 | .name = SCAT2(ro_memslot, _access), \ |
| 832 | .data_memslot_flags = KVM_MEM_READONLY, \ | 833 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 834 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 833 | .guest_prepare = { _PREPARE(_access) }, \ | 835 | .guest_prepare = { _PREPARE(_access) }, \ |
| 834 | .guest_test = _access, \ | 836 | .guest_test = _access, \ |
| 835 | .mmio_handler = _mmio_handler, \ | 837 | .mmio_handler = _mmio_handler, \ |
| @@ -840,6 +842,7 @@ static void help(char *name) · 4 unmodified lines | |||
| 840 | { \ | 842 | { \ |
| 841 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 843 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 842 | .data_memslot_flags = KVM_MEM_READONLY, \ | 844 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 845 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 843 | .guest_test = _access, \ | 846 | .guest_test = _access, \ |
| 844 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 847 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 845 | .expected_events = { .fail_vcpu_runs = 1 }, \ | 848 | .expected_events = { .fail_vcpu_runs = 1 }, \ |
| @@ -848,9 +851,9 @@ static void help(char *name) · 2 unmodified lines | |||
| 848 | #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits, \ | 851 | #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits, \ |
| 849 | _test_check) \ | 852 | _test_check) \ |
| 850 | { \ | 853 | { \ |
| 851 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 854 | .name = SCAT2(ro_memslot, _access), \ |
| 852 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 855 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 853 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 856 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 854 | .guest_prepare = { _PREPARE(_access) }, \ | 857 | .guest_prepare = { _PREPARE(_access) }, \ |
| 855 | .guest_test = _access, \ | 858 | .guest_test = _access, \ |
| 856 | .guest_test_check = { _test_check }, \ | 859 | .guest_test_check = { _test_check }, \ |
| @@ -862,7 +865,7 @@ static void help(char *name) · 5 unmodified lines | |||
| 862 | { \ | 865 | { \ |
| 863 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ | 866 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ |
| 864 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 867 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 865 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 868 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 866 | .guest_test = _access, \ | 869 | .guest_test = _access, \ |
| 867 | .guest_test_check = { _test_check }, \ | 870 | .guest_test_check = { _test_check }, \ |
| 868 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 871 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| @@ -874,11 +877,12 @@ static void help(char *name) · 5 unmodified lines | |||
| 874 | { \ | 877 | { \ |
| 875 | .name = SCAT2(ro_memslot_uffd, _access), \ | 878 | .name = SCAT2(ro_memslot_uffd, _access), \ |
| 876 | .data_memslot_flags = KVM_MEM_READONLY, \ | 879 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 880 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 877 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 881 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 878 | .guest_prepare = { _PREPARE(_access) }, \ | 882 | .guest_prepare = { _PREPARE(_access) }, \ |
| 879 | .guest_test = _access, \ | 883 | .guest_test = _access, \ |
| 880 | .uffd_data_handler = _uffd_data_handler, \ | 884 | .uffd_data_handler = _uffd_data_handler, \ |
| 881 | .uffd_pt_handler = uffd_pt_write_handler, \ | 885 | .uffd_pt_handler = uffd_pt_handler, \ |
| 882 | .mmio_handler = _mmio_handler, \ | 886 | .mmio_handler = _mmio_handler, \ |
| 883 | .expected_events = { .mmio_exits = _mmio_exits, \ | 887 | .expected_events = { .mmio_exits = _mmio_exits, \ |
| 884 | .uffd_faults = _uffd_faults }, \ | 888 | .uffd_faults = _uffd_faults }, \ |
| @@ -889,10 +893,11 @@ static void help(char *name) · 4 unmodified lines | |||
| 889 | { \ | 893 | { \ |
| 890 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 894 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 891 | .data_memslot_flags = KVM_MEM_READONLY, \ | 895 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 896 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 892 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 897 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 893 | .guest_test = _access, \ | 898 | .guest_test = _access, \ |
| 894 | .uffd_data_handler = _uffd_data_handler, \ | 899 | .uffd_data_handler = _uffd_data_handler, \ |
| 895 | .uffd_pt_handler = uffd_pt_write_handler, \ | 900 | .uffd_pt_handler = uffd_pt_handler, \ |
| 896 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 901 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 897 | .expected_events = { .fail_vcpu_runs = 1, \ | 902 | .expected_events = { .fail_vcpu_runs = 1, \ |
| 898 | .uffd_faults = _uffd_faults }, \ | 903 | .uffd_faults = _uffd_faults }, \ |
| @@ -933,44 +938,51 @@ static struct test_desc tests[] = { · 34 unmodified lines | |||
| 933 | * (S1PTW). | 938 | * (S1PTW). |
| 934 | */ | 939 | */ |
| 935 | TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 940 | TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 936 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 941 | uffd_data_handler, uffd_pt_handler, 2), |
| 937 | /* no_af should also lead to a PT write. */ | ||
| 938 | TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 942 | TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 939 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 943 | uffd_data_handler, uffd_pt_handler, 2), |
| 940 | /* Note how that cas invokes the read handler. */ | ||
| 941 | TEST_UFFD(guest_cas, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 944 | TEST_UFFD(guest_cas, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 942 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 945 | uffd_data_handler, uffd_pt_handler, 2), |
| 943 | /* | 946 | /* |
| 944 | * Can't test guest_at with_af as it's IMPDEF whether the AF is set. | 947 | * Can't test guest_at with_af as it's IMPDEF whether the AF is set. |
| 945 | * The S1PTW fault should still be marked as a write. | 948 | * The S1PTW fault should still be marked as a write. |
| 946 | */ | 949 | */ |
| 947 | TEST_UFFD(guest_at, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 950 | TEST_UFFD(guest_at, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 948 | uffd_data_read_handler, uffd_pt_write_handler, 1), | 951 | uffd_no_handler, uffd_pt_handler, 1), |
| 949 | TEST_UFFD(guest_ld_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 952 | TEST_UFFD(guest_ld_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 950 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 953 | uffd_data_handler, uffd_pt_handler, 2), |
| 951 | TEST_UFFD(guest_write64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 954 | TEST_UFFD(guest_write64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 952 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 955 | uffd_data_handler, uffd_pt_handler, 2), |
| 953 | TEST_UFFD(guest_dc_zva, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 956 | TEST_UFFD(guest_dc_zva, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 954 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 957 | uffd_data_handler, uffd_pt_handler, 2), |
| 955 | TEST_UFFD(guest_st_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 958 | TEST_UFFD(guest_st_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 956 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 959 | uffd_data_handler, uffd_pt_handler, 2), |
| 957 | TEST_UFFD(guest_exec, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 960 | TEST_UFFD(guest_exec, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 958 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 961 | uffd_data_handler, uffd_pt_handler, 2), |
| 959 | 962 | ||
| 960 | /* | 963 | /* |
| 961 | * Try accesses when the data and PT memory regions are both | 964 | * Try accesses when the data and PT memory regions are both |
| 962 | * tracked for dirty logging. | 965 | * tracked for dirty logging. |
| 963 | */ | 966 | */ |
| 964 | TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log), | 967 | TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log, |
| 965 | /* no_af should also lead to a PT write. */ | 968 | guest_check_s1ptw_wr_in_dirty_log), |
| 966 | TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log), | 969 | TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log, |
| 967 | TEST_DIRTY_LOG(guest_ld_preidx, with_af, guest_check_no_write_in_dirty_log), | 970 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 968 | TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log), | 971 | TEST_DIRTY_LOG(guest_ld_preidx, with_af, |
| 969 | TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log), | 972 | guest_check_no_write_in_dirty_log, |
| 970 | TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log), | 973 | guest_check_s1ptw_wr_in_dirty_log), |
| 971 | TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log), | 974 | TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log, |
| 972 | TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log), | 975 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 973 | TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log), | 976 | TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log, |
| 977 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 978 | TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log, | ||
| 979 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 980 | TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log, | ||
| 981 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 982 | TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log, | ||
| 983 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 984 | TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log, | ||
| 985 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 974 | 986 | ||
| 975 | /* | 987 | /* |
| 976 | * Access when the data and PT memory regions are both marked for | 988 | * Access when the data and PT memory regions are both marked for |
| @@ -980,29 +992,43 @@ static struct test_desc tests[] = { · 3 unmodified lines | |||
| 980 | * fault, and nothing in the dirty log. Any S1PTW should result in | 992 | * fault, and nothing in the dirty log. Any S1PTW should result in |
| 981 | * a write in the dirty log and a userfaultfd write. | 993 | * a write in the dirty log and a userfaultfd write. |
| 982 | */ | 994 | */ |
| 983 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, uffd_data_read_handler, 2, | 995 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, |
| 984 | guest_check_no_write_in_dirty_log), | 996 | uffd_data_handler, 2, |
| 985 | /* no_af should also lead to a PT write. */ | 997 | guest_check_no_write_in_dirty_log, |
| 986 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, uffd_data_read_handler, 2, | 998 | guest_check_s1ptw_wr_in_dirty_log), |
| 987 | guest_check_no_write_in_dirty_log), | 999 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, |
| 988 | TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, uffd_data_read_handler, | 1000 | uffd_data_handler, 2, |
| 989 | 2, guest_check_no_write_in_dirty_log), | 1001 | guest_check_no_write_in_dirty_log, |
| 990 | TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, 0, 1, | 1002 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 991 | guest_check_no_write_in_dirty_log), | 1003 | TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, |
| 992 | TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, uffd_data_read_handler, 2, | 1004 | uffd_data_handler, |
| 993 | guest_check_no_write_in_dirty_log), | 1005 | 2, guest_check_no_write_in_dirty_log, |
| 994 | TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, uffd_data_write_handler, | 1006 | guest_check_s1ptw_wr_in_dirty_log), |
| 995 | 2, guest_check_write_in_dirty_log), | 1007 | TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, uffd_no_handler, 1, |
| 996 | TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, uffd_data_read_handler, 2, | 1008 | guest_check_no_write_in_dirty_log, |
| 997 | guest_check_write_in_dirty_log), | 1009 | guest_check_s1ptw_wr_in_dirty_log), |
| 998 | TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, uffd_data_write_handler, | 1010 | TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, |
| 999 | 2, guest_check_write_in_dirty_log), | 1011 | uffd_data_handler, 2, |
| 1012 | guest_check_no_write_in_dirty_log, | ||
| 1013 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 1014 | TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, | ||
| 1015 | uffd_data_handler, | ||
| 1016 | 2, guest_check_write_in_dirty_log, | ||
| 1017 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 1018 | TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, | ||
| 1019 | uffd_data_handler, 2, | ||
| 1020 | guest_check_write_in_dirty_log, | ||
| 1021 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 1022 | TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, | ||
| 1023 | uffd_data_handler, | ||
| 1024 | 2, guest_check_write_in_dirty_log, | ||
| 1025 | guest_check_s1ptw_wr_in_dirty_log), | ||
| 1000 | TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af, | 1026 | TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af, |
| 1001 | uffd_data_write_handler, 2, | 1027 | uffd_data_handler, 2, |
| 1002 | guest_check_write_in_dirty_log), | 1028 | guest_check_write_in_dirty_log, |
| 1003 | 1029 | guest_check_s1ptw_wr_in_dirty_log), | |
| 1004 | /* | 1030 | /* |
| 1005 | * Try accesses when the data memory region is marked read-only | 1031 | * Access when both the PT and data regions are marked read-only |
| 1006 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an | 1032 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an |
| 1007 | * MMIO exit, writes with no syndrome (e.g., CAS) result in a | 1033 | * MMIO exit, writes with no syndrome (e.g., CAS) result in a |
| 1008 | * failed vcpu run, and reads/execs with and without syndroms do | 1034 | * failed vcpu run, and reads/execs with and without syndroms do |
| @@ -1018,7 +1044,7 @@ static struct test_desc tests[] = { · 9 unmodified lines | |||
| 1018 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), | 1044 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), |
| 1019 | 1045 | ||
| 1020 | /* | 1046 | /* |
| 1021 | * Access when both the data region is both read-only and marked | 1047 | * The PT and data regions are both read-only and marked |
| 1022 | * for dirty logging at the same time. The expected result is that | 1048 | * for dirty logging at the same time. The expected result is that |
| 1023 | * for writes there should be no write in the dirty log. The | 1049 | * for writes there should be no write in the dirty log. The |
| 1024 | * readonly handling is the same as if the memslot was not marked | 1050 | * readonly handling is the same as if the memslot was not marked |
| @@ -1043,7 +1069,7 @@ static struct test_desc tests[] = { · 18 unmodified lines | |||
| 1043 | guest_check_no_write_in_dirty_log), | 1069 | guest_check_no_write_in_dirty_log), |
| 1044 | 1070 | ||
| 1045 | /* | 1071 | /* |
| 1046 | * Access when the data region is both read-only and punched with | 1072 | * The PT and data regions are both read-only and punched with |
| 1047 | * holes tracked with userfaultfd. The expected result is the | 1073 | * holes tracked with userfaultfd. The expected result is the |
| 1048 | * union of both userfaultfd and read-only behaviors. For example, | 1074 | * union of both userfaultfd and read-only behaviors. For example, |
| 1049 | * write accesses result in a userfaultfd write fault and an MMIO | 1075 | * write accesses result in a userfaultfd write fault and an MMIO |
| @@ -1051,22 +1077,15 @@ static struct test_desc tests[] = { · 1 unmodified line | |||
| 1051 | * no userfaultfd write fault. Reads result in userfaultfd getting | 1077 | * no userfaultfd write fault. Reads result in userfaultfd getting |
| 1052 | * triggered. | 1078 | * triggered. |
| 1053 | */ | 1079 | */ |
| 1054 | TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, | 1080 | TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, uffd_data_handler, 2), |
| 1055 | uffd_data_read_handler, 2), | 1081 | TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, uffd_data_handler, 2), |
| 1056 | TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, | 1082 | TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, uffd_no_handler, 1), |
| 1057 | uffd_data_read_handler, 2), | 1083 | TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, uffd_data_handler, 2), |
| 1058 | TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, | ||
| 1059 | uffd_no_handler, 1), | ||
| 1060 | TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, | ||
| 1061 | uffd_data_read_handler, 2), | ||
| 1062 | TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1, | 1084 | TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1, |
| 1063 | uffd_data_write_handler, 2), | 1085 | uffd_data_handler, 2), |
| 1064 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, | 1086 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, uffd_data_handler, 2), |
| 1065 | uffd_data_read_handler, 2), | 1087 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, uffd_no_handler, 1), |
| 1066 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, | 1088 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, uffd_no_handler, 1), |
| 1067 | uffd_no_handler, 1), | ||
| 1068 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, | ||
| 1069 | uffd_no_handler, 1), | ||
| 1070 | 1089 | ||
| 1071 | { 0 } | 1090 | { 0 } |
| 1072 | }; | 1091 | }; |
| @@ -893,14 +893,14 @@ sysctl_set() · 892 unmodified lines | |||
| 893 | local value=$1; shift | 893 | local value=$1; shift |
| 894 | 894 | ||
| 895 | SYSCTL_ORIG[$key]=$(sysctl -n $key) | 895 | SYSCTL_ORIG[$key]=$(sysctl -n $key) |
| 896 | sysctl -qw $key=$value | 896 | sysctl -qw $key="$value" |
| 897 | } | 897 | } |
| 898 | 898 | ||
| 899 | sysctl_restore() | 899 | sysctl_restore() |
| 900 | { | 900 | { |
| 901 | local key=$1; shift | 901 | local key=$1; shift |
| 902 | 902 | ||
| 903 | sysctl -qw $key=${SYSCTL_ORIG["$key"]} | 903 | sysctl -qw $key="${SYSCTL_ORIG[$key]}" |
| 904 | } | 904 | } |
| 905 | 905 | ||
| 906 | forwarding_enable() | 906 | forwarding_enable() |
| @@ -498,6 +498,12 @@ kill_events_pids() · 497 unmodified lines | |||
| 498 | kill_wait $evts_ns2_pid | 498 | kill_wait $evts_ns2_pid |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | kill_tests_wait() | ||
| 502 | { | ||
| 503 | kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1) | ||
| 504 | wait | ||
| 505 | } | ||
| 506 | |||
| 501 | pm_nl_set_limits() | 507 | pm_nl_set_limits() |
| 502 | { | 508 | { |
| 503 | local ns=$1 | 509 | local ns=$1 |
| @@ -1687,6 +1693,7 @@ chk_subflow_nr() · 1183 unmodified lines | |||
| 1687 | local subflow_nr=$3 | 1693 | local subflow_nr=$3 |
| 1688 | local cnt1 | 1694 | local cnt1 |
| 1689 | local cnt2 | 1695 | local cnt2 |
| 1696 | local dump_stats | ||
| 1690 | 1697 | ||
| 1691 | if [ -n "${need_title}" ]; then | 1698 | if [ -n "${need_title}" ]; then |
| 1692 | printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}" | 1699 | printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}" |
| @@ -1704,7 +1711,12 @@ chk_subflow_nr() · 11 unmodified lines | |||
| 1704 | echo "[ ok ]" | 1711 | echo "[ ok ]" |
| 1705 | fi | 1712 | fi |
| 1706 | 1713 | ||
| 1707 | [ "${dump_stats}" = 1 ] && ( ss -N $ns1 -tOni ; ss -N $ns1 -tOni | grep token; ip -n $ns1 mptcp endpoint ) | 1714 | if [ "${dump_stats}" = 1 ]; then |
| 1715 | ss -N $ns1 -tOni | ||
| 1716 | ss -N $ns1 -tOni | grep token | ||
| 1717 | ip -n $ns1 mptcp endpoint | ||
| 1718 | dump_stats | ||
| 1719 | fi | ||
| 1708 | } | 1720 | } |
| 1709 | 1721 | ||
| 1710 | chk_link_usage() | 1722 | chk_link_usage() |
| @@ -3083,7 +3095,7 @@ endpoint_tests() · 1372 unmodified lines | |||
| 3083 | pm_nl_set_limits $ns1 2 2 | 3095 | pm_nl_set_limits $ns1 2 2 |
| 3084 | pm_nl_set_limits $ns2 2 2 | 3096 | pm_nl_set_limits $ns2 2 2 |
| 3085 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal | 3097 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| 3086 | run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow & | 3098 | run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow 2>/dev/null & |
| 3087 | 3099 | ||
| 3088 | wait_mpj $ns1 | 3100 | wait_mpj $ns1 |
| 3089 | pm_nl_check_endpoint 1 "creation" \ | 3101 | pm_nl_check_endpoint 1 "creation" \ |
| @@ -3096,14 +3108,14 @@ endpoint_tests() · 6 unmodified lines | |||
| 3096 | pm_nl_add_endpoint $ns2 10.0.2.2 flags signal | 3108 | pm_nl_add_endpoint $ns2 10.0.2.2 flags signal |
| 3097 | pm_nl_check_endpoint 0 "modif is allowed" \ | 3109 | pm_nl_check_endpoint 0 "modif is allowed" \ |
| 3098 | $ns2 10.0.2.2 id 1 flags signal | 3110 | $ns2 10.0.2.2 id 1 flags signal |
| 3099 | wait | 3111 | kill_tests_wait |
| 3100 | fi | 3112 | fi |
| 3101 | 3113 | ||
| 3102 | if reset "delete and re-add"; then | 3114 | if reset "delete and re-add"; then |
| 3103 | pm_nl_set_limits $ns1 1 1 | 3115 | pm_nl_set_limits $ns1 1 1 |
| 3104 | pm_nl_set_limits $ns2 1 1 | 3116 | pm_nl_set_limits $ns2 1 1 |
| 3105 | pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow | 3117 | pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow |
| 3106 | run_tests $ns1 $ns2 10.0.1.1 4 0 0 slow & | 3118 | run_tests $ns1 $ns2 10.0.1.1 4 0 0 speed_20 2>/dev/null & |
| 3107 | 3119 | ||
| 3108 | wait_mpj $ns2 | 3120 | wait_mpj $ns2 |
| 3109 | pm_nl_del_endpoint $ns2 2 10.0.2.2 | 3121 | pm_nl_del_endpoint $ns2 2 10.0.2.2 |
| @@ -3113,7 +3125,7 @@ endpoint_tests() · 3 unmodified lines | |||
| 3113 | pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow | 3125 | pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow |
| 3114 | wait_mpj $ns2 | 3126 | wait_mpj $ns2 |
| 3115 | chk_subflow_nr "" "after re-add" 2 | 3127 | chk_subflow_nr "" "after re-add" 2 |
| 3116 | wait | 3128 | kill_tests_wait |
| 3117 | fi | 3129 | fi |
| 3118 | } | 3130 | } |
| 3119 | 3131 | ||
| @@ -293,19 +293,11 @@ setup-vm() { · 292 unmodified lines | |||
| 293 | elif [[ -n $vtype && $vtype == "vnifilterg" ]]; then | 293 | elif [[ -n $vtype && $vtype == "vnifilterg" ]]; then |
| 294 | # Add per vni group config with 'bridge vni' api | 294 | # Add per vni group config with 'bridge vni' api |
| 295 | if [ -n "$group" ]; then | 295 | if [ -n "$group" ]; then |
| 296 | if [ "$family" == "v4" ]; then | 296 | if [ $mcast -eq 1 ]; then |
| 297 | if [ $mcast -eq 1 ]; then | 297 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group $group |
| 298 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group $group | 298 | else |
| 299 | else | 299 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote $group |
| 300 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote $group | 300 | fi |
| 301 | fi | ||
| 302 | else | ||
| 303 | if [ $mcast -eq 1 ]; then | ||
| 304 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group6 $group | ||
| 305 | else | ||
| 306 | bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote6 $group | ||
| 307 | fi | ||
| 308 | fi | ||
| 309 | fi | 301 | fi |
| 310 | fi | 302 | fi |
| 311 | done | 303 | done |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | |||
| 17 | #include <stdio.h> | 17 | #include <stdio.h> |
| 18 | #include <unistd.h> | 18 | #include <unistd.h> |
| 19 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
| 20 | #define __USE_GNU | ||
| 21 | #include <fcntl.h> | 20 | #include <fcntl.h> |
| 22 | 21 | ||
| 23 | #define MIN_FREE_PAGES 20 | 22 | #define MIN_FREE_PAGES 20 |