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 | 130 | Douglas Gilbert <dougg@torque.net> |
| 131 | 131 | Ed L. Cashin <ecashin@coraid.com> |
| 132 | 132 | Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com> |
| 133 | +Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com> | |
| 133 | 134 | Evgeniy Polyakov <johnpol@2ka.mipt.ru> |
| 134 | 135 | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> <ezequiel@collabora.com> |
| 135 | 136 | Felipe W Damasio <felipewd@terra.com.br> |
| @@ -1245,13 +1245,17 @@ PAGE_SIZE multiple when read back. · 1244 unmodified lines | ||
| 1245 | 1245 | This is a simple interface to trigger memory reclaim in the |
| 1246 | 1246 | target cgroup. |
| 1247 | 1247 | |
| 1248 | − This file accepts a string which contains the number of bytes to | |
| 1249 | − reclaim. | |
| 1248 | + This file accepts a single key, the number of bytes to reclaim. | |
| 1249 | + No nested keys are currently supported. | |
| 1250 | 1250 | |
| 1251 | 1251 | Example:: |
| 1252 | 1252 | |
| 1253 | 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 | 1259 | Please note that the kernel can over or under reclaim from |
| 1256 | 1260 | the target cgroup. If less bytes are reclaimed than the |
| 1257 | 1261 | specified amount, -EAGAIN is returned. |
| @@ -1263,13 +1267,6 @@ PAGE_SIZE multiple when read back. · 5 unmodified lines | ||
| 1263 | 1267 | This means that the networking layer will not adapt based on |
| 1264 | 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 | 1270 | memory.peak |
| 1274 | 1271 | A read-only single value file which exists on non-root |
| 1275 | 1272 | cgroups. |
| @@ -2,3 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | *.example.dts |
| 3 | 3 | /processed-schema*.yaml |
| 4 | 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 | 109 | msi-controller: |
| 110 | 110 | description: |
| 111 | − Only present if the Message Based Interrupt functionnality is | |
| 111 | + Only present if the Message Based Interrupt functionality is | |
| 112 | 112 | being exposed by the HW, and the mbi-ranges property present. |
| 113 | 113 | |
| 114 | 114 | mbi-ranges: |
| @@ -40,6 +40,8 @@ properties: · 39 unmodified lines | ||
| 40 | 40 | description: |
| 41 | 41 | Indicates that the setting of RTC time is allowed by the host CPU. |
| 42 | 42 | |
| 43 | + wakeup-source: true | |
| 44 | + | |
| 43 | 45 | required: |
| 44 | 46 | - compatible |
| 45 | 47 | - reg |
| @@ -16,5 +16,5 @@ Contents · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 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 | 20 | and Cc: netdev. |
| @@ -8070,9 +8070,13 @@ considering the state as complete. VMM needs to ensure that the dirty · 8069 unmodified lines | ||
| 8070 | 8070 | state is final and avoid missing dirty pages from another ioctl ordered |
| 8071 | 8071 | after the bitmap collection. |
| 8072 | 8072 | |
| 8073 | −NOTE: One example of using the backup bitmap is saving arm64 vgic/its | |
| 8074 | −tables through KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} command on | |
| 8075 | −KVM device "kvm-arm-vgic-its" when dirty ring is enabled. | |
| 8073 | +NOTE: Multiple examples of using the backup bitmap: (1) save vgic/its | |
| 8074 | +tables through command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} on | |
| 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 | 8081 | 8.30 KVM_CAP_XEN_HVM |
| 8078 | 8082 | -------------------- |
| @@ -15679,7 +15679,7 @@ OPENRISC ARCHITECTURE · 15678 unmodified lines | ||
| 15679 | 15679 | M: Jonas Bonn <jonas@southpole.se> |
| 15680 | 15680 | M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> |
| 15681 | 15681 | M: Stafford Horne <shorne@gmail.com> |
| 15682 | −L: openrisc@lists.librecores.org | |
| 15682 | +L: linux-openrisc@vger.kernel.org | |
| 15683 | 15683 | S: Maintained |
| 15684 | 15684 | W: http://openrisc.io |
| 15685 | 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 | 21753 | USB WEBCAM GADGET |
| 21754 | 21754 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 21755 | +M: Daniel Scally <dan.scally@ideasonboard.com> | |
| 21755 | 21756 | L: linux-usb@vger.kernel.org |
| 21756 | 21757 | S: Maintained |
| 21757 | 21758 | F: drivers/usb/gadget/function/*uvc* |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 2 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc6 | |
| 5 | +EXTRAVERSION = -rc7 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -2187,7 +2187,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, · 2186 unmodified lines | ||
| 2187 | 2187 | ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | |
| 2188 | 2188 | ite->collection->collection_id; |
| 2189 | 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 | 2339 | (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | |
| 2340 | 2340 | (dev->num_eventid_bits - 1)); |
| 2341 | 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 | 2526 | ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | |
| 2527 | 2527 | collection->collection_id); |
| 2528 | 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 | 2608 | val = 0; |
| 2609 | 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 | 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 | 2743 | static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) |
| 2744 | 2744 | { |
| 2745 | 2745 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| 2746 | − struct vgic_dist *dist = &kvm->arch.vgic; | |
| 2747 | 2746 | int ret = 0; |
| 2748 | 2747 | |
| 2749 | 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 | 2762 | vgic_its_reset(kvm, its); |
| 2764 | 2763 | break; |
| 2765 | 2764 | case KVM_DEV_ARM_ITS_SAVE_TABLES: |
| 2766 | − dist->save_its_tables_in_progress = true; | |
| 2767 | 2765 | ret = abi->save_tables(its); |
| 2768 | − dist->save_its_tables_in_progress = false; | |
| 2769 | 2766 | break; |
| 2770 | 2767 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: |
| 2771 | 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 | 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 | 2795 | static int vgic_its_set_attr(struct kvm_device *dev, |
| @@ -339,7 +339,7 @@ retry: · 338 unmodified lines | ||
| 339 | 339 | if (status) { |
| 340 | 340 | /* clear consumed data */ |
| 341 | 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 | 343 | if (ret) |
| 344 | 344 | return ret; |
| 345 | 345 | } |
| @@ -434,7 +434,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) · 88 unmodified lines | ||
| 434 | 434 | else |
| 435 | 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 | 438 | if (ret) |
| 439 | 439 | goto out; |
| 440 | 440 | } |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #define __KVM_ARM_VGIC_NEW_H__ |
| 7 | 7 | |
| 8 | 8 | #include <linux/irqchip/arm-gic-common.h> |
| 9 | +#include <asm/kvm_mmu.h> | |
| 9 | 10 | |
| 10 | 11 | #define PRODUCT_ID_KVM 0x4b /* ASCII code K */ |
| 11 | 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 | 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 | 149 | * This struct provides an intermediate representation of the fields contained |
| 136 | 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 | 170 | asmlinkage long |
| 171 | 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 | 177 | * ia64's clock_gettime() syscall is implemented as a vdso call |
| 175 | 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 | 188 | switch (which_clock) { |
| 186 | 189 | case CLOCK_REALTIME: |
| 187 | 190 | case CLOCK_MONOTONIC: |
| 188 | − s64 tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq); | |
| 189 | − struct timespec64 rtn_tp = ns_to_timespec64(tick_ns); | |
| 191 | + tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq); | |
| 192 | + rtn_tp = ns_to_timespec64(tick_ns); | |
| 190 | 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 | 1304 | int pdc_iodc_print(const unsigned char *str, unsigned count) |
| 1305 | 1305 | { |
| 1306 | − unsigned int i; | |
| 1306 | + unsigned int i, found = 0; | |
| 1307 | 1307 | unsigned long flags; |
| 1308 | 1308 | |
| 1309 | 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 | 1315 | iodc_dbuf[i+0] = '\r'; |
| 1316 | 1316 | iodc_dbuf[i+1] = '\n'; |
| 1317 | 1317 | i += 2; |
| 1318 | + found = 1; | |
| 1318 | 1319 | goto print; |
| 1319 | 1320 | default: |
| 1320 | 1321 | iodc_dbuf[i] = str[i]; |
| @@ -1330,7 +1331,7 @@ print: · 9 unmodified lines | ||
| 1330 | 1331 | __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0); |
| 1331 | 1332 | spin_unlock_irqrestore(&pdc_lock, flags); |
| 1332 | 1333 | |
| 1333 | − return i; | |
| 1334 | + return i - found; | |
| 1334 | 1335 | } |
| 1335 | 1336 | |
| 1336 | 1337 | #if !defined(BOOTLOADER) |
| @@ -126,6 +126,12 @@ long arch_ptrace(struct task_struct *child, long request, · 125 unmodified lines | ||
| 126 | 126 | unsigned long tmp; |
| 127 | 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 | 135 | switch (request) { |
| 130 | 136 | |
| 131 | 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 | 172 | addr >= sizeof(struct pt_regs)) |
| 167 | 173 | break; |
| 168 | 174 | if (addr == PT_IAOQ0 || addr == PT_IAOQ1) { |
| 169 | − data |= 3; /* ensure userspace privilege */ | |
| 175 | + data |= PRIV_USER; /* ensure userspace privilege */ | |
| 170 | 176 | } |
| 171 | 177 | if ((addr >= PT_GR1 && addr <= PT_GR31) || |
| 172 | 178 | addr == PT_IAOQ0 || addr == PT_IAOQ1 || |
| @@ -181,14 +187,14 @@ long arch_ptrace(struct task_struct *child, long request, · 8 unmodified lines | ||
| 181 | 187 | return copy_regset_to_user(child, |
| 182 | 188 | task_user_regset_view(current), |
| 183 | 189 | REGSET_GENERAL, |
| 184 | − 0, sizeof(struct user_regs_struct), | |
| 190 | + 0, user_regs_struct_size, | |
| 185 | 191 | datap); |
| 186 | 192 | |
| 187 | 193 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
| 188 | 194 | return copy_regset_from_user(child, |
| 189 | 195 | task_user_regset_view(current), |
| 190 | 196 | REGSET_GENERAL, |
| 191 | − 0, sizeof(struct user_regs_struct), | |
| 197 | + 0, user_regs_struct_size, | |
| 192 | 198 | datap); |
| 193 | 199 | |
| 194 | 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 | 291 | if (addr >= sizeof(struct pt_regs)) |
| 286 | 292 | break; |
| 287 | 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 | 296 | if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { |
| 291 | 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 | 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 | 317 | default: |
| 307 | 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 | 495 | case RI(iaoq[0]): |
| 485 | 496 | case RI(iaoq[1]): |
| 486 | 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 | 499 | return; |
| 489 | 500 | case RI(sar): regs->sar = val; |
| 490 | 501 | return; |
| @@ -97,6 +97,8 @@ static inline void tlb_flush(struct mmu_gather *tlb) · 96 unmodified lines | ||
| 97 | 97 | { |
| 98 | 98 | if (radix_enabled()) |
| 99 | 99 | radix__tlb_flush(tlb); |
| 100 | + | |
| 101 | + return hash__tlb_flush(tlb); | |
| 100 | 102 | } |
| 101 | 103 | |
| 102 | 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 | 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 | 185 | static inline unsigned long arch_local_save_flags(void) |
| 177 | 186 | { |
| 178 | 187 | return irq_soft_mask_return(); |
| @@ -192,7 +201,7 @@ static inline void arch_local_irq_enable(void) · 13 unmodified lines | ||
| 192 | 201 | |
| 193 | 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 | 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 | 340 | * is a different soft-masked interrupt pending that requires hard |
| 332 | 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 | 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 | 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 | 358 | * TODO: Add test for 64e |
| 349 | 359 | */ |
| 350 | − if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !power_pmu_wants_prompt_pmi()) | |
| 351 | − return false; | |
| 360 | + if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) { | |
| 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 | 372 | if (get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK) |
| 354 | 373 | return false; |
| @@ -358,18 +377,16 @@ static inline bool should_hard_irq_enable(void) · 3 unmodified lines | ||
| 358 | 377 | |
| 359 | 378 | /* |
| 360 | 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 | 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. | |
| 371 | − * There is no other reason to enable this way. | |
| 385 | + * Asynch interrupts come in with IRQS_ALL_DISABLED, | |
| 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 | 390 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; |
| 374 | 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 | 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 | 474 | return false; |
| 458 | 475 | } |
| @@ -27,7 +27,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(doorbell_exception) · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | ppc_msgsync(); |
| 29 | 29 | |
| 30 | − if (should_hard_irq_enable()) | |
| 30 | + if (should_hard_irq_enable(regs)) | |
| 31 | 31 | do_hard_irq_enable(); |
| 32 | 32 | |
| 33 | 33 | kvmppc_clear_host_ipi(smp_processor_id()); |
| @@ -864,7 +864,7 @@ _GLOBAL(load_up_spe) · 863 unmodified lines | ||
| 864 | 864 | * SPE unavailable trap from kernel - print a message, but let |
| 865 | 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 | 868 | lwz r3,_MSR(r1) |
| 869 | 869 | oris r3,r3,MSR_SPE@h |
| 870 | 870 | stw r3,_MSR(r1) /* enable use of SPE after return */ |
| @@ -881,6 +881,7 @@ KernelSPE: · 10 unmodified lines | ||
| 881 | 881 | #endif |
| 882 | 882 | .align 4,0 |
| 883 | 883 | |
| 884 | +SYM_FUNC_END(KernelSPE) | |
| 884 | 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 | 238 | irq = static_call(ppc_get_irq)(); |
| 239 | 239 | |
| 240 | 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 | 242 | do_hard_irq_enable(); |
| 243 | 243 | |
| 244 | 244 | /* And finally process it */ |
| @@ -515,7 +515,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt) · 514 unmodified lines | ||
| 515 | 515 | } |
| 516 | 516 | |
| 517 | 517 | /* Conditionally hard-enable interrupts. */ |
| 518 | − if (should_hard_irq_enable()) { | |
| 518 | + if (should_hard_irq_enable(regs)) { | |
| 519 | 519 | /* |
| 520 | 520 | * Ensure a positive value is written to the decrementer, or |
| 521 | 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 | 989 | * linux,drconf-usable-memory properties. Get an approximate on the |
| 990 | 990 | * number of usable memory entries and use for FDT size estimation. |
| 991 | 991 | */ |
| 992 | − usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) + | |
| 993 | − (2 * (resource_size(&crashk_res) / drmem_lmb_size()))); | |
| 994 | − | |
| 995 | − extra_size = (unsigned int)(usm_entries * sizeof(u64)); | |
| 992 | + if (drmem_lmb_size()) { | |
| 993 | + usm_entries = ((memory_hotplug_max() / drmem_lmb_size()) + | |
| 994 | + (2 * (resource_size(&crashk_res) / drmem_lmb_size()))); | |
| 995 | + extra_size = (unsigned int)(usm_entries * sizeof(u64)); | |
| 996 | + } else { | |
| 997 | + extra_size = 0; | |
| 998 | + } | |
| 996 | 999 | |
| 997 | 1000 | /* |
| 998 | 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 | 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 | 917 | asm("mr %0, 1" : "=r"(r1)); |
| 918 | 918 | asm("mflr %0" : "=r"(lr)); |
| 919 | 919 | asm("mfmsr %0" : "=r"(msr)); |
| 920 | − asm("bl 1f; 1: mflr %0" : "=r"(ip)); | |
| 921 | 920 | |
| 922 | 921 | memset(regs, 0, sizeof(*regs)); |
| 923 | 922 | regs->gpr[1] = r1; |
| 924 | − regs->nip = ip; | |
| 923 | + regs->nip = _THIS_IP_; | |
| 925 | 924 | regs->msr = msr; |
| 926 | 925 | regs->link = lr; |
| 927 | 926 | } |
| @@ -234,6 +234,14 @@ void radix__mark_rodata_ro(void) · 233 unmodified lines | ||
| 234 | 234 | end = (unsigned long)__end_rodata; |
| 235 | 235 | |
| 236 | 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 | 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 | 270 | static unsigned long next_boundary(unsigned long addr, unsigned long end) |
| 263 | 271 | { |
| 264 | 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 | 289 | if (addr < __pa_symbol(__srwx_boundary)) |
| 266 | 290 | return __pa_symbol(__srwx_boundary); |
| 267 | 291 | #endif |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | * Used to avoid races in counting the nest-pmu units during hotplug |
| 23 | 23 | * register and unregister |
| 24 | 24 | */ |
| 25 | −static DEFINE_SPINLOCK(nest_init_lock); | |
| 25 | +static DEFINE_MUTEX(nest_init_lock); | |
| 26 | 26 | static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc); |
| 27 | 27 | static struct imc_pmu **per_nest_pmu_arr; |
| 28 | 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 | 1629 | static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) |
| 1630 | 1630 | { |
| 1631 | 1631 | if (pmu_ptr->domain == IMC_DOMAIN_NEST) { |
| 1632 | − spin_lock(&nest_init_lock); | |
| 1632 | + mutex_lock(&nest_init_lock); | |
| 1633 | 1633 | if (nest_pmus == 1) { |
| 1634 | 1634 | cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE); |
| 1635 | 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 | 1640 | if (nest_pmus > 0) |
| 1641 | 1641 | nest_pmus--; |
| 1642 | − spin_unlock(&nest_init_lock); | |
| 1642 | + mutex_unlock(&nest_init_lock); | |
| 1643 | 1643 | } |
| 1644 | 1644 | |
| 1645 | 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 | 1796 | * rest. To handle the cpuhotplug callback unregister, we track |
| 1797 | 1797 | * the number of nest pmus in "nest_pmus". |
| 1798 | 1798 | */ |
| 1799 | − spin_lock(&nest_init_lock); | |
| 1799 | + mutex_lock(&nest_init_lock); | |
| 1800 | 1800 | if (nest_pmus == 0) { |
| 1801 | 1801 | ret = init_nest_pmu_ref(); |
| 1802 | 1802 | if (ret) { |
| 1803 | − spin_unlock(&nest_init_lock); | |
| 1803 | + mutex_unlock(&nest_init_lock); | |
| 1804 | 1804 | kfree(per_nest_pmu_arr); |
| 1805 | 1805 | per_nest_pmu_arr = NULL; |
| 1806 | 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 | 1808 | /* Register for cpu hotplug notification. */ |
| 1809 | 1809 | ret = nest_pmu_cpumask_init(); |
| 1810 | 1810 | if (ret) { |
| 1811 | − spin_unlock(&nest_init_lock); | |
| 1811 | + mutex_unlock(&nest_init_lock); | |
| 1812 | 1812 | kfree(nest_imc_refc); |
| 1813 | 1813 | kfree(per_nest_pmu_arr); |
| 1814 | 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 | 1818 | nest_pmus++; |
| 1819 | − spin_unlock(&nest_init_lock); | |
| 1819 | + mutex_unlock(&nest_init_lock); | |
| 1820 | 1820 | break; |
| 1821 | 1821 | case IMC_DOMAIN_CORE: |
| 1822 | 1822 | ret = core_imc_pmu_cpumask_init(); |
| @@ -80,6 +80,9 @@ ifeq ($(CONFIG_PERF_EVENTS),y) · 79 unmodified lines | ||
| 80 | 80 | KBUILD_CFLAGS += -fno-omit-frame-pointer |
| 81 | 81 | endif |
| 82 | 82 | |
| 83 | +# Avoid generating .eh_frame sections. | |
| 84 | +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables | |
| 85 | + | |
| 83 | 86 | KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) |
| 84 | 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 | 71 | enum riscv_isa_ext_key { |
| 72 | 72 | RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */ |
| 73 | − RISCV_ISA_EXT_KEY_ZIHINTPAUSE, | |
| 74 | 73 | RISCV_ISA_EXT_KEY_SVINVAL, |
| 75 | 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 | 90 | return RISCV_ISA_EXT_KEY_FPU; |
| 92 | 91 | case RISCV_ISA_EXT_d: |
| 93 | 92 | return RISCV_ISA_EXT_KEY_FPU; |
| 94 | − case RISCV_ISA_EXT_ZIHINTPAUSE: | |
| 95 | − return RISCV_ISA_EXT_KEY_ZIHINTPAUSE; | |
| 96 | 93 | case RISCV_ISA_EXT_SVINVAL: |
| 97 | 94 | return RISCV_ISA_EXT_KEY_SVINVAL; |
| 98 | 95 | default: |
| @@ -4,30 +4,26 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #ifndef __ASSEMBLY__ |
| 6 | 6 | |
| 7 | −#include <linux/jump_label.h> | |
| 8 | 7 | #include <asm/barrier.h> |
| 9 | −#include <asm/hwcap.h> | |
| 10 | 8 | |
| 11 | 9 | static inline void cpu_relax(void) |
| 12 | 10 | { |
| 13 | − if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) { | |
| 14 | 11 | #ifdef __riscv_muldiv |
| 15 | − int dummy; | |
| 16 | − /* In lieu of a halt instruction, induce a long-latency stall. */ | |
| 17 | − __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); | |
| 12 | + int dummy; | |
| 13 | + /* In lieu of a halt instruction, induce a long-latency stall. */ | |
| 14 | + __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); | |
| 18 | 15 | #endif |
| 19 | − } else { | |
| 20 | − /* | |
| 21 | − * Reduce instruction retirement. | |
| 22 | − * This assumes the PC changes. | |
| 23 | − */ | |
| 24 | −#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE | |
| 25 | − __asm__ __volatile__ ("pause"); | |
| 16 | + | |
| 17 | +#ifdef __riscv_zihintpause | |
| 18 | + /* | |
| 19 | + * Reduce instruction retirement. | |
| 20 | + * This assumes the PC changes. | |
| 21 | + */ | |
| 22 | + __asm__ __volatile__ ("pause"); | |
| 26 | 23 | #else |
| 27 | − /* Encoding of the pause instruction */ | |
| 28 | − __asm__ __volatile__ (".4byte 0x100000F"); | |
| 24 | + /* Encoding of the pause instruction */ | |
| 25 | + __asm__ __volatile__ (".4byte 0x100000F"); | |
| 29 | 26 | #endif |
| 30 | − } | |
| 31 | 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 | 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 | 66 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
| 52 | 67 | { |
| 53 | 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 | 70 | if (probe_addr & 0x1) |
| 56 | 71 | return -EILSEQ; |
| 57 | 72 | |
| 73 | + if (!arch_check_kprobe(p)) | |
| 74 | + return -EILSEQ; | |
| 75 | + | |
| 58 | 76 | /* copy instruction */ |
| 59 | 77 | p->opcode = *p->addr; |
| 60 | 78 | |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * Written by Niibe Yutaka and Paul Mundt |
| 5 | 5 | */ |
| 6 | 6 | OUTPUT_ARCH(sh) |
| 7 | +#define RUNTIME_DISCARD_EXIT | |
| 7 | 8 | #include <asm/thread_info.h> |
| 8 | 9 | #include <asm/cache.h> |
| 9 | 10 | #include <asm/vmlinux.lds.h> |
| @@ -39,7 +39,20 @@ static __always_inline unsigned long native_get_debugreg(int regno) · 38 unmodified lines | ||
| 39 | 39 | asm("mov %%db6, %0" :"=r" (val)); |
| 40 | 40 | break; |
| 41 | 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 | 56 | break; |
| 44 | 57 | default: |
| 45 | 58 | BUG(); |
| @@ -66,7 +79,16 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value) · 20 unmodified lines | ||
| 66 | 79 | asm("mov %0, %%db6" ::"r" (value)); |
| 67 | 80 | break; |
| 68 | 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 | 92 | break; |
| 71 | 93 | default: |
| 72 | 94 | BUG(); |
| @@ -769,8 +769,8 @@ static void __bfq_bic_change_cgroup(struct bfq_data *bfqd, · 768 unmodified lines | ||
| 769 | 769 | * request from the old cgroup. |
| 770 | 770 | */ |
| 771 | 771 | bfq_put_cooperator(sync_bfqq); |
| 772 | − bfq_release_process_ref(bfqd, sync_bfqq); | |
| 773 | 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 | 5426 | bfqq = bic_to_bfqq(bic, false); |
| 5427 | 5427 | if (bfqq) { |
| 5428 | − bfq_release_process_ref(bfqd, bfqq); | |
| 5428 | + struct bfq_queue *old_bfqq = bfqq; | |
| 5429 | + | |
| 5429 | 5430 | bfqq = bfq_get_queue(bfqd, bio, false, bic, true); |
| 5430 | 5431 | bic_set_bfqq(bic, bfqq, false); |
| 5432 | + bfq_release_process_ref(bfqd, old_bfqq); | |
| 5431 | 5433 | } |
| 5432 | 5434 | |
| 5433 | 5435 | bfqq = bic_to_bfqq(bic, true); |
| @@ -2001,6 +2001,10 @@ void blk_cgroup_bio_start(struct bio *bio) · 2000 unmodified lines | ||
| 2001 | 2001 | struct blkg_iostat_set *bis; |
| 2002 | 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 | 2008 | cpu = get_cpu(); |
| 2005 | 2009 | bis = per_cpu_ptr(bio->bi_blkg->iostat_cpu, cpu); |
| 2006 | 2010 | flags = u64_stats_update_begin_irqsave(&bis->sync); |
| @@ -4069,8 +4069,9 @@ EXPORT_SYMBOL(blk_mq_init_queue); · 4068 unmodified lines | ||
| 4069 | 4069 | * blk_mq_destroy_queue - shutdown a request queue |
| 4070 | 4070 | * @q: request queue to shutdown |
| 4071 | 4071 | * |
| 4072 | − * This shuts down a request queue allocated by blk_mq_init_queue() and drops | |
| 4073 | − * the initial reference. All future requests will failed with -ENODEV. | |
| 4072 | + * This shuts down a request queue allocated by blk_mq_init_queue(). All future | |
| 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 | 4076 | * Context: can sleep |
| 4076 | 4077 | */ |
| @@ -23,8 +23,8 @@ $(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE · 22 unmodified lines | ||
| 23 | 23 | targets += blacklist_hash_list |
| 24 | 24 | |
| 25 | 25 | quiet_cmd_extract_certs = CERT $@ |
| 26 | − cmd_extract_certs = $(obj)/extract-cert $(extract-cert-in) $@ | |
| 27 | −extract-cert-in = $(or $(filter-out $(obj)/extract-cert, $(real-prereqs)),"") | |
| 26 | + cmd_extract_certs = $(obj)/extract-cert "$(extract-cert-in)" $@ | |
| 27 | +extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs)) | |
| 28 | 28 | |
| 29 | 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 | 3110 | if (spd > 1) |
| 3111 | 3111 | mask &= (1 << (spd - 1)) - 1; |
| 3112 | − else | |
| 3112 | + else if (link->sata_spd) | |
| 3113 | 3113 | return -EINVAL; |
| 3114 | 3114 | |
| 3115 | 3115 | /* were we already at the bottom? */ |
| @@ -137,7 +137,7 @@ struct ublk_device { · 136 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | char *__queues; |
| 139 | 139 | |
| 140 | − unsigned short queue_size; | |
| 140 | + unsigned int queue_size; | |
| 141 | 141 | struct ublksrv_ctrl_dev_info dev_info; |
| 142 | 142 | |
| 143 | 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 | 167 | 0, 0); |
| 168 | 168 | |
| 169 | 169 | set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, |
| 170 | − &dma_fence_stub.flags); | |
| 170 | + &fence->flags); | |
| 171 | 171 | |
| 172 | 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 | 1007 | /* first try to find a slot in an existing linked list entry */ |
| 1008 | 1008 | for (prsv = efi_memreserve_root->next; prsv; ) { |
| 1009 | 1009 | rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB); |
| 1010 | + if (!rsv) | |
| 1011 | + return -ENOMEM; | |
| 1010 | 1012 | index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size); |
| 1011 | 1013 | if (index < rsv->size) { |
| 1012 | 1014 | rsv->entry[index].base = addr; |
| @@ -33,7 +33,7 @@ int __init efi_memattr_init(void) · 32 unmodified lines | ||
| 33 | 33 | return -ENOMEM; |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | − if (tbl->version > 1) { | |
| 36 | + if (tbl->version > 2) { | |
| 37 | 37 | pr_warn("Unexpected EFI Memory Attributes table version %d\n", |
| 38 | 38 | tbl->version); |
| 39 | 39 | goto unmap; |
| @@ -574,20 +574,27 @@ static int m10bmc_sec_probe(struct platform_device *pdev) · 573 unmodified lines | ||
| 574 | 574 | len = scnprintf(buf, SEC_UPDATE_LEN_MAX, "secure-update%d", |
| 575 | 575 | sec->fw_name_id); |
| 576 | 576 | sec->fw_name = kmemdup_nul(buf, len, GFP_KERNEL); |
| 577 | − if (!sec->fw_name) | |
| 578 | − return -ENOMEM; | |
| 577 | + if (!sec->fw_name) { | |
| 578 | + ret = -ENOMEM; | |
| 579 | + goto fw_name_fail; | |
| 580 | + } | |
| 579 | 581 | |
| 580 | 582 | fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name, |
| 581 | 583 | &m10bmc_ops, sec); |
| 582 | 584 | if (IS_ERR(fwl)) { |
| 583 | 585 | dev_err(sec->dev, "Firmware Upload driver failed to start\n"); |
| 584 | − kfree(sec->fw_name); | |
| 585 | − xa_erase(&fw_upload_xa, sec->fw_name_id); | |
| 586 | − return PTR_ERR(fwl); | |
| 586 | + ret = PTR_ERR(fwl); | |
| 587 | + goto fw_uploader_fail; | |
| 587 | 588 | } |
| 588 | 589 | |
| 589 | 590 | sec->fwl = fwl; |
| 590 | 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 | 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 | 213 | /* Allocate buffers from the service layer's pool. */ |
| 214 | 214 | for (i = 0; i < NUM_SVC_BUFS; i++) { |
| 215 | 215 | kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE); |
| 216 | − if (!kbuf) { | |
| 216 | + if (IS_ERR(kbuf)) { | |
| 217 | 217 | s10_free_buffers(mgr); |
| 218 | − ret = -ENOMEM; | |
| 218 | + ret = PTR_ERR(kbuf); | |
| 219 | 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 | 790 | * zero here */ |
| 791 | 791 | WARN_ON(simd != 0); |
| 792 | 792 | |
| 793 | − /* type 2 wave data */ | |
| 794 | − dst[(*no_fields)++] = 2; | |
| 793 | + /* type 3 wave data */ | |
| 794 | + dst[(*no_fields)++] = 3; | |
| 795 | 795 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_STATUS); |
| 796 | 796 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_LO); |
| 797 | 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 | 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 | 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 | 640 | AMD_CG_SUPPORT_GFX_CGCG | |
| 641 | 641 | AMD_CG_SUPPORT_GFX_CGLS | |
| 642 | 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 | 645 | adev->pg_flags = AMD_PG_SUPPORT_VCN | |
| 645 | 646 | AMD_PG_SUPPORT_VCN_DPG | |
| 646 | 647 | AMD_PG_SUPPORT_JPEG; |
| @@ -4501,6 +4501,17 @@ DEVICE_ATTR_WO(s3_debug); · 4500 unmodified lines | ||
| 4501 | 4501 | static int dm_early_init(void *handle) |
| 4502 | 4502 | { |
| 4503 | 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 | 4516 | switch (adev->asic_type) { |
| 4506 | 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 | 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 | 878 | .max_downscale_factor = { |
| 878 | − .argb8888 = 167, | |
| 879 | + .argb8888 = 250, | |
| 879 | 880 | .nv12 = 167, |
| 880 | 881 | .fp16 = 167 |
| 881 | 882 | }, |
| @@ -1763,7 +1764,7 @@ static bool dcn314_resource_construct( · 881 unmodified lines | ||
| 1763 | 1764 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; |
| 1764 | 1765 | pool->base.pipe_count = pool->base.res_cap->num_timing_generator; |
| 1765 | 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 | 1768 | dc->caps.i2c_speed_in_khz = 100; |
| 1768 | 1769 | dc->caps.i2c_speed_in_khz_hdcp = 100; |
| 1769 | 1770 | dc->caps.max_cursor_size = 256; |
| @@ -94,7 +94,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { · 93 unmodified lines | ||
| 94 | 94 | .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, |
| 95 | 95 | .calc_vupdate_position = dcn10_calc_vupdate_position, |
| 96 | 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 | 98 | .set_backlight_level = dcn21_set_backlight_level, |
| 99 | 99 | .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, |
| 100 | 100 | .hardware_release = dcn30_hardware_release, |
| @@ -3183,7 +3183,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman · 3182 unmodified lines | ||
| 3183 | 3183 | } else { |
| 3184 | 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 | 3187 | if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k]) |
| 3188 | 3188 | <= (isInterlaceTiming ? |
| 3189 | 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 | 532 | if (dmub->hw_funcs.reset) |
| 533 | 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 | 538 | cw0.offset.quad_part = inst_fb->gpu_addr; |
| 536 | 539 | cw0.region.base = DMUB_CW0_BASE; |
| 537 | 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 | 652 | if (dmub->hw_funcs.reset) |
| 650 | 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 | 664 | dmub->hw_init = false; |
| 653 | 665 | |
| 654 | 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 | 2007 | gc_ver == IP_VERSION(10, 3, 0) || |
| 2008 | 2008 | gc_ver == IP_VERSION(10, 1, 2) || |
| 2009 | 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 | 2012 | *states = ATTR_STATE_UNSUPPORTED; |
| 2012 | 2013 | } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { |
| 2013 | 2014 | if (!(gc_ver == IP_VERSION(10, 3, 1) || |
| 2014 | 2015 | gc_ver == IP_VERSION(10, 3, 0) || |
| 2015 | 2016 | gc_ver == IP_VERSION(10, 1, 2) || |
| 2016 | 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 | 2020 | *states = ATTR_STATE_UNSUPPORTED; |
| 2019 | 2021 | } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { |
| 2020 | 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 | 1517 | * For gpu reset, runpm and hibernation through BACO, |
| 1504 | 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 | 1319 | { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 }, |
| 1320 | 1320 | { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 }, |
| 1321 | 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 | 1324 | { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 }, |
| 1325 | 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 | 1861 | vm = ctx->vm; |
| 1862 | 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 | 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 | 1875 | return err; |
| 1867 | − | |
| 1868 | − i915_vm_get(vm); | |
| 1876 | + } | |
| 1869 | 1877 | |
| 1870 | 1878 | GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ |
| 1871 | 1879 | args->value = id; |
| @@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, · 304 unmodified lines | ||
| 305 | 305 | spin_unlock(&obj->vma.lock); |
| 306 | 306 | |
| 307 | 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 | 309 | /* Try to preallocate memory required to save swizzling on put-pages */ |
| 314 | 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 | 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 | 325 | return 0; |
| 325 | 326 | } |
| 326 | 327 | |
| @@ -528,7 +528,7 @@ retry: · 527 unmodified lines | ||
| 528 | 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 | 533 | struct intel_context *parent = intel_context_to_parent(ce); |
| 534 | 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 | 553 | active = rq; |
| 554 | 554 | } |
| 555 | + if (active) | |
| 556 | + active = i915_request_get_rcu(active); | |
| 555 | 557 | spin_unlock_irqrestore(&parent->guc_state.lock, flags); |
| 556 | 558 | |
| 557 | 559 | return active; |
| @@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce, · 267 unmodified lines | ||
| 268 | 268 | |
| 269 | 269 | struct i915_request *intel_context_create_request(struct intel_context *ce); |
| 270 | 270 | |
| 271 | −struct i915_request * | |
| 272 | −intel_context_find_active_request(struct intel_context *ce); | |
| 271 | +struct i915_request *intel_context_get_active_request(struct intel_context *ce); | |
| 273 | 272 | |
| 274 | 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 | 248 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, |
| 249 | 249 | ktime_t *now); |
| 250 | 250 | |
| 251 | −struct i915_request * | |
| 252 | −intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine); | |
| 251 | +void intel_engine_get_hung_entity(struct intel_engine_cs *engine, | |
| 252 | + struct intel_context **ce, struct i915_request **rq); | |
| 253 | 253 | |
| 254 | 254 | u32 intel_engine_context_size(struct intel_gt *gt, u8 class); |
| 255 | 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 | 2097 | static unsigned long read_ul(void *p, size_t x) |
| 2109 | 2098 | { |
| 2110 | 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 | 2192 | struct i915_request *hung_rq = NULL; |
| 2202 | − struct intel_context *ce; | |
| 2203 | − bool guc; | |
| 2204 | 2193 | |
| 2205 | 2194 | /* |
| 2206 | 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 | 2198 | * But the intention here is just to report an instantaneous snapshot |
| 2210 | 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 | 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 | 2205 | if (hung_rq) |
| 2226 | 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 | 2211 | intel_guc_dump_active_requests(engine, hung_rq, m); |
| 2230 | 2212 | else |
| 2231 | − intel_engine_dump_active_requests(&engine->sched_engine->requests, | |
| 2232 | − hung_rq, m); | |
| 2213 | + intel_execlists_dump_active_requests(engine, hung_rq, m); | |
| 2214 | + | |
| 2215 | + if (hung_rq) | |
| 2216 | + i915_request_put(hung_rq); | |
| 2233 | 2217 | } |
| 2234 | 2218 | |
| 2235 | 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 | 2223 | struct i915_gpu_error * const error = &engine->i915->gpu_error; |
| 2240 | 2224 | struct i915_request *rq; |
| 2241 | 2225 | intel_wakeref_t wakeref; |
| 2242 | − unsigned long flags; | |
| 2243 | 2226 | ktime_t dummy; |
| 2244 | 2227 | |
| 2245 | 2228 | if (header) { |
| @@ -2276,13 +2259,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 30 unmodified lines | ||
| 2276 | 2259 | i915_reset_count(error)); |
| 2277 | 2260 | print_properties(engine, m); |
| 2278 | 2261 | |
| 2279 | − spin_lock_irqsave(&engine->sched_engine->lock, flags); | |
| 2280 | 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 | 2264 | drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); |
| 2287 | 2265 | wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); |
| 2288 | 2266 | if (wakeref) { |
| @@ -2328,8 +2306,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings, · 39 unmodified lines | ||
| 2328 | 2306 | return siblings[0]->cops->create_virtual(siblings, count, flags); |
| 2329 | 2307 | } |
| 2330 | 2308 | |
| 2331 | −struct i915_request * | |
| 2332 | −intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) | |
| 2309 | +static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine) | |
| 2333 | 2310 | { |
| 2334 | 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 | 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 | 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 | 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 | 4178 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
| 4152 | 4179 | #include "selftest_execlists.c" |
| 4153 | 4180 | #endif |
| @@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, · 31 unmodified lines | ||
| 32 | 32 | int indent), |
| 33 | 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 | 39 | bool |
| 36 | 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 | 1702 | goto next_context; |
| 1703 | 1703 | |
| 1704 | 1704 | guilty = false; |
| 1705 | − rq = intel_context_find_active_request(ce); | |
| 1705 | + rq = intel_context_get_active_request(ce); | |
| 1706 | 1706 | if (!rq) { |
| 1707 | 1707 | head = ce->ring->tail; |
| 1708 | 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 | 1715 | head = intel_ring_wrap(ce->ring, rq->head); |
| 1716 | 1716 | |
| 1717 | 1717 | __i915_request_reset(rq, guilty); |
| 1718 | + i915_request_put(rq); | |
| 1718 | 1719 | out_replay: |
| 1719 | 1720 | guc_reset_state(ce, head, guilty); |
| 1720 | 1721 | next_context: |
| @@ -4817,6 +4818,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 3096 unmodified lines | ||
| 4817 | 4818 | |
| 4818 | 4819 | xa_lock_irqsave(&guc->context_lookup, flags); |
| 4819 | 4820 | xa_for_each(&guc->context_lookup, index, ce) { |
| 4821 | + bool found; | |
| 4822 | + | |
| 4820 | 4823 | if (!kref_get_unless_zero(&ce->ref)) |
| 4821 | 4824 | continue; |
| 4822 | 4825 | |
| @@ -4833,10 +4836,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) · 10 unmodified lines | ||
| 4833 | 4836 | goto next; |
| 4834 | 4837 | } |
| 4835 | 4838 | |
| 4839 | + found = false; | |
| 4840 | + spin_lock(&ce->guc_state.lock); | |
| 4836 | 4841 | list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { |
| 4837 | 4842 | if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) |
| 4838 | 4843 | continue; |
| 4839 | 4844 | |
| 4845 | + found = true; | |
| 4846 | + break; | |
| 4847 | + } | |
| 4848 | + spin_unlock(&ce->guc_state.lock); | |
| 4849 | + | |
| 4850 | + if (found) { | |
| 4840 | 4851 | intel_engine_set_hung_context(engine, ce); |
| 4841 | 4852 | |
| 4842 | 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 | 4855 | xa_lock(&guc->context_lookup); |
| 4845 | 4856 | goto done; |
| 4846 | 4857 | } |
| 4858 | + | |
| 4847 | 4859 | next: |
| 4848 | 4860 | intel_context_put(ce); |
| 4849 | 4861 | xa_lock(&guc->context_lookup); |
| @@ -1596,43 +1596,20 @@ capture_engine(struct intel_engine_cs *engine, · 1595 unmodified lines | ||
| 1596 | 1596 | { |
| 1597 | 1597 | struct intel_engine_capture_vma *capture = NULL; |
| 1598 | 1598 | struct intel_engine_coredump *ee; |
| 1599 | − struct intel_context *ce; | |
| 1599 | + struct intel_context *ce = NULL; | |
| 1600 | 1600 | struct i915_request *rq = NULL; |
| 1601 | − unsigned long flags; | |
| 1602 | 1601 | |
| 1603 | 1602 | ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); |
| 1604 | 1603 | if (!ee) |
| 1605 | 1604 | return NULL; |
| 1606 | 1605 | |
| 1607 | − ce = intel_engine_get_hung_context(engine); | |
| 1608 | − if (ce) { | |
| 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) | |
| 1606 | + intel_engine_get_hung_entity(engine, &ce, &rq); | |
| 1607 | + if (!rq || !i915_request_started(rq)) | |
| 1629 | 1608 | goto no_request_capture; |
| 1630 | 1609 | |
| 1631 | 1610 | capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); |
| 1632 | − if (!capture) { | |
| 1633 | − i915_request_put(rq); | |
| 1611 | + if (!capture) | |
| 1634 | 1612 | goto no_request_capture; |
| 1635 | − } | |
| 1636 | 1613 | if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) |
| 1637 | 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 | 1619 | return ee; |
| 1643 | 1620 | |
| 1644 | 1621 | no_request_capture: |
| 1622 | + if (rq) | |
| 1623 | + i915_request_put(rq); | |
| 1645 | 1624 | kfree(ee); |
| 1646 | 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 | 97 | int gp102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 98 | 98 | int gp10b_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 99 | 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 | 101 | int ga100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **); |
| 101 | 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 | 151 | static enum nvkm_memory_target |
| 152 | 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 | 157 | return NVKM_MEM_TARGET_HOST; |
| 155 | 158 | } |
| 156 | 159 | |
| @@ -2405,7 +2405,7 @@ nv162_chipset = { · 2404 unmodified lines | ||
| 2405 | 2405 | .bus = { 0x00000001, gf100_bus_new }, |
| 2406 | 2406 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2407 | 2407 | .fault = { 0x00000001, tu102_fault_new }, |
| 2408 | − .fb = { 0x00000001, gv100_fb_new }, | |
| 2408 | + .fb = { 0x00000001, tu102_fb_new }, | |
| 2409 | 2409 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2410 | 2410 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2411 | 2411 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2440,7 +2440,7 @@ nv164_chipset = { · 28 unmodified lines | ||
| 2440 | 2440 | .bus = { 0x00000001, gf100_bus_new }, |
| 2441 | 2441 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2442 | 2442 | .fault = { 0x00000001, tu102_fault_new }, |
| 2443 | − .fb = { 0x00000001, gv100_fb_new }, | |
| 2443 | + .fb = { 0x00000001, tu102_fb_new }, | |
| 2444 | 2444 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2445 | 2445 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2446 | 2446 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2475,7 +2475,7 @@ nv166_chipset = { · 28 unmodified lines | ||
| 2475 | 2475 | .bus = { 0x00000001, gf100_bus_new }, |
| 2476 | 2476 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2477 | 2477 | .fault = { 0x00000001, tu102_fault_new }, |
| 2478 | − .fb = { 0x00000001, gv100_fb_new }, | |
| 2478 | + .fb = { 0x00000001, tu102_fb_new }, | |
| 2479 | 2479 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2480 | 2480 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2481 | 2481 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2510,7 +2510,7 @@ nv167_chipset = { · 28 unmodified lines | ||
| 2510 | 2510 | .bus = { 0x00000001, gf100_bus_new }, |
| 2511 | 2511 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2512 | 2512 | .fault = { 0x00000001, tu102_fault_new }, |
| 2513 | − .fb = { 0x00000001, gv100_fb_new }, | |
| 2513 | + .fb = { 0x00000001, tu102_fb_new }, | |
| 2514 | 2514 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2515 | 2515 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2516 | 2516 | .gsp = { 0x00000001, gv100_gsp_new }, |
| @@ -2545,7 +2545,7 @@ nv168_chipset = { · 28 unmodified lines | ||
| 2545 | 2545 | .bus = { 0x00000001, gf100_bus_new }, |
| 2546 | 2546 | .devinit = { 0x00000001, tu102_devinit_new }, |
| 2547 | 2547 | .fault = { 0x00000001, tu102_fault_new }, |
| 2548 | − .fb = { 0x00000001, gv100_fb_new }, | |
| 2548 | + .fb = { 0x00000001, tu102_fb_new }, | |
| 2549 | 2549 | .fuse = { 0x00000001, gm107_fuse_new }, |
| 2550 | 2550 | .gpio = { 0x00000001, gk104_gpio_new }, |
| 2551 | 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 | 48 | img += 4; |
| 49 | 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 | 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 | 74 | img += 4; |
| 65 | 75 | len -= 4; |
| 66 | 76 | } |
| 77 | + | |
| 78 | + WARN_ON(len); | |
| 67 | 79 | } |
| 68 | 80 | |
| 69 | 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 | 87 | const struct nvkm_falcon_func_pio |
| 76 | 88 | gm200_flcn_dmem_pio = { |
| 77 | − .min = 4, | |
| 89 | + .min = 1, | |
| 78 | 90 | .max = 0x100, |
| 79 | 91 | .wr_init = gm200_flcn_pio_dmem_wr_init, |
| 80 | 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 | 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 | 85 | int |
| 69 | 86 | tu102_devinit_post(struct nvkm_devinit *base, bool post) |
| 70 | 87 | { |
| 71 | 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 | 95 | gm200_devinit_preos(init, post); |
| 73 | 96 | return 0; |
| 74 | 97 | } |
| @@ -32,6 +32,7 @@ nvkm-y += nvkm/subdev/fb/gp100.o · 31 unmodified lines | ||
| 32 | 32 | nvkm-y += nvkm/subdev/fb/gp102.o |
| 33 | 33 | nvkm-y += nvkm/subdev/fb/gp10b.o |
| 34 | 34 | nvkm-y += nvkm/subdev/fb/gv100.o |
| 35 | +nvkm-y += nvkm/subdev/fb/tu102.o | |
| 35 | 36 | nvkm-y += nvkm/subdev/fb/ga100.o |
| 36 | 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 | 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 | 43 | static const struct nvkm_fb_func |
| 50 | 44 | ga102_fb = { |
| 51 | 45 | .dtor = gf100_fb_dtor, |
| @@ -56,7 +50,7 @@ ga102_fb = { · 4 unmodified lines | ||
| 56 | 50 | .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, |
| 57 | 51 | .ram_new = ga102_ram_new, |
| 58 | 52 | .default_bigpage = 16, |
| 59 | − .vpr.scrub_required = ga102_fb_vpr_scrub_required, | |
| 53 | + .vpr.scrub_required = tu102_fb_vpr_scrub_required, | |
| 60 | 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 | 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 | 89 | int gp102_fb_vpr_scrub(struct nvkm_fb *); |
| 90 | 90 | |
| 91 | 91 | int gv100_fb_init_page(struct nvkm_fb *); |
| 92 | + | |
| 93 | +bool tu102_fb_vpr_scrub_required(struct nvkm_fb *); | |
| 92 | 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 | 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 | 229 | nvkm_falcon_start(falcon); |
| 230 | 230 | return 0; |
| 231 | 231 | } |
| @@ -1193,14 +1193,11 @@ static int boe_panel_enter_sleep_mode(struct boe_panel *boe) · 1192 unmodified lines | ||
| 1193 | 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 | 1198 | struct boe_panel *boe = to_boe_panel(panel); |
| 1199 | 1199 | int ret; |
| 1200 | 1200 | |
| 1201 | − if (!boe->prepared) | |
| 1202 | − return 0; | |
| 1203 | − | |
| 1204 | 1201 | ret = boe_panel_enter_sleep_mode(boe); |
| 1205 | 1202 | if (ret < 0) { |
| 1206 | 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 | 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 | 1219 | if (boe->desc->discharge_on_disable) { |
| 1213 | 1220 | regulator_disable(boe->avee); |
| 1214 | 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 | 1537 | static const struct drm_panel_funcs boe_panel_funcs = { |
| 1538 | + .disable = boe_panel_disable, | |
| 1531 | 1539 | .unprepare = boe_panel_unprepare, |
| 1532 | 1540 | .prepare = boe_panel_prepare, |
| 1533 | 1541 | .enable = boe_panel_enable, |
| @@ -656,18 +656,8 @@ static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = { · 655 unmodified lines | ||
| 656 | 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 | 659 | static const struct drm_crtc_funcs ssd130x_crtc_funcs = { |
| 670 | − .reset = ssd130x_crtc_reset, | |
| 660 | + .reset = drm_atomic_helper_crtc_reset, | |
| 671 | 661 | .destroy = drm_crtc_cleanup, |
| 672 | 662 | .set_config = drm_atomic_helper_set_config, |
| 673 | 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 | 676 | if (ret) |
| 687 | 677 | return; |
| 688 | 678 | |
| 679 | + ret = ssd130x_init(ssd130x); | |
| 680 | + if (ret) { | |
| 681 | + ssd130x_power_off(ssd130x); | |
| 682 | + return; | |
| 683 | + } | |
| 684 | + | |
| 689 | 685 | ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON); |
| 690 | 686 | |
| 691 | 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 | 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 | 3023 | CEC_CAP_DEFAULTS | |
| 3023 | 3024 | CEC_CAP_CONNECTOR_INFO, 1); |
| 3024 | 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 | 227 | cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]); |
| 228 | 228 | if (cl_data->num_hid_devices == 0) |
| 229 | 229 | return -ENODEV; |
| 230 | + cl_data->is_any_sensor_enabled = false; | |
| 230 | 231 | |
| 231 | 232 | INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); |
| 232 | 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 | 288 | status = amd_sfh_wait_for_response |
| 288 | 289 | (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); |
| 289 | 290 | if (status == SENSOR_ENABLED) { |
| 291 | + cl_data->is_any_sensor_enabled = true; | |
| 290 | 292 | cl_data->sensor_sts[i] = SENSOR_ENABLED; |
| 291 | 293 | rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); |
| 292 | 294 | if (rc) { |
| @@ -301,19 +303,26 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) · 8 unmodified lines | ||
| 301 | 303 | cl_data->sensor_sts[i]); |
| 302 | 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 | 313 | dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", |
| 306 | 314 | cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), |
| 307 | 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 | 319 | amd_sfh_hid_client_deinit(privdata); |
| 311 | 320 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 312 | 321 | devm_kfree(dev, cl_data->feature_report[i]); |
| 313 | 322 | devm_kfree(dev, in_data->input_report[i]); |
| 314 | 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 | 326 | return -EOPNOTSUPP; |
| 318 | 327 | } |
| 319 | 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 | 32 | struct amdtp_cl_data { |
| 33 | 33 | u8 init_done; |
| 34 | 34 | u32 cur_hid_dev; |
| 35 | + bool is_any_sensor_enabled; | |
| 35 | 36 | u32 hid_dev_count; |
| 36 | 37 | u32 num_hid_devices; |
| 37 | 38 | struct device_info *hid_devices; |
| @@ -1202,6 +1202,7 @@ int hid_open_report(struct hid_device *device) · 1201 unmodified lines | ||
| 1202 | 1202 | __u8 *end; |
| 1203 | 1203 | __u8 *next; |
| 1204 | 1204 | int ret; |
| 1205 | + int i; | |
| 1205 | 1206 | static int (*dispatch_type[])(struct hid_parser *parser, |
| 1206 | 1207 | struct hid_item *item) = { |
| 1207 | 1208 | hid_parser_main, |
| @@ -1252,6 +1253,8 @@ int hid_open_report(struct hid_device *device) · 44 unmodified lines | ||
| 1252 | 1253 | goto err; |
| 1253 | 1254 | } |
| 1254 | 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 | 1259 | ret = -EINVAL; |
| 1257 | 1260 | while ((next = fetch_item(start, end, &item)) != NULL) { |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> |
| 13 | 13 | * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com> |
| 14 | 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 | 90 | case USB_DEVICE_ID_ELECOM_M_DT1URBK: |
| 90 | 91 | case USB_DEVICE_ID_ELECOM_M_DT1DRBK: |
| 91 | 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 | 95 | * Report descriptor format: |
| 95 | 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 | 101 | mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); |
| 101 | 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 | 114 | return rdesc; |
| 104 | 115 | } |
| @@ -112,7 +123,8 @@ static const struct hid_device_id elecom_devices[] = { · 7 unmodified lines | ||
| 112 | 123 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, |
| 113 | 124 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, |
| 114 | 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 | 130 | MODULE_DEVICE_TABLE(hid, elecom_devices); |
| @@ -413,6 +413,8 @@ · 412 unmodified lines | ||
| 413 | 413 | #define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF |
| 414 | 414 | #define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9 |
| 415 | 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 | 418 | #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 |
| 417 | 419 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 |
| 418 | 420 | #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A |
| @@ -428,7 +430,8 @@ · 9 unmodified lines | ||
| 428 | 430 | #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe |
| 429 | 431 | #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff |
| 430 | 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 | 436 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 |
| 434 | 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 | 370 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 371 | 371 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), |
| 372 | 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 | 375 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), |
| 374 | 376 | HID_BATTERY_QUIRK_IGNORE }, |
| 375 | 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 | 386 | HID_BATTERY_QUIRK_IGNORE }, |
| 385 | 387 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), |
| 386 | 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 | 391 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), |
| 388 | 392 | HID_BATTERY_QUIRK_IGNORE }, |
| 389 | 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 | 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 | 3984 | /* forward current battery state */ |
| 3984 | 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 | 393 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, |
| 394 | 394 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, |
| 395 | 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 | 398 | #endif |
| 398 | 399 | #if IS_ENABLED(CONFIG_HID_ELO) |
| 399 | 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 | 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 | 1969 | #else |
| @@ -280,6 +280,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, · 279 unmodified lines | ||
| 280 | 280 | hid_sensor_convert_timestamp( |
| 281 | 281 | &accel_state->common_attributes, |
| 282 | 282 | *(int64_t *)raw_data); |
| 283 | + ret = 0; | |
| 283 | 284 | break; |
| 284 | 285 | default: |
| 285 | 286 | break; |
| @@ -298,8 +298,10 @@ static int berlin2_adc_probe(struct platform_device *pdev) · 297 unmodified lines | ||
| 298 | 298 | int ret; |
| 299 | 299 | |
| 300 | 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 | 303 | return -ENOMEM; |
| 304 | + } | |
| 303 | 305 | |
| 304 | 306 | priv = iio_priv(indio_dev); |
| 305 | 307 | |
| @@ -86,6 +86,8 @@ · 85 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | #define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100) |
| 88 | 88 | |
| 89 | +#define IMX8QXP_ADC_MAX_FIFO_SIZE 16 | |
| 90 | + | |
| 89 | 91 | struct imx8qxp_adc { |
| 90 | 92 | struct device *dev; |
| 91 | 93 | void __iomem *regs; |
| @@ -95,6 +97,7 @@ struct imx8qxp_adc { · 3 unmodified lines | ||
| 95 | 97 | /* Serialise ADC channel reads */ |
| 96 | 98 | struct mutex lock; |
| 97 | 99 | struct completion completion; |
| 100 | + u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE]; | |
| 98 | 101 | }; |
| 99 | 102 | |
| 100 | 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 | 241 | return ret; |
| 239 | 242 | } |
| 240 | 243 | |
| 241 | − *val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK, | |
| 242 | − readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO)); | |
| 244 | + *val = adc->fifo[0]; | |
| 243 | 245 | |
| 244 | 246 | mutex_unlock(&adc->lock); |
| 245 | 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 | 268 | struct imx8qxp_adc *adc = dev_id; |
| 267 | 269 | u32 fifo_count; |
| 270 | + int i; | |
| 268 | 271 | |
| 269 | 272 | fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK, |
| 270 | 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 | 279 | if (fifo_count) |
| 273 | 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 | 1525 | static int stm32_dfsdm_adc_probe(struct platform_device *pdev) |
| 1525 | 1526 | { |
| @@ -57,6 +57,18 @@ · 56 unmodified lines | ||
| 57 | 57 | #define TWL6030_GPADCS BIT(1) |
| 58 | 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 | 73 | * struct twl6030_chnl_calib - channel calibration |
| 62 | 74 | * @gain: slope coefficient for ideal curve |
| @@ -927,6 +939,26 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) · 864 unmodified lines | ||
| 927 | 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 | 962 | indio_dev->name = DRIVER_NAME; |
| 931 | 963 | indio_dev->info = &twl6030_gpadc_iio_info; |
| 932 | 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 | 1330 | dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL); |
| 1331 | 1331 | if (!dev_channels) |
| 1332 | − ret = -ENOMEM; | |
| 1332 | + return -ENOMEM; | |
| 1333 | 1333 | |
| 1334 | 1334 | indio_dev->channels = dev_channels; |
| 1335 | 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 | 231 | gyro_state->timestamp = |
| 232 | 232 | hid_sensor_convert_timestamp(&gyro_state->common_attributes, |
| 233 | 233 | *(s64 *)raw_data); |
| 234 | + ret = 0; | |
| 234 | 235 | break; |
| 235 | 236 | default: |
| 236 | 237 | break; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/regmap.h> |
| 11 | 11 | #include <linux/acpi.h> |
| 12 | 12 | #include <linux/bitops.h> |
| 13 | +#include <linux/bitfield.h> | |
| 13 | 14 | |
| 14 | 15 | #include <linux/iio/iio.h> |
| 15 | 16 | #include <linux/iio/sysfs.h> |
| @@ -144,9 +145,8 @@ · 128 unmodified lines | ||
| 144 | 145 | #define FXOS8700_NVM_DATA_BNK0 0xa7 |
| 145 | 146 | |
| 146 | 147 | /* Bit definitions for FXOS8700_CTRL_REG1 */ |
| 147 | −#define FXOS8700_CTRL_ODR_MSK 0x38 | |
| 148 | 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 | 151 | /* Bit definitions for FXOS8700_M_CTRL_REG1 */ |
| 152 | 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 | 320 | switch (iio_type) { |
| 321 | 321 | case IIO_ACCEL: |
| 322 | 322 | return FXOS8700_ACCEL; |
| 323 | − case IIO_ANGL_VEL: | |
| 323 | + case IIO_MAGN: | |
| 324 | 324 | return FXOS8700_MAGN; |
| 325 | 325 | default: |
| 326 | 326 | return -EINVAL; |
| @@ -345,15 +345,35 @@ static int fxos8700_set_active_mode(struct fxos8700_data *data, · 18 unmodified lines | ||
| 345 | 345 | static int fxos8700_set_scale(struct fxos8700_data *data, |
| 346 | 346 | enum fxos8700_sensor t, int uscale) |
| 347 | 347 | { |
| 348 | − int i; | |
| 348 | + int i, ret, val; | |
| 349 | + bool active_mode; | |
| 349 | 350 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); |
| 350 | 351 | struct device *dev = regmap_get_device(data->regmap); |
| 351 | 352 | |
| 352 | 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 | 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 | 377 | for (i = 0; i < scale_num; i++) |
| 358 | 378 | if (fxos8700_accel_scale[i].uscale == uscale) |
| 359 | 379 | break; |
| @@ -361,8 +381,12 @@ static int fxos8700_set_scale(struct fxos8700_data *data, · 1 unmodified line | ||
| 361 | 381 | if (i == scale_num) |
| 362 | 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 | 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 | 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 | 396 | static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale); |
| 373 | 397 | |
| 374 | 398 | if (t == FXOS8700_MAGN) { |
| 375 | − *uscale = 1200; /* Magnetometer is locked at 1200uT */ | |
| 399 | + *uscale = 1000; /* Magnetometer is locked at 0.001Gs */ | |
| 376 | 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 | 418 | int axis, int *val) |
| 395 | 419 | { |
| 396 | 420 | u8 base, reg; |
| 421 | + s16 tmp; | |
| 397 | 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 | 440 | /* Block read 6 bytes of device output registers to avoid data loss */ |
| 403 | 441 | ret = regmap_bulk_read(data->regmap, base, data->buf, |
| 404 | − FXOS8700_DATA_BUF_SIZE); | |
| 442 | + sizeof(data->buf)); | |
| 405 | 443 | if (ret) |
| 406 | 444 | return ret; |
| 407 | 445 | |
| 408 | 446 | /* Convert axis to buffer index */ |
| 409 | 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 | 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 | 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 | 508 | if (i >= odr_num) |
| 446 | 509 | return -EINVAL; |
| 447 | 510 | |
| 448 | − return regmap_update_bits(data->regmap, | |
| 449 | − FXOS8700_CTRL_REG1, | |
| 450 | − FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE, | |
| 451 | − fxos8700_odr[i].bits << 3 | active_mode); | |
| 511 | + val &= ~FXOS8700_CTRL_ODR_MSK; | |
| 512 | + val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE; | |
| 513 | + return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val); | |
| 452 | 514 | } |
| 453 | 515 | |
| 454 | 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 | 523 | if (ret) |
| 462 | 524 | return ret; |
| 463 | 525 | |
| 464 | − val &= FXOS8700_CTRL_ODR_MSK; | |
| 526 | + val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val); | |
| 465 | 527 | |
| 466 | 528 | for (i = 0; i < odr_num; i++) |
| 467 | 529 | if (val == fxos8700_odr[i].bits) |
| @@ -526,7 +588,7 @@ static IIO_CONST_ATTR(in_accel_sampling_frequency_available, · 58 unmodified lines | ||
| 526 | 588 | static IIO_CONST_ATTR(in_magn_sampling_frequency_available, |
| 527 | 589 | "1.5625 6.25 12.5 50 100 200 400 800"); |
| 528 | 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 | 593 | static struct attribute *fxos8700_attrs[] = { |
| 532 | 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 | 654 | if (ret) |
| 593 | 655 | return ret; |
| 594 | 656 | |
| 595 | − /* Max ODR (800Hz individual or 400Hz hybrid), active mode */ | |
| 596 | − ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, | |
| 597 | − FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE); | |
| 657 | + /* | |
| 658 | + * Set max full-scale range (+/-8G) for ACCEL sensor in chip | |
| 659 | + * initialization then activate the device. | |
| 660 | + */ | |
| 661 | + ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G); | |
| 598 | 662 | if (ret) |
| 599 | 663 | return ret; |
| 600 | 664 | |
| 601 | − /* Set for max full-scale range (+/-8G) */ | |
| 602 | − return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G); | |
| 665 | + /* Max ODR (800Hz individual or 400Hz hybrid), active mode */ | |
| 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 | 672 | static void fxos8700_chip_uninit(void *data) |
| @@ -4,6 +4,7 @@ config IIO_ST_LSM6DSX · 3 unmodified lines | ||
| 4 | 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" |
| 5 | 5 | depends on (I2C || SPI || I3C) |
| 6 | 6 | select IIO_BUFFER |
| 7 | + select IIO_TRIGGERED_BUFFER | |
| 7 | 8 | select IIO_KFIFO_BUF |
| 8 | 9 | select IIO_ST_LSM6DSX_I2C if (I2C) |
| 9 | 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 | 440 | if (!indio_dev) |
| 441 | 441 | return -ENOMEM; |
| 442 | 442 | |
| 443 | + i2c_set_clientdata(client, indio_dev); | |
| 444 | + | |
| 443 | 445 | /* |
| 444 | 446 | * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the |
| 445 | 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 | 462 | return PTR_ERR(client); |
| 461 | 463 | } |
| 462 | 464 | |
| 463 | − i2c_set_clientdata(client, indio_dev); | |
| 464 | − | |
| 465 | 465 | cm32181 = iio_priv(indio_dev); |
| 466 | 466 | cm32181->client = client; |
| 467 | 467 | cm32181->dev = dev; |
| @@ -490,7 +490,8 @@ static int cm32181_probe(struct i2c_client *client) · 22 unmodified lines | ||
| 490 | 490 | |
| 491 | 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 | 496 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, |
| 496 | 497 | CM32181_CMD_ALS_DISABLE); |
| @@ -498,8 +499,8 @@ static int cm32181_suspend(struct device *dev) · 1 unmodified line | ||
| 498 | 499 | |
| 499 | 500 | static int cm32181_resume(struct device *dev) |
| 500 | 501 | { |
| 501 | − struct i2c_client *client = to_i2c_client(dev); | |
| 502 | 502 | struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev)); |
| 503 | + struct i2c_client *client = cm32181->client; | |
| 503 | 504 | |
| 504 | 505 | return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD, |
| 505 | 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 | 77 | d = debugfs_rename(bonding_debug_root, bond->debug_dir, |
| 78 | 78 | bonding_debug_root, bond->dev->name); |
| 79 | − if (d) { | |
| 79 | + if (!IS_ERR(d)) { | |
| 80 | 80 | bond->debug_dir = d; |
| 81 | 81 | } else { |
| 82 | 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 | 1302 | if (!priv->ports[port].pvid) |
| 1303 | 1303 | mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK, |
| 1304 | 1304 | MT7530_VLAN_ACC_TAGGED); |
| 1305 | − } | |
| 1306 | 1305 | |
| 1307 | − /* Set the port as a user port which is to be able to recognize VID | |
| 1308 | − * from incoming packets before fetching entry within the VLAN table. | |
| 1309 | − */ | |
| 1310 | − mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, | |
| 1311 | − VLAN_ATTR(MT7530_VLAN_USER) | | |
| 1312 | − PVC_EG_TAG(MT7530_VLAN_EG_DISABLED)); | |
| 1306 | + /* Set the port as a user port which is to be able to recognize | |
| 1307 | + * VID from incoming packets before fetching entry within the | |
| 1308 | + * VLAN table. | |
| 1309 | + */ | |
| 1310 | + mt7530_rmw(priv, MT7530_PVC_P(port), | |
| 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 | 1327 | static void |
| @@ -4684,25 +4684,26 @@ static int init_reset_optional(struct platform_device *pdev) · 4683 unmodified lines | ||
| 4684 | 4684 | if (ret) |
| 4685 | 4685 | return dev_err_probe(&pdev->dev, ret, |
| 4686 | 4686 | "failed to init SGMII PHY\n"); |
| 4687 | − } | |
| 4688 | 4687 | |
| 4689 | − ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_GEM_CONFIG); | |
| 4690 | − if (!ret) { | |
| 4691 | − u32 pm_info[2]; | |
| 4688 | + ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_GEM_CONFIG); | |
| 4689 | + if (!ret) { | |
| 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", | |
| 4694 | − pm_info, ARRAY_SIZE(pm_info)); | |
| 4695 | − if (ret) { | |
| 4696 | − dev_err(&pdev->dev, "Failed to read power management information\n"); | |
| 4697 | − goto err_out_phy_exit; | |
| 4702 | + ret = zynqmp_pm_set_gem_config(pm_info[1], GEM_CONFIG_SGMII_MODE, 1); | |
| 4703 | + if (ret) | |
| 4704 | + 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 | 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 | 5534 | * returned by the firmware is a 16 bit * value, but is indexed |
| 5535 | 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 | 5538 | SPEED_10, /* BIT(0) */ |
| 5539 | 5539 | SPEED_100, |
| 5540 | 5540 | SPEED_1000, |
| @@ -5546,10 +5546,6 @@ static const u32 ice_aq_to_link_speed[15] = { · 5 unmodified lines | ||
| 5546 | 5546 | SPEED_40000, |
| 5547 | 5547 | SPEED_50000, |
| 5548 | 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 | 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 | 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 | 5724 | pr_info("%s\n", ice_driver_string); |
| 5725 | 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 | 5728 | if (!ice_wq) { |
| 5729 | 5729 | pr_err("Failed to create workqueue\n"); |
| 5730 | 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 | 5421 | status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw)); |
| 5422 | 5422 | if (status) |
| 5423 | − goto err_free_lkup_exts; | |
| 5423 | + goto err_unroll; | |
| 5424 | 5424 | |
| 5425 | 5425 | /* Group match words into recipes using preferred recipe grouping |
| 5426 | 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 | 1688 | struct ice_vsi *ch_vsi = NULL; |
| 1689 | 1689 | u16 queue = act->rx_queue; |
| 1690 | 1690 | |
| 1691 | − if (queue > vsi->num_rxq) { | |
| 1691 | + if (queue >= vsi->num_rxq) { | |
| 1692 | 1692 | NL_SET_ERR_MSG_MOD(fltr->extack, |
| 1693 | 1693 | "Unable to add filter because specified queue is invalid"); |
| 1694 | 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 | 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 | 43 | VIRTCHNL_LINK_SPEED_100MB, /* BIT(0) */ |
| 44 | 44 | VIRTCHNL_LINK_SPEED_100MB, |
| 45 | 45 | VIRTCHNL_LINK_SPEED_1GB, |
| @@ -51,10 +51,6 @@ static const u32 ice_legacy_aq_to_vc_speed[15] = { · 5 unmodified lines | ||
| 51 | 51 | VIRTCHNL_LINK_SPEED_40GB, |
| 52 | 52 | VIRTCHNL_LINK_SPEED_40GB, |
| 53 | 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 | 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) { | |
| 77 | − /* convert a BIT() value into an array index */ | |
| 78 | − speed = ice_get_link_speed(fls(link_speed) - 1); | |
| 79 | − } else { | |
| 73 | + if (adv_link_support) | |
| 74 | + return ice_get_link_speed(index); | |
| 75 | + else if (index < ARRAY_SIZE(ice_legacy_aq_to_vc_speed)) | |
| 80 | 76 | /* Virtchnl speeds are not defined for every speed supported in |
| 81 | 77 | * the hardware. To maintain compatibility with older AVF |
| 82 | 78 | * drivers, while reporting the speed the new speed values are |
| 83 | 79 | * resolved to the closest known virtchnl speeds |
| 84 | 80 | */ |
| 85 | − speed = ice_legacy_aq_to_vc_speed[fls(link_speed) - 1]; | |
| 86 | − } | |
| 81 | + return ice_legacy_aq_to_vc_speed[index]; | |
| 87 | 82 | |
| 88 | − return speed; | |
| 83 | + return VIRTCHNL_LINK_SPEED_UNKNOWN; | |
| 89 | 84 | } |
| 90 | 85 | |
| 91 | 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 | 45 | /* outer VLAN ops regardless of port VLAN config */ |
| 46 | 46 | vlan_ops->add_vlan = ice_vsi_add_vlan; |
| 47 | − vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering; | |
| 48 | 47 | vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; |
| 49 | 48 | vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; |
| 50 | 49 | |
| 51 | 50 | if (ice_vf_is_port_vlan_ena(vf)) { |
| 52 | 51 | /* setup outer VLAN ops */ |
| 53 | 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 | 58 | vlan_ops->ena_rx_filtering = |
| 55 | 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 | 67 | vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; |
| 64 | 68 | vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; |
| 65 | 69 | } else { |
| 70 | + vlan_ops->dis_rx_filtering = | |
| 71 | + ice_vsi_dis_rx_vlan_filtering; | |
| 72 | + | |
| 66 | 73 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) |
| 67 | 74 | vlan_ops->ena_rx_filtering = noop_vlan; |
| 68 | 75 | else |
| @@ -96,7 +103,14 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) · 27 unmodified lines | ||
| 96 | 103 | vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan; |
| 97 | 104 | vlan_ops->ena_rx_filtering = |
| 98 | 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 | 111 | } else { |
| 112 | + vlan_ops->dis_rx_filtering = | |
| 113 | + ice_vsi_dis_rx_vlan_filtering; | |
| 100 | 114 | if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) |
| 101 | 115 | vlan_ops->ena_rx_filtering = noop_vlan; |
| 102 | 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 | 2942 | if (tx_buffer->next_to_watch && |
| 2943 | 2943 | time_after(jiffies, tx_buffer->time_stamp + |
| 2944 | 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 | 2948 | /* detected Tx unit hang */ |
| 2947 | 2949 | netdev_err(tx_ring->netdev, |
| 2948 | 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 | 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 | 5092 | * igc_get_stats64 - Get System Network Statistics |
| 5073 | 5093 | * @netdev: network interface device structure |
| @@ -5495,7 +5515,7 @@ static void igc_watchdog_task(struct work_struct *work) · 421 unmodified lines | ||
| 5495 | 5515 | case SPEED_100: |
| 5496 | 5516 | case SPEED_1000: |
| 5497 | 5517 | case SPEED_2500: |
| 5498 | − adapter->tx_timeout_factor = 7; | |
| 5518 | + adapter->tx_timeout_factor = 1; | |
| 5499 | 5519 | break; |
| 5500 | 5520 | } |
| 5501 | 5521 | |
| @@ -6347,6 +6367,7 @@ static const struct net_device_ops igc_netdev_ops = { · 845 unmodified lines | ||
| 6347 | 6367 | .ndo_set_rx_mode = igc_set_rx_mode, |
| 6348 | 6368 | .ndo_set_mac_address = igc_set_mac, |
| 6349 | 6369 | .ndo_change_mtu = igc_change_mtu, |
| 6370 | + .ndo_tx_timeout = igc_tx_timeout, | |
| 6350 | 6371 | .ndo_get_stats64 = igc_get_stats64, |
| 6351 | 6372 | .ndo_fix_features = igc_fix_features, |
| 6352 | 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 | 1621 | if (IS_ERR(pp)) |
| 1622 | 1622 | return pp; |
| 1623 | 1623 | |
| 1624 | − err = __xdp_rxq_info_reg(xdp_q, ð->dummy_dev, eth->rx_napi.napi_id, | |
| 1625 | − id, PAGE_SIZE); | |
| 1624 | + err = __xdp_rxq_info_reg(xdp_q, ð->dummy_dev, id, | |
| 1625 | + eth->rx_napi.napi_id, PAGE_SIZE); | |
| 1626 | 1626 | if (err < 0) |
| 1627 | 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 | 1922 | while (done < budget) { |
| 1923 | 1923 | unsigned int pktlen, *rxdcsum; |
| 1924 | + bool has_hwaccel_tag = false; | |
| 1924 | 1925 | struct net_device *netdev; |
| 1926 | + u16 vlan_proto, vlan_tci; | |
| 1925 | 1927 | dma_addr_t dma_addr; |
| 1926 | 1928 | u32 hash, reason; |
| 1927 | 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 | 2064 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { |
| 2063 | 2065 | if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { |
| 2064 | − if (trxd.rxd3 & RX_DMA_VTAG_V2) | |
| 2065 | − __vlan_hwaccel_put_tag(skb, | |
| 2066 | − htons(RX_DMA_VPID(trxd.rxd4)), | |
| 2067 | − RX_DMA_VID(trxd.rxd4)); | |
| 2066 | + if (trxd.rxd3 & RX_DMA_VTAG_V2) { | |
| 2067 | + vlan_proto = RX_DMA_VPID(trxd.rxd4); | |
| 2068 | + vlan_tci = RX_DMA_VID(trxd.rxd4); | |
| 2069 | + has_hwaccel_tag = true; | |
| 2070 | + } | |
| 2068 | 2071 | } else if (trxd.rxd2 & RX_DMA_VTAG) { |
| 2069 | − __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), | |
| 2070 | − RX_DMA_VID(trxd.rxd3)); | |
| 2072 | + vlan_proto = RX_DMA_VPID(trxd.rxd3); | |
| 2073 | + vlan_tci = RX_DMA_VID(trxd.rxd3); | |
| 2074 | + has_hwaccel_tag = true; | |
| 2071 | 2075 | } |
| 2072 | 2076 | } |
| 2073 | 2077 | |
| 2074 | 2078 | /* When using VLAN untagging in combination with DSA, the |
| 2075 | 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)) { | |
| 2078 | − unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); | |
| 2081 | + if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { | |
| 2082 | + unsigned int port = vlan_proto & GENMASK(2, 0); | |
| 2079 | 2083 | |
| 2080 | 2084 | if (port < ARRAY_SIZE(eth->dsa_meta) && |
| 2081 | 2085 | eth->dsa_meta[port]) |
| 2082 | 2086 | skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); |
| 2083 | − | |
| 2084 | − __vlan_hwaccel_clear_tag(skb); | |
| 2087 | + } else if (has_hwaccel_tag) { | |
| 2088 | + __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); | |
| 2085 | 2089 | } |
| 2086 | 2090 | |
| 2087 | 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 | 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 | 3185 | val |= MTK_GDMA_SPECIAL_TAG; |
| 3182 | 3186 | |
| 3183 | 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 | 3247 | struct mtk_eth *eth = mac->hw; |
| 3244 | 3248 | int i, err; |
| 3245 | 3249 | |
| 3246 | − if ((mtk_uses_dsa(dev) && !eth->prog) && | |
| 3247 | − !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { | |
| 3250 | + if (mtk_uses_dsa(dev) && !eth->prog) { | |
| 3248 | 3251 | for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { |
| 3249 | 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 | 3265 | } else { |
| 3263 | 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 | |
| 3265 | − * MT7623 SoCs is being used. | |
| 3267 | + * one MAC does not use DSA. | |
| 3266 | 3268 | */ |
| 3267 | 3269 | u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); |
| 3268 | 3270 | val &= ~MTK_CDMP_STAG_EN; |
| @@ -245,8 +245,9 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev) · 244 unmodified lines | ||
| 245 | 245 | pages = dev->priv.dbg.pages_debugfs; |
| 246 | 246 | |
| 247 | 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); | |
| 249 | − debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.host_pf_pages); | |
| 248 | + debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]); | |
| 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 | 251 | debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); |
| 251 | 252 | debugfs_create_u32("fw_pages_give_dropped", 0400, pages, &dev->priv.give_pages_dropped); |
| 252 | 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 | 64 | MLX5_GET(mtrc_cap, out, num_string_trace); |
| 65 | 65 | tracer->str_db.num_string_db = MLX5_GET(mtrc_cap, out, num_string_db); |
| 66 | 66 | tracer->owner = !!MLX5_GET(mtrc_cap, out, trace_owner); |
| 67 | + tracer->str_db.loaded = false; | |
| 67 | 68 | |
| 68 | 69 | for (i = 0; i < tracer->str_db.num_string_db; i++) { |
| 69 | 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 | 784 | if (err) |
| 784 | 785 | mlx5_core_warn(dev, "FWTracer: Failed to set tracer configurations %d\n", err); |
| 785 | 786 | |
| 787 | + tracer->buff.consumer_index = 0; | |
| 786 | 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 | 849 | mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); |
| 848 | 850 | if (tracer->owner) { |
| 849 | 851 | tracer->owner = false; |
| 850 | − tracer->buff.consumer_index = 0; | |
| 851 | 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 | 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 | 99 | if (err) |
| 100 | 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 | 439 | switch (event) { |
| 440 | 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 | 441 | fdb_info = container_of(info, |
| 446 | 442 | struct switchdev_notifier_fdb_info, |
| 447 | 443 | info); |
| @@ -450,7 +450,7 @@ void mlx5e_enable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc) · 449 unmodified lines | ||
| 450 | 450 | |
| 451 | 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 | 454 | return; |
| 455 | 455 | |
| 456 | 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 | 597 | rq->ix = c->ix; |
| 598 | 598 | rq->channel = c; |
| 599 | 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 | 602 | rq->xdpsq = &c->rq_xdpsq; |
| 602 | 603 | rq->stats = &c->priv->channel_stats[c->ix]->rq; |
| 603 | 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 | 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 | 1024 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) |
| 1053 | 1025 | { |
| 1054 | 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 | 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 | 3303 | static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd) |
| 3346 | 3304 | { |
| 3347 | 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 | 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 | 3886 | static int set_feature_rx_fcs(struct net_device *netdev, bool enable) |
| 3921 | 3887 | { |
| 3922 | 3888 | struct mlx5e_priv *priv = netdev_priv(netdev); |
| 3923 | 3889 | struct mlx5e_channels *chs = &priv->channels; |
| 3924 | − struct mlx5_core_dev *mdev = priv->mdev; | |
| 3890 | + struct mlx5e_params new_params; | |
| 3925 | 3891 | int err; |
| 3926 | 3892 | |
| 3927 | 3893 | mutex_lock(&priv->state_lock); |
| 3928 | 3894 | |
| 3929 | − if (enable) { | |
| 3930 | − err = mlx5e_set_rx_port_ts(mdev, false); | |
| 3931 | − if (err) | |
| 3932 | − goto out; | |
| 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: | |
| 3895 | + new_params = chs->params; | |
| 3896 | + new_params.scatter_fcs_en = enable; | |
| 3897 | + err = mlx5e_safe_switch_params(priv, &new_params, mlx5e_set_rx_port_ts_wrap, | |
| 3898 | + &new_params.scatter_fcs_en, true); | |
| 3955 | 3899 | mutex_unlock(&priv->state_lock); |
| 3956 | 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 | 4032 | if (netdev->features & NETIF_F_GRO_HW) |
| 4089 | 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 | 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 | 1715 | struct mlx5_esw_bridge *bridge; |
| 1716 | 1716 | |
| 1717 | 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 | 1719 | return; |
| 1720 | 1720 | |
| 1721 | 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 | 196 | int rate, width; |
| 197 | 197 | |
| 198 | 198 | rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper); |
| 199 | 199 | if (rate < 0) |
| 200 | − return -EINVAL; | |
| 200 | + return SPEED_UNKNOWN; | |
| 201 | 201 | width = mlx5_ptys_width_enum_to_int(ib_link_width_oper); |
| 202 | 202 | if (width < 0) |
| 203 | − return -EINVAL; | |
| 203 | + return SPEED_UNKNOWN; | |
| 204 | 204 | |
| 205 | 205 | return rate * width; |
| 206 | 206 | } |
| @@ -223,16 +223,13 @@ static int mlx5i_get_link_ksettings(struct net_device *netdev, · 16 unmodified lines | ||
| 223 | 223 | ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); |
| 224 | 224 | |
| 225 | 225 | speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper); |
| 226 | − if (speed < 0) | |
| 227 | − return -EINVAL; | |
| 226 | + link_ksettings->base.speed = speed; | |
| 227 | + link_ksettings->base.duplex = speed == SPEED_UNKNOWN ? DUPLEX_UNKNOWN : DUPLEX_FULL; | |
| 228 | 228 | |
| 229 | − link_ksettings->base.duplex = DUPLEX_FULL; | |
| 230 | 229 | link_ksettings->base.port = PORT_OTHER; |
| 231 | 230 | |
| 232 | 231 | link_ksettings->base.autoneg = AUTONEG_DISABLE; |
| 233 | 232 | |
| 234 | − link_ksettings->base.speed = speed; | |
| 235 | − | |
| 236 | 233 | return 0; |
| 237 | 234 | } |
| 238 | 235 | |
| @@ -2131,7 +2131,7 @@ static int __init mlx5_init(void) · 2130 unmodified lines | ||
| 2131 | 2131 | mlx5_core_verify_params(); |
| 2132 | 2132 | mlx5_register_debugfs(); |
| 2133 | 2133 | |
| 2134 | − err = pci_register_driver(&mlx5_core_driver); | |
| 2134 | + err = mlx5e_init(); | |
| 2135 | 2135 | if (err) |
| 2136 | 2136 | goto err_debug; |
| 2137 | 2137 | |
| @@ -2139,16 +2139,16 @@ static int __init mlx5_init(void) · 1 unmodified line | ||
| 2139 | 2139 | if (err) |
| 2140 | 2140 | goto err_sf; |
| 2141 | 2141 | |
| 2142 | − err = mlx5e_init(); | |
| 2142 | + err = pci_register_driver(&mlx5_core_driver); | |
| 2143 | 2143 | if (err) |
| 2144 | − goto err_en; | |
| 2144 | + goto err_pci; | |
| 2145 | 2145 | |
| 2146 | 2146 | return 0; |
| 2147 | 2147 | |
| 2148 | −err_en: | |
| 2148 | +err_pci: | |
| 2149 | 2149 | mlx5_sf_driver_unregister(); |
| 2150 | 2150 | err_sf: |
| 2151 | − pci_unregister_driver(&mlx5_core_driver); | |
| 2151 | + mlx5e_cleanup(); | |
| 2152 | 2152 | err_debug: |
| 2153 | 2153 | mlx5_unregister_debugfs(); |
| 2154 | 2154 | return err; |
| @@ -2156,9 +2156,9 @@ err_debug: · 1 unmodified line | ||
| 2156 | 2156 | |
| 2157 | 2157 | static void __exit mlx5_cleanup(void) |
| 2158 | 2158 | { |
| 2159 | − mlx5e_cleanup(); | |
| 2160 | − mlx5_sf_driver_unregister(); | |
| 2161 | 2159 | pci_unregister_driver(&mlx5_core_driver); |
| 2160 | + mlx5_sf_driver_unregister(); | |
| 2161 | + mlx5e_cleanup(); | |
| 2162 | 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 | 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 | 85 | static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function) |
| 78 | 86 | { |
| 79 | 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 | 341 | u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0}; |
| 334 | 342 | int inlen = MLX5_ST_SZ_BYTES(manage_pages_in); |
| 335 | 343 | int notify_fail = event; |
| 344 | + u16 func_type; | |
| 336 | 345 | u64 addr; |
| 337 | 346 | int err; |
| 338 | 347 | u32 *in; |
| @@ -384,11 +393,9 @@ retry: · 45 unmodified lines | ||
| 384 | 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 | 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 | 400 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n", |
| 394 | 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 | 422 | struct rb_root *root; |
| 416 | 423 | struct rb_node *p; |
| 417 | 424 | int npages = 0; |
| 425 | + u16 func_type; | |
| 418 | 426 | |
| 419 | 427 | root = xa_load(&dev->priv.page_root_xa, function); |
| 420 | 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 | 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 | 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 | 444 | mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x\n", |
| 439 | 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 | 505 | int outlen = MLX5_ST_SZ_BYTES(manage_pages_out); |
| 500 | 506 | u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {}; |
| 501 | 507 | int num_claimed; |
| 508 | + u16 func_type; | |
| 502 | 509 | u32 *out; |
| 503 | 510 | int err; |
| 504 | 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 | 557 | if (nclaimed) |
| 551 | 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 | 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 | 564 | out_free: |
| 560 | 565 | kvfree(out); |
| @@ -707,12 +712,12 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) · 146 unmodified lines | ||
| 707 | 712 | WARN(dev->priv.fw_pages, |
| 708 | 713 | "FW pages counter is %d after reclaiming all pages\n", |
| 709 | 714 | dev->priv.fw_pages); |
| 710 | − WARN(dev->priv.vfs_pages, | |
| 715 | + WARN(dev->priv.page_counters[MLX5_VF], | |
| 711 | 716 | "VFs FW pages counter is %d after reclaiming all pages\n", |
| 712 | − dev->priv.vfs_pages); | |
| 713 | − WARN(dev->priv.host_pf_pages, | |
| 717 | + dev->priv.page_counters[MLX5_VF]); | |
| 718 | + WARN(dev->priv.page_counters[MLX5_HOST_PF], | |
| 714 | 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 | 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 | 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 | 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 | 1138 | rule->flow_source)) |
| 1139 | 1139 | return 0; |
| 1140 | 1140 | |
| 1141 | + mlx5dr_domain_nic_lock(nic_dmn); | |
| 1142 | + | |
| 1141 | 1143 | ret = mlx5dr_matcher_select_builders(matcher, |
| 1142 | 1144 | nic_matcher, |
| 1143 | 1145 | dr_rule_get_ipv(¶m->outer), |
| 1144 | 1146 | dr_rule_get_ipv(¶m->inner)); |
| 1145 | 1147 | if (ret) |
| 1146 | − return ret; | |
| 1148 | + goto err_unlock; | |
| 1147 | 1149 | |
| 1148 | 1150 | hw_ste_arr_is_opt = nic_matcher->num_of_builders <= DR_RULE_MAX_STES_OPTIMIZED; |
| 1149 | 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 | 1154 | hw_ste_arr = kzalloc((nic_matcher->num_of_builders + DR_ACTION_MAX_STES) * |
| 1153 | 1155 | DR_STE_SIZE, GFP_KERNEL); |
| 1154 | 1156 | |
| 1155 | − if (!hw_ste_arr) | |
| 1156 | − return -ENOMEM; | |
| 1157 | + if (!hw_ste_arr) { | |
| 1158 | + ret = -ENOMEM; | |
| 1159 | + goto err_unlock; | |
| 1160 | + } | |
| 1157 | 1161 | } |
| 1158 | 1162 | |
| 1159 | − mlx5dr_domain_nic_lock(nic_dmn); | |
| 1160 | − | |
| 1161 | 1163 | ret = mlx5dr_matcher_add_to_tbl_nic(dmn, nic_matcher); |
| 1162 | 1164 | if (ret) |
| 1163 | 1165 | goto free_hw_ste; |
| @@ -1223,7 +1225,10 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule, · 59 unmodified lines | ||
| 1223 | 1225 | |
| 1224 | 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 | 1233 | free_rule: |
| 1229 | 1234 | dr_rule_clean_rule_members(rule, nic_rule); |
| @@ -1238,12 +1243,12 @@ remove_from_nic_tbl: · 8 unmodified lines | ||
| 1238 | 1243 | mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher); |
| 1239 | 1244 | |
| 1240 | 1245 | free_hw_ste: |
| 1241 | − mlx5dr_domain_nic_unlock(nic_dmn); | |
| 1242 | − | |
| 1243 | −out: | |
| 1244 | − if (unlikely(!hw_ste_arr_is_opt)) | |
| 1246 | + if (!hw_ste_arr_is_opt) | |
| 1245 | 1247 | kfree(hw_ste_arr); |
| 1246 | 1248 | |
| 1249 | +err_unlock: | |
| 1250 | + mlx5dr_domain_nic_unlock(nic_dmn); | |
| 1251 | + | |
| 1247 | 1252 | return ret; |
| 1248 | 1253 | } |
| 1249 | 1254 | |
| @@ -632,7 +632,7 @@ int sparx5_ptp_init(struct sparx5 *sparx5) · 631 unmodified lines | ||
| 632 | 632 | /* Enable master counters */ |
| 633 | 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 | 636 | port = sparx5->ports[i]; |
| 637 | 637 | if (!port) |
| 638 | 638 | continue; |
| @@ -648,7 +648,7 @@ void sparx5_ptp_deinit(struct sparx5 *sparx5) · 9 unmodified lines | ||
| 648 | 648 | struct sparx5_port *port; |
| 649 | 649 | int i; |
| 650 | 650 | |
| 651 | − for (i = 0; i < sparx5->port_count; i++) { | |
| 651 | + for (i = 0; i < SPX5_PORTS; i++) { | |
| 652 | 652 | port = sparx5->ports[i]; |
| 653 | 653 | if (!port) |
| 654 | 654 | continue; |
| @@ -1217,9 +1217,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 1216 unmodified lines | ||
| 1217 | 1217 | unsigned int max_queues_per_port = num_online_cpus(); |
| 1218 | 1218 | struct gdma_context *gc = pci_get_drvdata(pdev); |
| 1219 | 1219 | struct gdma_irq_context *gic; |
| 1220 | − unsigned int max_irqs; | |
| 1221 | − u16 *cpus; | |
| 1222 | − cpumask_var_t req_mask; | |
| 1220 | + unsigned int max_irqs, cpu; | |
| 1223 | 1221 | int nvec, irq; |
| 1224 | 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 | 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 | 1241 | for (i = 0; i < nvec; i++) { |
| 1257 | − cpumask_set_cpu(cpus[i], req_mask); | |
| 1258 | 1242 | gic = &gc->irq_contexts[i]; |
| 1259 | 1243 | gic->handler = NULL; |
| 1260 | 1244 | gic->arg = NULL; |
| @@ -1269,17 +1253,16 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 8 unmodified lines | ||
| 1269 | 1253 | irq = pci_irq_vector(pdev, i); |
| 1270 | 1254 | if (irq < 0) { |
| 1271 | 1255 | err = irq; |
| 1272 | − goto free_mask; | |
| 1256 | + goto free_irq; | |
| 1273 | 1257 | } |
| 1274 | 1258 | |
| 1275 | 1259 | err = request_irq(irq, mana_gd_intr, 0, gic->name, gic); |
| 1276 | 1260 | if (err) |
| 1277 | − goto free_mask; | |
| 1278 | − irq_set_affinity_and_hint(irq, req_mask); | |
| 1279 | − cpumask_clear(req_mask); | |
| 1261 | + goto free_irq; | |
| 1262 | + | |
| 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 | 1267 | err = mana_gd_alloc_res_map(nvec, &gc->msix_resource); |
| 1285 | 1268 | if (err) |
| @@ -1290,13 +1273,12 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) · 4 unmodified lines | ||
| 1290 | 1273 | |
| 1291 | 1274 | return 0; |
| 1292 | 1275 | |
| 1293 | −free_mask: | |
| 1294 | − free_cpumask_var(req_mask); | |
| 1295 | − kfree(cpus); | |
| 1296 | 1276 | free_irq: |
| 1297 | 1277 | for (j = i - 1; j >= 0; j--) { |
| 1298 | 1278 | irq = pci_irq_vector(pdev, j); |
| 1299 | 1279 | gic = &gc->irq_contexts[j]; |
| 1280 | + | |
| 1281 | + irq_update_affinity_hint(irq, NULL); | |
| 1300 | 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 | 1306 | continue; |
| 1325 | 1307 | |
| 1326 | 1308 | gic = &gc->irq_contexts[i]; |
| 1309 | + | |
| 1310 | + /* Need to clear the hint before free_irq */ | |
| 1311 | + irq_update_affinity_hint(irq, NULL); | |
| 1327 | 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 | 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 | 620 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { |
| 609 | 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 | 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 | 752 | finished_key_parsing: |
| 753 | 753 | if (match_protocol && proto != ETH_P_ALL) { |
| 754 | 754 | if (filter->block_id == VCAP_ES0) { |
| @@ -335,8 +335,8 @@ static void · 334 unmodified lines | ||
| 335 | 335 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 336 | 336 | { |
| 337 | 337 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 338 | − trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 339 | − trap->key.ipv4.proto.mask[0] = 0xff; | |
| 338 | + trap->key.ipv6.proto.value[0] = IPPROTO_UDP; | |
| 339 | + trap->key.ipv6.proto.mask[0] = 0xff; | |
| 340 | 340 | trap->key.ipv6.dport.value = PTP_EV_PORT; |
| 341 | 341 | trap->key.ipv6.dport.mask = 0xffff; |
| 342 | 342 | } |
| @@ -355,8 +355,8 @@ static void · 12 unmodified lines | ||
| 355 | 355 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 356 | 356 | { |
| 357 | 357 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 358 | − trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 359 | − trap->key.ipv4.proto.mask[0] = 0xff; | |
| 358 | + trap->key.ipv6.proto.value[0] = IPPROTO_UDP; | |
| 359 | + trap->key.ipv6.proto.mask[0] = 0xff; | |
| 360 | 360 | trap->key.ipv6.dport.value = PTP_GEN_PORT; |
| 361 | 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[] = { | |
| 297 | − [NFP_MEDIA_1000BASE_CX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | |
| 298 | − [NFP_MEDIA_1000BASE_KX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | |
| 299 | − [NFP_MEDIA_10GBASE_KX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | |
| 300 | − [NFP_MEDIA_10GBASE_KR] = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, | |
| 301 | − [NFP_MEDIA_10GBASE_CX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | |
| 302 | − [NFP_MEDIA_10GBASE_CR] = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, | |
| 303 | − [NFP_MEDIA_10GBASE_SR] = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, | |
| 304 | − [NFP_MEDIA_10GBASE_ER] = ETHTOOL_LINK_MODE_10000baseER_Full_BIT, | |
| 305 | − [NFP_MEDIA_25GBASE_KR] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | |
| 306 | − [NFP_MEDIA_25GBASE_KR_S] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, | |
| 307 | − [NFP_MEDIA_25GBASE_CR] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | |
| 308 | − [NFP_MEDIA_25GBASE_CR_S] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, | |
| 309 | − [NFP_MEDIA_25GBASE_SR] = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, | |
| 310 | − [NFP_MEDIA_40GBASE_CR4] = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, | |
| 311 | − [NFP_MEDIA_40GBASE_KR4] = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, | |
| 312 | − [NFP_MEDIA_40GBASE_SR4] = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, | |
| 313 | − [NFP_MEDIA_40GBASE_LR4] = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, | |
| 314 | − [NFP_MEDIA_50GBASE_KR] = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, | |
| 315 | − [NFP_MEDIA_50GBASE_SR] = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, | |
| 316 | − [NFP_MEDIA_50GBASE_CR] = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, | |
| 317 | − [NFP_MEDIA_50GBASE_LR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | |
| 318 | − [NFP_MEDIA_50GBASE_ER] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | |
| 319 | − [NFP_MEDIA_50GBASE_FR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, | |
| 320 | − [NFP_MEDIA_100GBASE_KR4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | |
| 321 | − [NFP_MEDIA_100GBASE_SR4] = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, | |
| 322 | − [NFP_MEDIA_100GBASE_CR4] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | |
| 323 | − [NFP_MEDIA_100GBASE_KP4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, | |
| 324 | − [NFP_MEDIA_100GBASE_CR10] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, | |
| 296 | +static const struct nfp_eth_media_link_mode { | |
| 297 | + u16 ethtool_link_mode; | |
| 298 | + u16 speed; | |
| 299 | +} nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { | |
| 300 | + [NFP_MEDIA_1000BASE_CX] = { | |
| 301 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | |
| 302 | + .speed = NFP_SPEED_1G, | |
| 303 | + }, | |
| 304 | + [NFP_MEDIA_1000BASE_KX] = { | |
| 305 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | |
| 306 | + .speed = NFP_SPEED_1G, | |
| 307 | + }, | |
| 308 | + [NFP_MEDIA_10GBASE_KX4] = { | |
| 309 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | |
| 310 | + .speed = NFP_SPEED_10G, | |
| 311 | + }, | |
| 312 | + [NFP_MEDIA_10GBASE_KR] = { | |
| 313 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, | |
| 314 | + .speed = NFP_SPEED_10G, | |
| 315 | + }, | |
| 316 | + [NFP_MEDIA_10GBASE_CX4] = { | |
| 317 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | |
| 318 | + .speed = NFP_SPEED_10G, | |
| 319 | + }, | |
| 320 | + [NFP_MEDIA_10GBASE_CR] = { | |
| 321 | + .ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, | |
| 322 | + .speed = NFP_SPEED_10G, | |
| 323 | + }, | |
| 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 | 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 | 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 | 435 | return; |
| 436 | + } | |
| 437 | + | |
| 438 | + bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); | |
| 339 | 439 | |
| 340 | 440 | for (u32 i = 0; i < 2; i++) { |
| 341 | 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 | 445 | for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { |
| 346 | 446 | if (i < 64) { |
| 347 | − if (supported_modes[0] & BIT_ULL(i)) | |
| 348 | − __set_bit(nfp_eth_media_table[i], | |
| 447 | + if (supported_modes[0] & BIT_ULL(i)) { | |
| 448 | + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, | |
| 349 | 449 | cmd->link_modes.supported); |
| 450 | + __set_bit(nfp_eth_media_table[i].speed, | |
| 451 | + port->speed_bitmap); | |
| 452 | + } | |
| 350 | 453 | |
| 351 | 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 | 456 | cmd->link_modes.advertising); |
| 354 | 457 | } else { |
| 355 | − if (supported_modes[1] & BIT_ULL(i - 64)) | |
| 356 | − __set_bit(nfp_eth_media_table[i], | |
| 458 | + if (supported_modes[1] & BIT_ULL(i - 64)) { | |
| 459 | + __set_bit(nfp_eth_media_table[i].ethtool_link_mode, | |
| 357 | 460 | cmd->link_modes.supported); |
| 461 | + __set_bit(nfp_eth_media_table[i].speed, | |
| 462 | + port->speed_bitmap); | |
| 463 | + } | |
| 358 | 464 | |
| 359 | 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 | 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 | 575 | if (cmd->base.speed != SPEED_UNKNOWN) { |
| 470 | 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 | 594 | if (req_aneg) { |
| 473 | 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 | 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 | 52 | * struct nfp_port - structure representing NFP port |
| 43 | 53 | * @netdev: backpointer to associated netdev |
| @@ -52,6 +62,7 @@ enum nfp_port_flags { · 8 unmodified lines | ||
| 52 | 62 | * @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change |
| 53 | 63 | * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry |
| 54 | 64 | * @eth_stats: for %NFP_PORT_PHYS_PORT MAC stats if available |
| 65 | + * @speed_bitmap: for %NFP_PORT_PHYS_PORT supported speed bitmap | |
| 55 | 66 | * @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3) |
| 56 | 67 | * @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id |
| 57 | 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 | 89 | bool eth_forced; |
| 79 | 90 | struct nfp_eth_table_port *eth_port; |
| 80 | 91 | u8 __iomem *eth_stats; |
| 92 | + DECLARE_BITMAP(speed_bitmap, NFP_SUP_SPEED_NUMBER); | |
| 81 | 93 | }; |
| 82 | 94 | /* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */ |
| 83 | 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 | 708 | q->lif->index, q->name, q->hw_type, q->hw_index, |
| 709 | 709 | q->head_idx, ring_doorbell); |
| 710 | 710 | |
| 711 | − if (ring_doorbell) | |
| 711 | + if (ring_doorbell) { | |
| 712 | 712 | ionic_dbell_ring(lif->kern_dbpage, q->hw_type, |
| 713 | 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 | 723 | static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos) |
| @@ -25,6 +25,12 @@ · 24 unmodified lines | ||
| 25 | 25 | #define IONIC_DEV_INFO_REG_COUNT 32 |
| 26 | 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 | 34 | struct ionic_dev_bar { |
| 29 | 35 | void __iomem *vaddr; |
| 30 | 36 | phys_addr_t bus_addr; |
| @@ -216,6 +222,8 @@ struct ionic_queue { · 185 unmodified lines | ||
| 216 | 222 | struct ionic_lif *lif; |
| 217 | 223 | struct ionic_desc_info *info; |
| 218 | 224 | u64 dbval; |
| 225 | + unsigned long dbell_deadline; | |
| 226 | + unsigned long dbell_jiffies; | |
| 219 | 227 | u16 head_idx; |
| 220 | 228 | u16 tail_idx; |
| 221 | 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 | 369 | int ionic_heartbeat_check(struct ionic *ionic); |
| 362 | 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 | 376 | #endif /* _IONIC_DEV_H_ */ |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #include "ionic.h" |
| 18 | 18 | #include "ionic_bus.h" |
| 19 | +#include "ionic_dev.h" | |
| 19 | 20 | #include "ionic_lif.h" |
| 20 | 21 | #include "ionic_txrx.h" |
| 21 | 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 | 211 | static irqreturn_t ionic_isr(int irq, void *data) |
| 204 | 212 | { |
| 205 | 213 | struct napi_struct *napi = data; |
| @@ -269,6 +277,7 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) · 63 unmodified lines | ||
| 269 | 277 | .oper = IONIC_Q_ENABLE, |
| 270 | 278 | }, |
| 271 | 279 | }; |
| 280 | + int ret; | |
| 272 | 281 | |
| 273 | 282 | idev = &lif->ionic->idev; |
| 274 | 283 | dev = lif->ionic->dev; |
| @@ -276,16 +285,24 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) · 1 unmodified line | ||
| 276 | 285 | dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n", |
| 277 | 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 | 298 | if (qcq->flags & IONIC_QCQ_F_INTR) { |
| 280 | 299 | irq_set_affinity_hint(qcq->intr.vector, |
| 281 | 300 | &qcq->intr.affinity_mask); |
| 282 | − napi_enable(&qcq->napi); | |
| 283 | − ionic_intr_clean(idev->intr_ctrl, qcq->intr.index); | |
| 284 | 301 | ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, |
| 285 | 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 | 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 | 333 | synchronize_irq(qcq->intr.vector); |
| 317 | 334 | irq_set_affinity_hint(qcq->intr.vector, NULL); |
| 318 | 335 | napi_disable(&qcq->napi); |
| 336 | + del_timer_sync(&qcq->napi_deadline); | |
| 319 | 337 | } |
| 320 | 338 | |
| 321 | 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 | 470 | n_qcq->intr.vector = src_qcq->intr.vector; |
| 453 | 471 | n_qcq->intr.index = src_qcq->intr.index; |
| 472 | + n_qcq->napi_qcq = src_qcq->napi_qcq; | |
| 454 | 473 | } |
| 455 | 474 | |
| 456 | 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 | 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 | 592 | q_size = ALIGN(num_descs * desc_size, PAGE_SIZE); |
| 571 | − cq_size = ALIGN(num_descs * cq_desc_size, PAGE_SIZE); | |
| 572 | − | |
| 573 | − new->q_size = PAGE_SIZE + q_size + cq_size; | |
| 593 | + new->q_size = PAGE_SIZE + q_size + | |
| 594 | + ALIGN(num_descs * cq_desc_size, PAGE_SIZE); | |
| 574 | 595 | new->q_base = dma_alloc_coherent(dev, new->q_size, |
| 575 | 596 | &new->q_base_pa, GFP_KERNEL); |
| 576 | 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 | 794 | dev_dbg(dev, "txq->hw_type %d\n", q->hw_type); |
| 774 | 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 | 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 | 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 | 855 | dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type); |
| 829 | 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 | 861 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) |
| 832 | 862 | netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi); |
| 833 | 863 | else |
| 834 | 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 | 869 | qcq->flags |= IONIC_QCQ_F_INITED; |
| 837 | 870 | |
| 838 | 871 | return 0; |
| @@ -1150,6 +1183,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) · 311 unmodified lines | ||
| 1150 | 1183 | struct ionic_dev *idev = &lif->ionic->idev; |
| 1151 | 1184 | unsigned long irqflags; |
| 1152 | 1185 | unsigned int flags = 0; |
| 1186 | + bool resched = false; | |
| 1153 | 1187 | int rx_work = 0; |
| 1154 | 1188 | int tx_work = 0; |
| 1155 | 1189 | int n_work = 0; |
| @@ -1187,6 +1221,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) · 31 unmodified lines | ||
| 1187 | 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 | 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 | 3289 | dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type); |
| 3246 | 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 | 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 | 3300 | napi_enable(&qcq->napi); |
| 3251 | 3301 | |
| 3252 | 3302 | if (qcq->flags & IONIC_QCQ_F_INTR) |
| @@ -74,8 +74,10 @@ struct ionic_qcq { · 73 unmodified lines | ||
| 74 | 74 | struct ionic_queue q; |
| 75 | 75 | struct ionic_cq cq; |
| 76 | 76 | struct ionic_intr_info intr; |
| 77 | + struct timer_list napi_deadline; | |
| 77 | 78 | struct napi_struct napi; |
| 78 | 79 | unsigned int flags; |
| 80 | + struct ionic_qcq *napi_qcq; | |
| 79 | 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 | 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 | 321 | int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) |
| 293 | 322 | { |
| 294 | 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 | 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 | 86 | static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q) |
| 26 | 87 | { |
| 27 | 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 | 486 | ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, |
| 426 | 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 | 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 | 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 | 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 | 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 | 620 | return work_done; |
| 548 | 621 | } |
| 549 | 622 | |
| 550 | 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 | 626 | struct ionic_cq *rxcq = napi_to_cq(napi); |
| 554 | 627 | unsigned int qi = rxcq->bound_q->index; |
| 628 | + struct ionic_qcq *txqcq; | |
| 555 | 629 | struct ionic_dev *idev; |
| 556 | 630 | struct ionic_lif *lif; |
| 557 | 631 | struct ionic_cq *txcq; |
| 632 | + bool resched = false; | |
| 558 | 633 | u32 rx_work_done = 0; |
| 559 | 634 | u32 tx_work_done = 0; |
| 560 | 635 | u32 flags = 0; |
| 561 | 636 | |
| 562 | 637 | lif = rxcq->bound_q->lif; |
| 563 | 638 | idev = &lif->ionic->idev; |
| 639 | + txqcq = lif->txqcqs[qi]; | |
| 564 | 640 | txcq = &lif->txqcqs[qi]->cq; |
| 565 | 641 | |
| 566 | 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 | 648 | ionic_rx_fill(rxcq->bound_q); |
| 573 | 649 | |
| 574 | 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 | 652 | flags |= IONIC_INTR_CRED_UNMASK; |
| 577 | 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 | 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 | 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 | 1035 | packet->dma_range = kcalloc(page_count, |
| 1036 | 1036 | sizeof(*packet->dma_range), |
| 1037 | − GFP_KERNEL); | |
| 1037 | + GFP_ATOMIC); | |
| 1038 | 1038 | if (!packet->dma_range) |
| 1039 | 1039 | return -ENOMEM; |
| 1040 | 1040 | |
| @@ -261,6 +261,8 @@ static struct phy_driver meson_gxl_phy[] = { · 260 unmodified lines | ||
| 261 | 261 | .handle_interrupt = meson_gxl_handle_interrupt, |
| 262 | 262 | .suspend = genphy_suspend, |
| 263 | 263 | .resume = genphy_resume, |
| 264 | + .read_mmd = genphy_read_mmd_unsupported, | |
| 265 | + .write_mmd = genphy_write_mmd_unsupported, | |
| 264 | 266 | }, { |
| 265 | 267 | PHY_ID_MATCH_EXACT(0x01803301), |
| 266 | 268 | .name = "Meson G12A Internal PHY", |
| @@ -1816,10 +1816,9 @@ int phylink_fwnode_phy_connect(struct phylink *pl, · 1815 unmodified lines | ||
| 1816 | 1816 | |
| 1817 | 1817 | ret = phy_attach_direct(pl->netdev, phy_dev, flags, |
| 1818 | 1818 | pl->link_interface); |
| 1819 | − if (ret) { | |
| 1820 | − phy_device_free(phy_dev); | |
| 1819 | + phy_device_free(phy_dev); | |
| 1820 | + if (ret) | |
| 1821 | 1821 | return ret; |
| 1822 | − } | |
| 1823 | 1822 | |
| 1824 | 1823 | ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface); |
| 1825 | 1824 | if (ret) |
| @@ -57,9 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | static inline int |
| 58 | 58 | pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) |
| 59 | 59 | { |
| 60 | − return usbnet_read_cmd(dev, req, | |
| 61 | − USB_DIR_IN | USB_TYPE_VENDOR | | |
| 62 | − USB_RECIP_DEVICE, | |
| 60 | + return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 63 | 61 | val, index, NULL, 0); |
| 64 | 62 | } |
| 65 | 63 | |
| @@ -45,6 +45,8 @@ struct nvme_dhchap_queue_context { · 44 unmodified lines | ||
| 45 | 45 | int sess_key_len; |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | +struct workqueue_struct *nvme_auth_wq; | |
| 49 | + | |
| 48 | 50 | #define nvme_auth_flags_from_qid(qid) \ |
| 49 | 51 | (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED |
| 50 | 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 | 869 | chap = &ctrl->dhchap_ctxs[qid]; |
| 868 | 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 | 872 | return 0; |
| 871 | 873 | } |
| 872 | 874 | EXPORT_SYMBOL_GPL(nvme_auth_negotiate); |
| @@ -1008,10 +1010,15 @@ EXPORT_SYMBOL_GPL(nvme_auth_free); · 135 unmodified lines | ||
| 1008 | 1010 | |
| 1009 | 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 | 1018 | nvme_chap_buf_cache = kmem_cache_create("nvme-chap-buf-cache", |
| 1012 | 1019 | CHAP_BUF_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL); |
| 1013 | 1020 | if (!nvme_chap_buf_cache) |
| 1014 | − return -ENOMEM; | |
| 1021 | + goto err_destroy_workqueue; | |
| 1015 | 1022 | |
| 1016 | 1023 | nvme_chap_buf_pool = mempool_create(16, mempool_alloc_slab, |
| 1017 | 1024 | mempool_free_slab, nvme_chap_buf_cache); |
| @@ -1021,6 +1028,8 @@ int __init nvme_init_auth(void) · 3 unmodified lines | ||
| 1021 | 1028 | return 0; |
| 1022 | 1029 | err_destroy_chap_buf_cache: |
| 1023 | 1030 | kmem_cache_destroy(nvme_chap_buf_cache); |
| 1031 | +err_destroy_workqueue: | |
| 1032 | + destroy_workqueue(nvme_auth_wq); | |
| 1024 | 1033 | return -ENOMEM; |
| 1025 | 1034 | } |
| 1026 | 1035 | |
| @@ -1028,4 +1037,5 @@ void __exit nvme_exit_auth(void) · 1 unmodified line | ||
| 1028 | 1037 | { |
| 1029 | 1038 | mempool_destroy(nvme_chap_buf_pool); |
| 1030 | 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 | 4921 | blk_mq_destroy_queue(ctrl->admin_q); |
| 4922 | 4922 | blk_put_queue(ctrl->admin_q); |
| 4923 | 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 | 4927 | return ret; |
| 4926 | 4928 | } |
| 4927 | 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 | 4986 | out_free_tag_set: |
| 4985 | 4987 | blk_mq_free_tag_set(set); |
| 4988 | + ctrl->connect_q = NULL; | |
| 4986 | 4989 | return ret; |
| 4987 | 4990 | } |
| 4988 | 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 | 1685 | else { |
| 1686 | 1686 | queue = nvmet_fc_alloc_target_queue(iod->assoc, 0, |
| 1687 | 1687 | be16_to_cpu(rqst->assoc_cmd.sqsize)); |
| 1688 | − if (!queue) | |
| 1688 | + if (!queue) { | |
| 1689 | 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 | 98 | len = le32_to_cpu(header.len); |
| 99 | 99 | |
| 100 | 100 | data = kzalloc(len, GFP_KERNEL); |
| 101 | + if (!data) | |
| 102 | + return -ENOMEM; | |
| 103 | + | |
| 101 | 104 | memcpy_fromio(data, priv->base, len); |
| 102 | 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 | 770 | return ERR_PTR(rval); |
| 771 | 771 | } |
| 772 | 772 | |
| 773 | − if (config->wp_gpio) | |
| 774 | − nvmem->wp_gpio = config->wp_gpio; | |
| 775 | − else if (!config->ignore_wp) | |
| 773 | + nvmem->id = rval; | |
| 774 | + | |
| 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 | 782 | nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp", |
| 777 | 783 | GPIOD_OUT_HIGH); |
| 778 | 784 | if (IS_ERR(nvmem->wp_gpio)) { |
| 779 | − ida_free(&nvmem_ida, nvmem->id); | |
| 780 | 785 | rval = PTR_ERR(nvmem->wp_gpio); |
| 781 | − kfree(nvmem); | |
| 782 | − return ERR_PTR(rval); | |
| 786 | + nvmem->wp_gpio = NULL; | |
| 787 | + goto err_put_device; | |
| 783 | 788 | } |
| 784 | 789 | |
| 785 | 790 | kref_init(&nvmem->refcnt); |
| 786 | 791 | INIT_LIST_HEAD(&nvmem->cells); |
| 787 | 792 | |
| 788 | − nvmem->id = rval; | |
| 789 | 793 | nvmem->owner = config->owner; |
| 790 | 794 | if (!nvmem->owner && config->dev->driver) |
| 791 | 795 | nvmem->owner = config->dev->driver->owner; |
| 792 | 796 | nvmem->stride = config->stride ?: 1; |
| 793 | 797 | nvmem->word_size = config->word_size ?: 1; |
| 794 | 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 | 799 | nvmem->root_only = config->root_only; |
| 799 | 800 | nvmem->priv = config->priv; |
| 800 | 801 | nvmem->type = config->type; |
| @@ -822,11 +823,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) · 21 unmodified lines | ||
| 822 | 823 | break; |
| 823 | 824 | } |
| 824 | 825 | |
| 825 | − if (rval) { | |
| 826 | − ida_free(&nvmem_ida, nvmem->id); | |
| 827 | − kfree(nvmem); | |
| 828 | − return ERR_PTR(rval); | |
| 829 | − } | |
| 826 | + if (rval) | |
| 827 | + goto err_put_device; | |
| 830 | 828 | |
| 831 | 829 | nvmem->read_only = device_property_present(config->dev, "read-only") || |
| 832 | 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 | 833 | nvmem->dev.groups = nvmem_dev_groups; |
| 836 | 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 | 836 | if (nvmem->nkeepout) { |
| 845 | 837 | rval = nvmem_validate_keepouts(nvmem); |
| 846 | 838 | if (rval) |
| 847 | − goto err_device_del; | |
| 839 | + goto err_put_device; | |
| 848 | 840 | } |
| 849 | 841 | |
| 850 | 842 | if (config->compat) { |
| 851 | 843 | rval = nvmem_sysfs_setup_compat(nvmem, config); |
| 852 | 844 | if (rval) |
| 853 | − goto err_device_del; | |
| 845 | + goto err_put_device; | |
| 854 | 846 | } |
| 855 | 847 | |
| 856 | 848 | if (config->cells) { |
| 857 | 849 | rval = nvmem_add_cells(nvmem, config->cells, config->ncells); |
| 858 | 850 | if (rval) |
| 859 | − goto err_teardown_compat; | |
| 851 | + goto err_remove_cells; | |
| 860 | 852 | } |
| 861 | 853 | |
| 862 | 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 | 859 | if (rval) |
| 868 | 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 | 868 | blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); |
| 871 | 869 | |
| 872 | 870 | return nvmem; |
| 873 | 871 | |
| 874 | 872 | err_remove_cells: |
| 875 | 873 | nvmem_device_remove_all_cells(nvmem); |
| 876 | −err_teardown_compat: | |
| 877 | 874 | if (config->compat) |
| 878 | 875 | nvmem_sysfs_remove_compat(nvmem, config); |
| 879 | −err_device_del: | |
| 880 | − device_del(&nvmem->dev); | |
| 881 | 876 | err_put_device: |
| 882 | 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 | 1237 | if (!cell_np) |
| 1243 | 1238 | return ERR_PTR(-ENOENT); |
| 1244 | 1239 | |
| 1245 | − nvmem_np = of_get_next_parent(cell_np); | |
| 1246 | − if (!nvmem_np) | |
| 1240 | + nvmem_np = of_get_parent(cell_np); | |
| 1241 | + if (!nvmem_np) { | |
| 1242 | + of_node_put(cell_np); | |
| 1247 | 1243 | return ERR_PTR(-EINVAL); |
| 1244 | + } | |
| 1248 | 1245 | |
| 1249 | 1246 | nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); |
| 1250 | 1247 | of_node_put(nvmem_np); |
| 1251 | − if (IS_ERR(nvmem)) | |
| 1248 | + if (IS_ERR(nvmem)) { | |
| 1249 | + of_node_put(cell_np); | |
| 1252 | 1250 | return ERR_CAST(nvmem); |
| 1251 | + } | |
| 1253 | 1252 | |
| 1254 | 1253 | cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np); |
| 1254 | + of_node_put(cell_np); | |
| 1255 | 1255 | if (!cell_entry) { |
| 1256 | 1256 | __nvmem_device_put(nvmem); |
| 1257 | 1257 | return ERR_PTR(-ENOENT); |
| @@ -166,6 +166,7 @@ static const struct of_device_id sdam_match_table[] = { · 165 unmodified lines | ||
| 166 | 166 | { .compatible = "qcom,spmi-sdam" }, |
| 167 | 167 | {}, |
| 168 | 168 | }; |
| 169 | +MODULE_DEVICE_TABLE(of, sdam_match_table); | |
| 169 | 170 | |
| 170 | 171 | static struct platform_driver sdam_driver = { |
| 171 | 172 | .driver = { |
| @@ -41,8 +41,21 @@ static int sunxi_sid_read(void *context, unsigned int offset, · 40 unmodified lines | ||
| 41 | 41 | void *val, size_t bytes) |
| 42 | 42 | { |
| 43 | 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 | 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 | 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 | 974 | num_ranges++; |
| 975 | + } | |
| 976 | + | |
| 977 | + if (!num_ranges) { | |
| 978 | + ret = -EINVAL; | |
| 979 | + goto out; | |
| 980 | + } | |
| 970 | 981 | |
| 971 | 982 | r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL); |
| 972 | 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 | 992 | *map = r; |
| 981 | 993 | of_dma_range_parser_init(&parser, node); |
| 982 | 994 | for_each_of_range(&parser, &range) { |
| 983 | 995 | pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", |
| 984 | 996 | range.bus_addr, range.cpu_addr, range.size); |
| 985 | − 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); | |
| 997 | + if (range.cpu_addr == OF_BAD_ADDR) | |
| 988 | 998 | continue; |
| 989 | − } | |
| 990 | 999 | r->cpu_start = range.cpu_addr; |
| 991 | 1000 | r->dma_start = range.bus_addr; |
| 992 | 1001 | r->size = range.size; |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/serial_core.h> |
| 27 | 27 | #include <linux/sysfs.h> |
| 28 | 28 | #include <linux/random.h> |
| 29 | −#include <linux/kmemleak.h> | |
| 30 | 29 | |
| 31 | 30 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
| 32 | 31 | #include <asm/page.h> |
| @@ -525,12 +524,9 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, · 492 unmodified lines | ||
| 525 | 524 | size = dt_mem_next_cell(dt_root_size_cells, &prop); |
| 526 | 525 | |
| 527 | 526 | if (size && |
| 528 | − early_init_dt_reserve_memory(base, size, nomap) == 0) { | |
| 527 | + early_init_dt_reserve_memory(base, size, nomap) == 0) | |
| 529 | 528 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", |
| 530 | 529 | uname, &base, (unsigned long)(size / SZ_1M)); |
| 531 | − if (!nomap) | |
| 532 | − kmemleak_alloc_phys(base, size, 0); | |
| 533 | − } | |
| 534 | 530 | else |
| 535 | 531 | pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", |
| 536 | 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 | 525 | if (IS_ENABLED(CONFIG_PPC)) { |
| 526 | 526 | struct device_node *boot_display = NULL; |
| 527 | 527 | struct platform_device *dev; |
| 528 | + int display_number = 0; | |
| 528 | 529 | int ret; |
| 529 | 530 | |
| 530 | 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 | 556 | if (!of_get_property(node, "linux,opened", NULL) || |
| 556 | 557 | !of_get_property(node, "linux,boot-display", NULL)) |
| 557 | 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 | 561 | if (WARN_ON(!dev)) |
| 560 | 562 | return -ENOMEM; |
| 561 | 563 | boot_display = node; |
| 564 | + display_number++; | |
| 562 | 565 | break; |
| 563 | 566 | } |
| 564 | 567 | for_each_node_by_type(node, "display") { |
| 568 | + char buf[14]; | |
| 569 | + const char *of_display_format = "of-display.%d"; | |
| 570 | + | |
| 565 | 571 | if (!of_get_property(node, "linux,opened", NULL) || node == boot_display) |
| 566 | 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 | 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 | 275 | /* We'll use a local copy of buf */ |
| 276 | 276 | count = min_t(size_t, count, sizeof(in)-1); |
| 277 | − strncpy(in, buf, count); | |
| 278 | − in[count] = '\0'; | |
| 277 | + strscpy(in, buf, count + 1); | |
| 279 | 278 | |
| 280 | 279 | /* Let's clean up the target. 0xff is a blank pattern */ |
| 281 | 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 | 388 | /* We'll use a local copy of buf */ |
| 390 | 389 | count = min_t(size_t, count, sizeof(in)-1); |
| 391 | − strncpy(in, buf, count); | |
| 392 | − in[count] = '\0'; | |
| 390 | + strscpy(in, buf, count + 1); | |
| 393 | 391 | |
| 394 | 392 | /* Let's clean up the target. 0 is a blank pattern */ |
| 395 | 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 | 755 | /* We'll use a local copy of buf */ |
| 758 | 756 | count = min_t(size_t, count, sizeof(in)-1); |
| 759 | − strncpy(in, buf, count); | |
| 760 | − in[count] = '\0'; | |
| 757 | + strscpy(in, buf, count + 1); | |
| 761 | 758 | |
| 762 | 759 | /* Current flags are stored in primary boot path entry */ |
| 763 | 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 | 189 | static int efi_procfs(struct device *dev, struct seq_file *seq) |
| 190 | 190 | { |
| 191 | − efi_time_t eft, alm; | |
| 192 | − efi_time_cap_t cap; | |
| 193 | − efi_bool_t enabled, pending; | |
| 191 | + efi_time_t eft, alm; | |
| 192 | + efi_time_cap_t cap; | |
| 193 | + efi_bool_t enabled, pending; | |
| 194 | + struct rtc_device *rtc = dev_get_drvdata(dev); | |
| 194 | 195 | |
| 195 | 196 | memset(&eft, 0, sizeof(eft)); |
| 196 | 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 | 214 | /* XXX fixme: convert to string? */ |
| 214 | 215 | seq_printf(seq, "Timezone\t: %u\n", eft.timezone); |
| 215 | 216 | |
| 216 | − seq_printf(seq, | |
| 217 | − "Alarm Time\t: %u:%u:%u.%09u\n" | |
| 218 | − "Alarm Date\t: %u-%u-%u\n" | |
| 219 | − "Alarm Daylight\t: %u\n" | |
| 220 | − "Enabled\t\t: %s\n" | |
| 221 | − "Pending\t\t: %s\n", | |
| 222 | − alm.hour, alm.minute, alm.second, alm.nanosecond, | |
| 223 | − alm.year, alm.month, alm.day, | |
| 224 | − alm.daylight, | |
| 225 | − enabled == 1 ? "yes" : "no", | |
| 226 | − pending == 1 ? "yes" : "no"); | |
| 227 | − | |
| 228 | − if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE) | |
| 229 | − seq_puts(seq, "Timezone\t: unspecified\n"); | |
| 230 | − else | |
| 231 | − /* XXX fixme: convert to string? */ | |
| 232 | − seq_printf(seq, "Timezone\t: %u\n", alm.timezone); | |
| 217 | + if (test_bit(RTC_FEATURE_ALARM, rtc->features)) { | |
| 218 | + seq_printf(seq, | |
| 219 | + "Alarm Time\t: %u:%u:%u.%09u\n" | |
| 220 | + "Alarm Date\t: %u-%u-%u\n" | |
| 221 | + "Alarm Daylight\t: %u\n" | |
| 222 | + "Enabled\t\t: %s\n" | |
| 223 | + "Pending\t\t: %s\n", | |
| 224 | + alm.hour, alm.minute, alm.second, alm.nanosecond, | |
| 225 | + alm.year, alm.month, alm.day, | |
| 226 | + alm.daylight, | |
| 227 | + enabled == 1 ? "yes" : "no", | |
| 228 | + pending == 1 ? "yes" : "no"); | |
| 229 | + | |
| 230 | + if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE) | |
| 231 | + seq_puts(seq, "Timezone\t: unspecified\n"); | |
| 232 | + else | |
| 233 | + /* XXX fixme: convert to string? */ | |
| 234 | + seq_printf(seq, "Timezone\t: %u\n", alm.timezone); | |
| 235 | + } | |
| 233 | 236 | |
| 234 | 237 | /* |
| 235 | 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 | 273 | rtc->ops = &efi_rtc_ops; |
| 271 | 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 | 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 | 240 | if (IS_ERR(sp_rtc->reg_base)) |
| 241 | 241 | return dev_err_probe(&plat_dev->dev, PTR_ERR(sp_rtc->reg_base), |
| 242 | 242 | "%s devm_ioremap_resource fail\n", RTC_REG_NAME); |
| 243 | − dev_dbg(&plat_dev->dev, "res = 0x%x, reg_base = 0x%lx\n", | |
| 244 | − sp_rtc->res->start, (unsigned long)sp_rtc->reg_base); | |
| 243 | + dev_dbg(&plat_dev->dev, "res = %pR, reg_base = %p\n", | |
| 244 | + sp_rtc->res, sp_rtc->reg_base); | |
| 245 | 245 | |
| 246 | 246 | sp_rtc->irq = platform_get_irq(plat_dev, 0); |
| 247 | 247 | if (sp_rtc->irq < 0) |
| @@ -43,15 +43,23 @@ static void __dma_rx_complete(struct uart_8250_port *p) · 42 unmodified lines | ||
| 43 | 43 | struct uart_8250_dma *dma = p->dma; |
| 44 | 44 | struct tty_port *tty_port = &p->port.state->port; |
| 45 | 45 | struct dma_tx_state state; |
| 46 | + enum dma_status dma_status; | |
| 46 | 47 | int count; |
| 47 | 48 | |
| 48 | − dma->rx_running = 0; | |
| 49 | − dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); | |
| 49 | + /* | |
| 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 | 58 | count = dma->rx_size - state.residue; |
| 52 | 59 | |
| 53 | 60 | tty_insert_flip_string(tty_port, dma->rx_buf, count); |
| 54 | 61 | p->port.icount.rx += count; |
| 62 | + dma->rx_running = 0; | |
| 55 | 63 | |
| 56 | 64 | tty_flip_buffer_push(tty_port); |
| 57 | 65 | } |
| @@ -62,9 +70,14 @@ static void dma_rx_complete(void *param) · 4 unmodified lines | ||
| 62 | 70 | struct uart_8250_dma *dma = p->dma; |
| 63 | 71 | unsigned long flags; |
| 64 | 72 | |
| 65 | − __dma_rx_complete(p); | |
| 66 | − | |
| 67 | 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 | 81 | if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR)) |
| 69 | 82 | p->dma->rx_dma(p); |
| 70 | 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 | 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 | 800 | /* Receiver timeout irq for DMA RX */ |
| 815 | − if (!stm32_port->throttled) { | |
| 816 | − spin_lock_irqsave(&port->lock, flags); | |
| 801 | + if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) { | |
| 802 | + spin_lock(&port->lock); | |
| 817 | 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 | 805 | if (size) |
| 820 | 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 | 1001 | u32 val; |
| 1016 | 1002 | int ret; |
| 1017 | 1003 | |
| 1018 | − ret = request_threaded_irq(port->irq, stm32_usart_interrupt, | |
| 1019 | − stm32_usart_threaded_interrupt, | |
| 1020 | − IRQF_ONESHOT | IRQF_NO_SUSPEND, | |
| 1021 | − name, port); | |
| 1004 | + ret = request_irq(port->irq, stm32_usart_interrupt, | |
| 1005 | + IRQF_NO_SUSPEND, name, port); | |
| 1022 | 1006 | if (ret) |
| 1023 | 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 | 1585 | struct dma_slave_config config; |
| 1602 | 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 | 1588 | stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L, |
| 1612 | 1589 | &stm32port->rx_dma_buf, |
| 1613 | 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 | 387 | uni_mode = use_unicode(inode); |
| 388 | 388 | attr = use_attributes(inode); |
| 389 | − ret = -ENXIO; | |
| 390 | − vc = vcs_vc(inode, &viewed); | |
| 391 | − if (!vc) | |
| 392 | − goto unlock_out; | |
| 393 | 389 | |
| 394 | 390 | ret = -EINVAL; |
| 395 | 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 | 403 | unsigned int this_round, skip = 0; |
| 408 | 404 | int size; |
| 409 | 405 | |
| 406 | + ret = -ENXIO; | |
| 407 | + vc = vcs_vc(inode, &viewed); | |
| 408 | + if (!vc) | |
| 409 | + goto unlock_out; | |
| 410 | + | |
| 410 | 411 | /* Check whether we are above size each round, |
| 411 | 412 | * as copy_to_user at the end of this loop |
| 412 | 413 | * could sleep. |
| @@ -901,7 +901,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 900 unmodified lines | ||
| 901 | 901 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); |
| 902 | 902 | |
| 903 | 903 | /* enable vbus override for device mode */ |
| 904 | − if (qcom->mode == USB_DR_MODE_PERIPHERAL) | |
| 904 | + if (qcom->mode != USB_DR_MODE_HOST) | |
| 905 | 905 | dwc3_qcom_vbus_override_enable(qcom, true); |
| 906 | 906 | |
| 907 | 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 | 1014 | int ret; |
| 1015 | 1015 | |
| 1016 | 1016 | /* hook up the driver */ |
| 1017 | − driver->driver.bus = NULL; | |
| 1018 | 1017 | fotg210->driver = driver; |
| 1019 | 1018 | |
| 1020 | 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 | 279 | struct usb_request *req = ffs->ep0req; |
| 280 | 280 | int ret; |
| 281 | 281 | |
| 282 | − if (!req) | |
| 282 | + if (!req) { | |
| 283 | + spin_unlock_irq(&ffs->ev.waitq.lock); | |
| 283 | 284 | return -EINVAL; |
| 285 | + } | |
| 284 | 286 | |
| 285 | 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 | 1143 | std_as_out_if0_desc.bInterfaceNumber = ret; |
| 1144 | 1144 | std_as_out_if1_desc.bInterfaceNumber = ret; |
| 1145 | + std_as_out_if1_desc.bNumEndpoints = 1; | |
| 1145 | 1146 | uac2->as_out_intf = ret; |
| 1146 | 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 | 1830 | bcm63xx_select_phy_mode(udc, true); |
| 1831 | 1831 | |
| 1832 | 1832 | udc->driver = driver; |
| 1833 | − driver->driver.bus = NULL; | |
| 1834 | 1833 | udc->gadget.dev.of_node = udc->dev->of_node; |
| 1835 | 1834 | |
| 1836 | 1835 | spin_unlock_irqrestore(&udc->lock, flags); |
| @@ -2285,7 +2285,6 @@ static int fsl_qe_start(struct usb_gadget *gadget, · 2284 unmodified lines | ||
| 2285 | 2285 | /* lock is needed but whether should use this lock or another */ |
| 2286 | 2286 | spin_lock_irqsave(&udc->lock, flags); |
| 2287 | 2287 | |
| 2288 | − driver->driver.bus = NULL; | |
| 2289 | 2288 | /* hook up the driver */ |
| 2290 | 2289 | udc->driver = driver; |
| 2291 | 2290 | udc->gadget.speed = driver->max_speed; |
| @@ -1943,7 +1943,6 @@ static int fsl_udc_start(struct usb_gadget *g, · 1942 unmodified lines | ||
| 1943 | 1943 | /* lock is needed but whether should use this lock or another */ |
| 1944 | 1944 | spin_lock_irqsave(&udc_controller->lock, flags); |
| 1945 | 1945 | |
| 1946 | − driver->driver.bus = NULL; | |
| 1947 | 1946 | /* hook up the driver */ |
| 1948 | 1947 | udc_controller->driver = driver; |
| 1949 | 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 | 1311 | struct fusb300 *fusb300 = to_fusb300(g); |
| 1312 | 1312 | |
| 1313 | 1313 | /* hook up the driver */ |
| 1314 | − driver->driver.bus = NULL; | |
| 1315 | 1314 | fusb300->driver = driver; |
| 1316 | 1315 | |
| 1317 | 1316 | return 0; |
| @@ -1375,7 +1375,6 @@ static int goku_udc_start(struct usb_gadget *g, · 1374 unmodified lines | ||
| 1375 | 1375 | struct goku_udc *dev = to_goku_udc(g); |
| 1376 | 1376 | |
| 1377 | 1377 | /* hook up the driver */ |
| 1378 | − driver->driver.bus = NULL; | |
| 1379 | 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 | 1906 | spin_lock(&dev->lock); |
| 1907 | 1907 | |
| 1908 | 1908 | /* Hook up the driver */ |
| 1909 | − driver->driver.bus = NULL; | |
| 1910 | 1909 | dev->driver = driver; |
| 1911 | 1910 | |
| 1912 | 1911 | /* Get ready for host detection */ |
| @@ -1454,7 +1454,6 @@ static int m66592_udc_start(struct usb_gadget *g, · 1453 unmodified lines | ||
| 1454 | 1454 | struct m66592 *m66592 = to_m66592(g); |
| 1455 | 1455 | |
| 1456 | 1456 | /* hook up the driver */ |
| 1457 | − driver->driver.bus = NULL; | |
| 1458 | 1457 | m66592->driver = driver; |
| 1459 | 1458 | |
| 1460 | 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 | 1109 | spin_lock_irqsave(&udc->lock, flags); |
| 1110 | 1110 | /* hook up the driver */ |
| 1111 | − driver->driver.bus = NULL; | |
| 1112 | 1111 | udc->driver = driver; |
| 1113 | 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 | 1245 | /* hook up the driver ... */ |
| 1246 | − driver->driver.bus = NULL; | |
| 1247 | 1246 | u3d->driver = driver; |
| 1248 | 1247 | |
| 1249 | 1248 | u3d->ep0_dir = USB_DIR_OUT; |
| @@ -1359,7 +1359,6 @@ static int mv_udc_start(struct usb_gadget *gadget, · 1358 unmodified lines | ||
| 1359 | 1359 | spin_lock_irqsave(&udc->lock, flags); |
| 1360 | 1360 | |
| 1361 | 1361 | /* hook up the driver ... */ |
| 1362 | − driver->driver.bus = NULL; | |
| 1363 | 1362 | udc->driver = driver; |
| 1364 | 1363 | |
| 1365 | 1364 | udc->usb_state = USB_STATE_ATTACHED; |
| @@ -1451,7 +1451,6 @@ static int net2272_start(struct usb_gadget *_gadget, · 1450 unmodified lines | ||
| 1451 | 1451 | dev->ep[i].irqs = 0; |
| 1452 | 1452 | /* hook up the driver ... */ |
| 1453 | 1453 | dev->softconnect = 1; |
| 1454 | − driver->driver.bus = NULL; | |
| 1455 | 1454 | dev->driver = driver; |
| 1456 | 1455 | |
| 1457 | 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 | 2423 | dev->ep[i].irqs = 0; |
| 2424 | 2424 | |
| 2425 | 2425 | /* hook up the driver ... */ |
| 2426 | − driver->driver.bus = NULL; | |
| 2427 | 2426 | dev->driver = driver; |
| 2428 | 2427 | |
| 2429 | 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 | 2066 | udc->softconnect = 1; |
| 2067 | 2067 | |
| 2068 | 2068 | /* hook up the driver */ |
| 2069 | − driver->driver.bus = NULL; | |
| 2070 | 2069 | udc->driver = driver; |
| 2071 | 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 | 2909 | struct pch_udc_dev *dev = to_pch_udc(g); |
| 2910 | 2910 | |
| 2911 | − driver->driver.bus = NULL; | |
| 2912 | 2911 | dev->driver = driver; |
| 2913 | 2912 | |
| 2914 | 2913 | /* get ready for ep0 traffic */ |
| @@ -1933,7 +1933,6 @@ static int amd5536_udc_start(struct usb_gadget *g, · 1932 unmodified lines | ||
| 1933 | 1933 | struct udc *dev = to_amd5536_udc(g); |
| 1934 | 1934 | u32 tmp; |
| 1935 | 1935 | |
| 1936 | − driver->driver.bus = NULL; | |
| 1937 | 1936 | dev->driver = driver; |
| 1938 | 1937 | |
| 1939 | 1938 | /* Some gadget drivers use both ep0 directions. |
| @@ -1269,6 +1269,9 @@ err_unregister: · 1268 unmodified lines | ||
| 1269 | 1269 | con->port = NULL; |
| 1270 | 1270 | } |
| 1271 | 1271 | |
| 1272 | + kfree(ucsi->connector); | |
| 1273 | + ucsi->connector = NULL; | |
| 1274 | + | |
| 1272 | 1275 | err_reset: |
| 1273 | 1276 | memset(&ucsi->cap, 0, sizeof(ucsi->cap)); |
| 1274 | 1277 | ucsi_reset_ppm(ucsi); |
| @@ -1300,7 +1303,8 @@ static void ucsi_resume_work(struct work_struct *work) · 25 unmodified lines | ||
| 1300 | 1303 | |
| 1301 | 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 | 1308 | return 0; |
| 1305 | 1309 | } |
| 1306 | 1310 | EXPORT_SYMBOL_GPL(ucsi_resume); |
| @@ -1420,6 +1424,9 @@ void ucsi_unregister(struct ucsi *ucsi) · 113 unmodified lines | ||
| 1420 | 1424 | /* Disable notifications */ |
| 1421 | 1425 | ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
| 1422 | 1426 | |
| 1427 | + if (!ucsi->connector) | |
| 1428 | + return; | |
| 1429 | + | |
| 1423 | 1430 | for (i = 0; i < ucsi->cap.num_connectors; i++) { |
| 1424 | 1431 | cancel_work_sync(&ucsi->connector[i].work); |
| 1425 | 1432 | ucsi_unregister_partner(&ucsi->connector[i]); |
| @@ -49,7 +49,6 @@ struct atmel_lcdfb_info { · 48 unmodified lines | ||
| 49 | 49 | struct clk *lcdc_clk; |
| 50 | 50 | |
| 51 | 51 | struct backlight_device *backlight; |
| 52 | − u8 bl_power; | |
| 53 | 52 | u8 saved_lcdcon; |
| 54 | 53 | |
| 55 | 54 | u32 pseudo_palette[16]; |
| @@ -109,22 +108,7 @@ static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 · 53 unmodified lines | ||
| 109 | 108 | static int atmel_bl_update_status(struct backlight_device *bl) |
| 110 | 109 | { |
| 111 | 110 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); |
| 112 | − int power = sinfo->bl_power; | |
| 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; | |
| 111 | + int brightness = backlight_get_brightness(bl); | |
| 128 | 112 | |
| 129 | 113 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); |
| 130 | 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 | 117 | else |
| 134 | 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 | 120 | return 0; |
| 139 | 121 | } |
| 140 | 122 | |
| @@ -155,8 +137,6 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) · 14 unmodified lines | ||
| 155 | 137 | struct backlight_properties props; |
| 156 | 138 | struct backlight_device *bl; |
| 157 | 139 | |
| 158 | − sinfo->bl_power = FB_BLANK_UNBLANK; | |
| 159 | − | |
| 160 | 140 | if (sinfo->backlight) |
| 161 | 141 | return; |
| 162 | 142 | |
| @@ -1766,12 +1766,10 @@ static int aty128_bl_update_status(struct backlight_device *bd) · 1765 unmodified lines | ||
| 1766 | 1766 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1767 | 1767 | int level; |
| 1768 | 1768 | |
| 1769 | − if (bd->props.power != FB_BLANK_UNBLANK || | |
| 1770 | − bd->props.fb_blank != FB_BLANK_UNBLANK || | |
| 1771 | − !par->lcd_on) | |
| 1769 | + if (!par->lcd_on) | |
| 1772 | 1770 | level = 0; |
| 1773 | 1771 | else |
| 1774 | − level = bd->props.brightness; | |
| 1772 | + level = backlight_get_brightness(bd); | |
| 1775 | 1773 | |
| 1776 | 1774 | reg |= LVDS_BL_MOD_EN | LVDS_BLON; |
| 1777 | 1775 | if (level > 0) { |
| @@ -2219,13 +2219,7 @@ static int aty_bl_update_status(struct backlight_device *bd) · 2218 unmodified lines | ||
| 2219 | 2219 | { |
| 2220 | 2220 | struct atyfb_par *par = bl_get_data(bd); |
| 2221 | 2221 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); |
| 2222 | − int level; | |
| 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; | |
| 2222 | + int level = backlight_get_brightness(bd); | |
| 2229 | 2223 | |
| 2230 | 2224 | reg |= (BLMOD_EN | BIASMOD_EN); |
| 2231 | 2225 | if (level > 0) { |
| @@ -57,11 +57,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) · 56 unmodified lines | ||
| 57 | 57 | * backlight. This provides some greater power saving and the display |
| 58 | 58 | * is useless without backlight anyway. |
| 59 | 59 | */ |
| 60 | − if (bd->props.power != FB_BLANK_UNBLANK || | |
| 61 | − bd->props.fb_blank != FB_BLANK_UNBLANK) | |
| 62 | − level = 0; | |
| 63 | − else | |
| 64 | − level = bd->props.brightness; | |
| 60 | + level = backlight_get_brightness(bd); | |
| 65 | 61 | |
| 66 | 62 | del_timer_sync(&rinfo->lvds_timer); |
| 67 | 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 | 2495 | h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) |
| 2496 | 2496 | return -EINVAL; |
| 2497 | 2497 | |
| 2498 | + if (font->width > 32 || font->height > 32) | |
| 2499 | + return -EINVAL; | |
| 2500 | + | |
| 2498 | 2501 | /* Make sure drawing engine can handle the font */ |
| 2499 | − if (!(info->pixmap.blit_x & (1 << (font->width - 1))) || | |
| 2500 | − !(info->pixmap.blit_y & (1 << (font->height - 1)))) | |
| 2502 | + if (!(info->pixmap.blit_x & BIT(font->width - 1)) || | |
| 2503 | + !(info->pixmap.blit_y & BIT(font->height - 1))) | |
| 2501 | 2504 | return -EINVAL; |
| 2502 | 2505 | |
| 2503 | 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 | 1054 | * @hfreq: horizontal freq |
| 1055 | 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 | 283 | static int mx3fb_bl_update_status(struct backlight_device *bl) |
| 284 | 284 | { |
| 285 | 285 | struct mx3fb_data *fbd = bl_get_data(bl); |
| 286 | − int brightness = bl->props.brightness; | |
| 287 | − | |
| 288 | − if (bl->props.power != FB_BLANK_UNBLANK) | |
| 289 | − brightness = 0; | |
| 290 | − if (bl->props.fb_blank != FB_BLANK_UNBLANK) | |
| 291 | − brightness = 0; | |
| 286 | + int brightness = backlight_get_brightness(bl); | |
| 292 | 287 | |
| 293 | 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 | 50 | struct nvidia_par *par = bl_get_data(bd); |
| 51 | 51 | u32 tmp_pcrt, tmp_pmc, fpcontrol; |
| 52 | − int level; | |
| 52 | + int level = backlight_get_brightness(bd); | |
| 53 | 53 | |
| 54 | 54 | if (!par->FlatPanel) |
| 55 | 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 | 57 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; |
| 64 | 58 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; |
| 65 | 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 | 331 | struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); |
| 332 | 332 | struct omap_dss_device *in = ddata->in; |
| 333 | 333 | int r; |
| 334 | − int level; | |
| 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; | |
| 334 | + int level = backlight_get_brightness(dev); | |
| 341 | 335 | |
| 342 | 336 | dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level); |
| 343 | 337 | |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #define DSS_SUBSYS_NAME "DISPLAY" |
| 11 | 11 | |
| 12 | 12 | #include <linux/kernel.h> |
| 13 | +#include <linux/kstrtox.h> | |
| 13 | 14 | #include <linux/module.h> |
| 14 | 15 | #include <linux/platform_device.h> |
| 15 | 16 | #include <linux/sysfs.h> |
| @@ -36,7 +37,7 @@ static ssize_t display_enabled_store(struct omap_dss_device *dssdev, · 20 unmodified lines | ||
| 36 | 37 | int r; |
| 37 | 38 | bool enable; |
| 38 | 39 | |
| 39 | − r = strtobool(buf, &enable); | |
| 40 | + r = kstrtobool(buf, &enable); | |
| 40 | 41 | if (r) |
| 41 | 42 | return r; |
| 42 | 43 | |
| @@ -73,7 +74,7 @@ static ssize_t display_tear_store(struct omap_dss_device *dssdev, · 30 unmodified lines | ||
| 73 | 74 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
| 74 | 75 | return -ENOENT; |
| 75 | 76 | |
| 76 | − r = strtobool(buf, &te); | |
| 77 | + r = kstrtobool(buf, &te); | |
| 77 | 78 | if (r) |
| 78 | 79 | return r; |
| 79 | 80 | |
| @@ -183,7 +184,7 @@ static ssize_t display_mirror_store(struct omap_dss_device *dssdev, · 103 unmodified lines | ||
| 183 | 184 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
| 184 | 185 | return -ENOENT; |
| 185 | 186 | |
| 186 | − r = strtobool(buf, &mirror); | |
| 187 | + r = kstrtobool(buf, &mirror); | |
| 187 | 188 | if (r) |
| 188 | 189 | return r; |
| 189 | 190 | |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #define DSS_SUBSYS_NAME "MANAGER" |
| 11 | 11 | |
| 12 | 12 | #include <linux/kernel.h> |
| 13 | +#include <linux/kstrtox.h> | |
| 13 | 14 | #include <linux/slab.h> |
| 14 | 15 | #include <linux/module.h> |
| 15 | 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 | 247 | bool enable; |
| 247 | 248 | int r; |
| 248 | 249 | |
| 249 | − r = strtobool(buf, &enable); | |
| 250 | + r = kstrtobool(buf, &enable); | |
| 250 | 251 | if (r) |
| 251 | 252 | return r; |
| 252 | 253 | |
| @@ -290,7 +291,7 @@ static ssize_t manager_alpha_blending_enabled_store( · 37 unmodified lines | ||
| 290 | 291 | if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
| 291 | 292 | return -ENODEV; |
| 292 | 293 | |
| 293 | − r = strtobool(buf, &enable); | |
| 294 | + r = kstrtobool(buf, &enable); | |
| 294 | 295 | if (r) |
| 295 | 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 | 330 | if (!dss_has_feature(FEAT_CPR)) |
| 330 | 331 | return -ENODEV; |
| 331 | 332 | |
| 332 | − r = strtobool(buf, &enable); | |
| 333 | + r = kstrtobool(buf, &enable); | |
| 333 | 334 | if (r) |
| 334 | 335 | return r; |
| 335 | 336 | |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/err.h> |
| 14 | 14 | #include <linux/sysfs.h> |
| 15 | 15 | #include <linux/kobject.h> |
| 16 | +#include <linux/kstrtox.h> | |
| 16 | 17 | #include <linux/platform_device.h> |
| 17 | 18 | |
| 18 | 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 | 211 | int r; |
| 211 | 212 | bool enable; |
| 212 | 213 | |
| 213 | − r = strtobool(buf, &enable); | |
| 214 | + r = kstrtobool(buf, &enable); | |
| 214 | 215 | if (r) |
| 215 | 216 | return r; |
| 216 | 217 | |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/uaccess.h> |
| 16 | 16 | #include <linux/platform_device.h> |
| 17 | 17 | #include <linux/kernel.h> |
| 18 | +#include <linux/kstrtox.h> | |
| 18 | 19 | #include <linux/mm.h> |
| 19 | 20 | #include <linux/omapfb.h> |
| 20 | 21 | |
| @@ -96,7 +97,7 @@ static ssize_t store_mirror(struct device *dev, · 75 unmodified lines | ||
| 96 | 97 | int r; |
| 97 | 98 | struct fb_var_screeninfo new_var; |
| 98 | 99 | |
| 99 | − r = strtobool(buf, &mirror); | |
| 100 | + r = kstrtobool(buf, &mirror); | |
| 100 | 101 | if (r) |
| 101 | 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 | 294 | struct riva_par *par = bl_get_data(bd); |
| 295 | 295 | U032 tmp_pcrt, tmp_pmc; |
| 296 | − int level; | |
| 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; | |
| 296 | + int level = backlight_get_brightness(bd); | |
| 303 | 297 | |
| 304 | 298 | tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF; |
| 305 | 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 | 1426 | u32 bio_size = 0; |
| 1427 | 1427 | struct bio_vec *bvec; |
| 1428 | 1428 | struct bvec_iter_all iter_all; |
| 1429 | + int i; | |
| 1429 | 1430 | |
| 1430 | 1431 | bio_for_each_segment_all(bvec, bio, iter_all) |
| 1431 | 1432 | bio_size += bvec->bv_len; |
| 1432 | 1433 | |
| 1433 | − bitmap_set(rbio->error_bitmap, total_sector_nr, | |
| 1434 | − bio_size >> rbio->bioc->fs_info->sectorsize_bits); | |
| 1434 | + /* | |
| 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 | 1445 | /* Verify the data sectors at read time. */ |
| @@ -1886,7 +1894,7 @@ pstripe: · 448 unmodified lines | ||
| 1886 | 1894 | sector->uptodate = 1; |
| 1887 | 1895 | } |
| 1888 | 1896 | if (failb >= 0) { |
| 1889 | − ret = verify_one_sector(rbio, faila, sector_nr); | |
| 1897 | + ret = verify_one_sector(rbio, failb, sector_nr); | |
| 1890 | 1898 | if (ret < 0) |
| 1891 | 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 | 8074 | * Check that we don't overflow at later allocations, we request |
| 8075 | 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 | − ULONG_MAX / sizeof(struct clone_root) - 1) { | |
| 8079 | + if (arg->clone_sources_count > SZ_8M / sizeof(struct clone_root)) { | |
| 8080 | 8080 | ret = -EINVAL; |
| 8081 | 8081 | goto out; |
| 8082 | 8082 | } |
| @@ -1600,7 +1600,7 @@ again: · 1599 unmodified lines | ||
| 1600 | 1600 | if (ret < 0) |
| 1601 | 1601 | goto out; |
| 1602 | 1602 | |
| 1603 | − while (1) { | |
| 1603 | + while (search_start < search_end) { | |
| 1604 | 1604 | l = path->nodes[0]; |
| 1605 | 1605 | slot = path->slots[0]; |
| 1606 | 1606 | if (slot >= btrfs_header_nritems(l)) { |
| @@ -1623,6 +1623,9 @@ again: · 16 unmodified lines | ||
| 1623 | 1623 | if (key.type != BTRFS_DEV_EXTENT_KEY) |
| 1624 | 1624 | goto next; |
| 1625 | 1625 | |
| 1626 | + if (key.offset > search_end) | |
| 1627 | + break; | |
| 1628 | + | |
| 1626 | 1629 | if (key.offset > search_start) { |
| 1627 | 1630 | hole_size = key.offset - search_start; |
| 1628 | 1631 | dev_extent_hole_check(device, &search_start, &hole_size, |
| @@ -1683,6 +1686,7 @@ next: · 54 unmodified lines | ||
| 1683 | 1686 | else |
| 1684 | 1687 | ret = 0; |
| 1685 | 1688 | |
| 1689 | + ASSERT(max_hole_start + max_hole_size <= search_end); | |
| 1686 | 1690 | out: |
| 1687 | 1691 | btrfs_free_path(path); |
| 1688 | 1692 | *start = max_hole_start; |
| @@ -63,7 +63,7 @@ struct list_head *zlib_alloc_workspace(unsigned int level) · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), |
| 65 | 65 | zlib_inflate_workspacesize()); |
| 66 | − workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL); | |
| 66 | + workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL); | |
| 67 | 67 | workspace->level = level; |
| 68 | 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 | 305 | struct inode *inode = rreq->inode; |
| 306 | 306 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 307 | 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 | 309 | struct ceph_vino vino = ceph_vino(inode); |
| 310 | 310 | struct iov_iter iter; |
| 311 | 311 | struct page **pages; |
| @@ -313,6 +313,11 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) · 1 unmodified line | ||
| 313 | 313 | int err = 0; |
| 314 | 314 | u64 len = subreq->len; |
| 315 | 315 | |
| 316 | + if (ceph_inode_is_shutdown(inode)) { | |
| 317 | + err = -EIO; | |
| 318 | + goto out; | |
| 319 | + } | |
| 320 | + | |
| 316 | 321 | if (ceph_has_inline_data(ci) && ceph_netfs_issue_op_inline(subreq)) |
| 317 | 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 | 569 | dout("writepage %p idx %lu\n", page, page->index); |
| 565 | 570 | |
| 571 | + if (ceph_inode_is_shutdown(inode)) | |
| 572 | + return -EIO; | |
| 573 | + | |
| 566 | 574 | /* verify this is a writeable snap context */ |
| 567 | 575 | snapc = page_snap_context(page); |
| 568 | 576 | if (!snapc) { |
| @@ -1643,7 +1651,7 @@ int ceph_uninline_data(struct file *file) · 1074 unmodified lines | ||
| 1643 | 1651 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1644 | 1652 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 1645 | 1653 | struct ceph_osd_request *req = NULL; |
| 1646 | − struct ceph_cap_flush *prealloc_cf; | |
| 1654 | + struct ceph_cap_flush *prealloc_cf = NULL; | |
| 1647 | 1655 | struct folio *folio = NULL; |
| 1648 | 1656 | u64 inline_version = CEPH_INLINE_NONE; |
| 1649 | 1657 | struct page *pages[1]; |
| @@ -1657,6 +1665,11 @@ int ceph_uninline_data(struct file *file) · 7 unmodified lines | ||
| 1657 | 1665 | dout("uninline_data %p %llx.%llx inline_version %llu\n", |
| 1658 | 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 | 1673 | if (inline_version == CEPH_INLINE_NONE) |
| 1661 | 1674 | return 0; |
| 1662 | 1675 | |
| @@ -4078,6 +4078,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 4077 unmodified lines | ||
| 4078 | 4078 | void *p, *end; |
| 4079 | 4079 | struct cap_extra_info extra_info = {}; |
| 4080 | 4080 | bool queue_trunc; |
| 4081 | + bool close_sessions = false; | |
| 4081 | 4082 | |
| 4082 | 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 | 4216 | realm = NULL; |
| 4216 | 4217 | if (snaptrace_len) { |
| 4217 | 4218 | down_write(&mdsc->snap_rwsem); |
| 4218 | − ceph_update_snap_trace(mdsc, snaptrace, | |
| 4219 | − snaptrace + snaptrace_len, | |
| 4220 | − false, &realm); | |
| 4219 | + if (ceph_update_snap_trace(mdsc, snaptrace, | |
| 4220 | + snaptrace + snaptrace_len, | |
| 4221 | + false, &realm)) { | |
| 4222 | + up_write(&mdsc->snap_rwsem); | |
| 4223 | + close_sessions = true; | |
| 4224 | + goto done; | |
| 4225 | + } | |
| 4221 | 4226 | downgrade_write(&mdsc->snap_rwsem); |
| 4222 | 4227 | } else { |
| 4223 | 4228 | down_read(&mdsc->snap_rwsem); |
| @@ -4277,6 +4282,11 @@ done_unlocked: · 53 unmodified lines | ||
| 4277 | 4282 | iput(inode); |
| 4278 | 4283 | out: |
| 4279 | 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 | 4290 | return; |
| 4281 | 4291 | |
| 4282 | 4292 | flush_cap_releases: |
| @@ -2011,6 +2011,9 @@ static int ceph_zero_partial_object(struct inode *inode, · 2010 unmodified lines | ||
| 2011 | 2011 | loff_t zero = 0; |
| 2012 | 2012 | int op; |
| 2013 | 2013 | |
| 2014 | + if (ceph_inode_is_shutdown(inode)) | |
| 2015 | + return -EIO; | |
| 2016 | + | |
| 2014 | 2017 | if (!length) { |
| 2015 | 2018 | op = offset ? CEPH_OSD_OP_DELETE : CEPH_OSD_OP_TRUNCATE; |
| 2016 | 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 | 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 | 812 | if (mds >= mdsc->mdsmap->possible_max_rank) |
| 810 | 813 | return ERR_PTR(-EINVAL); |
| 811 | 814 | |
| @@ -1478,6 +1481,9 @@ static int __open_session(struct ceph_mds_client *mdsc, · 666 unmodified lines | ||
| 1478 | 1481 | int mstate; |
| 1479 | 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 | 1487 | /* wait for mds to go active? */ |
| 1482 | 1488 | mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds); |
| 1483 | 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 | 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 | 2874 | if (req->r_timeout && |
| 2864 | 2875 | time_after_eq(jiffies, req->r_started + req->r_timeout)) { |
| 2865 | 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 | 3256 | u64 tid; |
| 3246 | 3257 | int err, result; |
| 3247 | 3258 | int mds = session->s_mds; |
| 3259 | + bool close_sessions = false; | |
| 3248 | 3260 | |
| 3249 | 3261 | if (msg->front.iov_len < sizeof(*head)) { |
| 3250 | 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 | 3363 | realm = NULL; |
| 3352 | 3364 | if (rinfo->snapblob_len) { |
| 3353 | 3365 | down_write(&mdsc->snap_rwsem); |
| 3354 | − ceph_update_snap_trace(mdsc, rinfo->snapblob, | |
| 3366 | + err = ceph_update_snap_trace(mdsc, rinfo->snapblob, | |
| 3355 | 3367 | rinfo->snapblob + rinfo->snapblob_len, |
| 3356 | 3368 | le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP, |
| 3357 | 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 | 3377 | downgrade_write(&mdsc->snap_rwsem); |
| 3359 | 3378 | } else { |
| 3360 | 3379 | down_read(&mdsc->snap_rwsem); |
| @@ -3412,6 +3431,10 @@ out_err: · 51 unmodified lines | ||
| 3412 | 3431 | req->r_end_latency, err); |
| 3413 | 3432 | out: |
| 3414 | 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 | 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 | 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 | 5324 | struct ceph_mds_client *mdsc = s->s_mdsc; |
| 5302 | 5325 | |
| 5303 | 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 | 5331 | static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg) |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | #include <linux/ceph/ceph_debug.h> |
| 3 | 3 | |
| 4 | +#include <linux/fs.h> | |
| 4 | 5 | #include <linux/sort.h> |
| 5 | 6 | #include <linux/slab.h> |
| 6 | 7 | #include <linux/iversion.h> |
| @@ -766,8 +767,10 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, · 759 unmodified lines | ||
| 766 | 767 | struct ceph_snap_realm *realm; |
| 767 | 768 | struct ceph_snap_realm *first_realm = NULL; |
| 768 | 769 | struct ceph_snap_realm *realm_to_rebuild = NULL; |
| 770 | + struct ceph_client *client = mdsc->fsc->client; | |
| 769 | 771 | int rebuild_snapcs; |
| 770 | 772 | int err = -ENOMEM; |
| 773 | + int ret; | |
| 771 | 774 | LIST_HEAD(dirty_realms); |
| 772 | 775 | |
| 773 | 776 | lockdep_assert_held_write(&mdsc->snap_rwsem); |
| @@ -884,6 +887,27 @@ fail: · 110 unmodified lines | ||
| 884 | 887 | if (first_realm) |
| 885 | 888 | ceph_put_snap_realm(mdsc, first_realm); |
| 886 | 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 | 911 | return err; |
| 888 | 912 | } |
| 889 | 913 | |
| @@ -984,6 +1008,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, · 94 unmodified lines | ||
| 984 | 1008 | __le64 *split_inos = NULL, *split_realms = NULL; |
| 985 | 1009 | int i; |
| 986 | 1010 | int locked_rwsem = 0; |
| 1011 | + bool close_sessions = false; | |
| 987 | 1012 | |
| 988 | 1013 | /* decode */ |
| 989 | 1014 | if (msg->front.iov_len < sizeof(*h)) |
| @@ -1092,8 +1117,12 @@ skip_inode: · 102 unmodified lines | ||
| 1092 | 1117 | * update using the provided snap trace. if we are deleting a |
| 1093 | 1118 | * snap, we can avoid queueing cap_snaps. |
| 1094 | 1119 | */ |
| 1095 | − ceph_update_snap_trace(mdsc, p, e, | |
| 1096 | − op == CEPH_SNAP_OP_DESTROY, NULL); | |
| 1120 | + if (ceph_update_snap_trace(mdsc, p, e, | |
| 1121 | + op == CEPH_SNAP_OP_DESTROY, | |
| 1122 | + NULL)) { | |
| 1123 | + close_sessions = true; | |
| 1124 | + goto bad; | |
| 1125 | + } | |
| 1097 | 1126 | |
| 1098 | 1127 | if (op == CEPH_SNAP_OP_SPLIT) |
| 1099 | 1128 | /* we took a reference when we created the realm, above */ |
| @@ -1112,6 +1141,9 @@ bad: · 12 unmodified lines | ||
| 1112 | 1141 | out: |
| 1113 | 1142 | if (locked_rwsem) |
| 1114 | 1143 | up_write(&mdsc->snap_rwsem); |
| 1144 | + | |
| 1145 | + if (close_sessions) | |
| 1146 | + ceph_mdsc_close_sessions(mdsc); | |
| 1115 | 1147 | return; |
| 1116 | 1148 | } |
| 1117 | 1149 | |
| @@ -100,6 +100,17 @@ struct ceph_mount_options { · 99 unmodified lines | ||
| 100 | 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 | 114 | #define CEPH_ASYNC_CREATE_CONFLICT_BITS 8 |
| 104 | 115 | |
| 105 | 116 | struct ceph_fs_client { |
| @@ -3889,7 +3889,7 @@ uncached_fill_pages(struct TCP_Server_Info *server, · 3888 unmodified lines | ||
| 3889 | 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 | 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 | 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 | 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 | 865 | static int dump_emit_page(struct coredump_params *cprm, struct page *page) |
| 842 | 866 | { |
| 843 | 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 | 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 | 898 | int dump_user_range(struct coredump_params *cprm, unsigned long start, |
| 899 | 899 | unsigned long len) |
| 900 | 900 | { |
| @@ -8,7 +8,7 @@ config VXFS_FS · 7 unmodified lines | ||
| 8 | 8 | of SCO UnixWare (and possibly others) and optionally available |
| 9 | 9 | for Sunsoft Solaris, HP-UX and many other operating systems. However |
| 10 | 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 | 12 | tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) |
| 13 | 13 | Currently only readonly access is supported and VxFX versions |
| 14 | 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 | 745 | page = pfn_swap_entry_to_page(swpent); |
| 746 | 746 | } |
| 747 | 747 | if (page) { |
| 748 | − int mapcount = page_mapcount(page); | |
| 749 | − | |
| 750 | − if (mapcount >= 2) | |
| 748 | + if (page_mapcount(page) >= 2 || hugetlb_pmd_shared(pte)) | |
| 751 | 749 | mss->shared_hugetlb += huge_page_size(hstate_vma(vma)); |
| 752 | 750 | else |
| 753 | 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 | 183 | #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ |
| 184 | 184 | sizeof(u64)) |
| 185 | 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 | 188 | #define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \ |
| 189 | 189 | SQUASHFS_METADATA_SIZE) |
| @@ -63,7 +63,7 @@ struct squashfs_sb_info { · 62 unmodified lines | ||
| 63 | 63 | long long bytes_used; |
| 64 | 64 | unsigned int inodes; |
| 65 | 65 | unsigned int fragments; |
| 66 | − int xattr_ids; | |
| 66 | + unsigned int xattr_ids; | |
| 67 | 67 | unsigned int ids; |
| 68 | 68 | bool panic_on_errors; |
| 69 | 69 | const struct squashfs_decompressor_thread_ops *thread_ops; |
| @@ -10,12 +10,12 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #ifdef CONFIG_SQUASHFS_XATTR |
| 12 | 12 | extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64, |
| 13 | − u64 *, int *); | |
| 13 | + u64 *, unsigned int *); | |
| 14 | 14 | extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *, |
| 15 | 15 | unsigned int *, unsigned long long *); |
| 16 | 16 | #else |
| 17 | 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 | 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 | 56 | * Read uncompressed xattr id lookup table indexes from disk into memory |
| 57 | 57 | */ |
| 58 | 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 | 61 | struct squashfs_sb_info *msblk = sb->s_fs_info; |
| 62 | 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 | 76 | /* Sanity check values */ |
| 77 | 77 | |
| 78 | 78 | /* there is always at least one xattr id */ |
| 79 | − if (*xattr_ids == 0) | |
| 79 | + if (*xattr_ids <= 0) | |
| 80 | 80 | return ERR_PTR(-EINVAL); |
| 81 | 81 | |
| 82 | 82 | len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); |
| @@ -263,7 +263,7 @@ struct vgic_dist { · 262 unmodified lines | ||
| 263 | 263 | struct vgic_io_device dist_iodev; |
| 264 | 264 | |
| 265 | 265 | bool has_its; |
| 266 | − bool save_its_tables_in_progress; | |
| 266 | + bool table_write_in_progress; | |
| 267 | 267 | |
| 268 | 268 | /* |
| 269 | 269 | * Contains the attributes and gpa of the LPI configuration table. |
| @@ -99,16 +99,6 @@ struct ceph_options { · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 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 | 102 | static inline unsigned long ceph_timeout_jiffies(unsigned long timeout) |
| 113 | 103 | { |
| 114 | 104 | return timeout ?: MAX_SCHEDULE_TIMEOUT; |
| @@ -668,7 +668,8 @@ extern struct efi { · 667 unmodified lines | ||
| 668 | 668 | |
| 669 | 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 | 673 | #define EFI_RT_SUPPORTED_VARIABLE_SERVICES 0x0070 |
| 673 | 674 | |
| 674 | 675 | extern struct mm_struct efi_mm; |
| @@ -200,7 +200,7 @@ static inline void *kmap_local_pfn(unsigned long pfn) · 199 unmodified lines | ||
| 200 | 200 | static inline void __kunmap_local(const void *addr) |
| 201 | 201 | { |
| 202 | 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 | 204 | #endif |
| 205 | 205 | } |
| 206 | 206 | |
| @@ -227,7 +227,7 @@ static inline void *kmap_atomic_pfn(unsigned long pfn) · 20 unmodified lines | ||
| 227 | 227 | static inline void __kunmap_atomic(const void *addr) |
| 228 | 228 | { |
| 229 | 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 | 231 | #endif |
| 232 | 232 | pagefault_enable(); |
| 233 | 233 | if (IS_ENABLED(CONFIG_PREEMPT_RT)) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/fs.h> |
| 8 | 8 | #include <linux/hugetlb_inline.h> |
| 9 | 9 | #include <linux/cgroup.h> |
| 10 | +#include <linux/page_ref.h> | |
| 10 | 11 | #include <linux/list.h> |
| 11 | 12 | #include <linux/kref.h> |
| 12 | 13 | #include <linux/pgtable.h> |
| @@ -1187,6 +1188,18 @@ static inline __init void hugetlb_cma_reserve(int order) · 1174 unmodified lines | ||
| 1187 | 1188 | } |
| 1188 | 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 | 1203 | bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr); |
| 1191 | 1204 | |
| 1192 | 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 | 1666 | static inline void mem_cgroup_track_foreign_dirty(struct folio *folio, |
| 1667 | 1667 | struct bdi_writeback *wb) |
| 1668 | 1668 | { |
| 1669 | + struct mem_cgroup *memcg; | |
| 1670 | + | |
| 1669 | 1671 | if (mem_cgroup_disabled()) |
| 1670 | 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 | 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 | 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 | 583 | struct mlx5_ft_pool; |
| 576 | 584 | struct mlx5_priv { |
| 577 | 585 | /* IRQ table valid only for real pci devices PF or VF */ |
| @@ -582,11 +590,10 @@ struct mlx5_priv { · 4 unmodified lines | ||
| 582 | 590 | struct mlx5_nb pg_nb; |
| 583 | 591 | struct workqueue_struct *pg_wq; |
| 584 | 592 | struct xarray page_root_xa; |
| 585 | − u32 fw_pages; | |
| 586 | 593 | atomic_t reg_pages; |
| 587 | 594 | struct list_head free_list; |
| 588 | − u32 vfs_pages; | |
| 589 | − u32 host_pf_pages; | |
| 595 | + u32 fw_pages; | |
| 596 | + u32 page_counters[MLX5_FUNC_TYPE_NUM]; | |
| 590 | 597 | u32 fw_pages_alloc_failed; |
| 591 | 598 | u32 give_pages_dropped; |
| 592 | 599 | u32 reclaim_pages_discard; |
| @@ -70,7 +70,6 @@ struct nvmem_keepout { · 69 unmodified lines | ||
| 70 | 70 | * @word_size: Minimum read/write access granularity. |
| 71 | 71 | * @stride: Minimum read/write access stride. |
| 72 | 72 | * @priv: User context passed to read/write callbacks. |
| 73 | − * @wp-gpio: Write protect pin | |
| 74 | 73 | * @ignore_wp: Write Protect pin is managed by the provider. |
| 75 | 74 | * |
| 76 | 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 | 84 | const char *name; |
| 86 | 85 | int id; |
| 87 | 86 | struct module *owner; |
| 88 | − struct gpio_desc *wp_gpio; | |
| 89 | 87 | const struct nvmem_cell_info *cells; |
| 90 | 88 | int ncells; |
| 91 | 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 | 476 | #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ |
| 477 | 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 | 488 | int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, |
| 480 | 489 | size_t max_size, unsigned int cpu_mult, |
| 481 | 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 | 418 | extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, |
| 419 | 419 | unsigned long nr_pages, |
| 420 | 420 | gfp_t gfp_mask, |
| 421 | − unsigned int reclaim_options, | |
| 422 | − nodemask_t *nodemask); | |
| 421 | + unsigned int reclaim_options); | |
| 423 | 422 | extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem, |
| 424 | 423 | gfp_t gfp_mask, bool noswap, |
| 425 | 424 | pg_data_t *pgdat, |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #ifndef _UAPI_LINUX_IP_H |
| 19 | 19 | #define _UAPI_LINUX_IP_H |
| 20 | 20 | #include <linux/types.h> |
| 21 | +#include <linux/stddef.h> | |
| 21 | 22 | #include <asm/byteorder.h> |
| 22 | 23 | |
| 23 | 24 | #define IPTOS_TOS_MASK 0x1E |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include <linux/libc-compat.h> |
| 6 | 6 | #include <linux/types.h> |
| 7 | +#include <linux/stddef.h> | |
| 7 | 8 | #include <linux/in6.h> |
| 8 | 9 | #include <asm/byteorder.h> |
| 9 | 10 | |
| @@ -1205,12 +1205,13 @@ void rebuild_sched_domains(void) · 1204 unmodified lines | ||
| 1205 | 1205 | /** |
| 1206 | 1206 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. |
| 1207 | 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 | 1210 | * Iterate through each task of @cs updating its cpus_allowed to the |
| 1210 | 1211 | * effective cpuset's. As this function is called with cpuset_rwsem held, |
| 1211 | 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 | 1216 | struct css_task_iter it; |
| 1216 | 1217 | struct task_struct *task; |
| @@ -1224,7 +1225,10 @@ static void update_tasks_cpumask(struct cpuset *cs) · 7 unmodified lines | ||
| 1224 | 1225 | if (top_cs && (task->flags & PF_KTHREAD) && |
| 1225 | 1226 | kthread_is_per_cpu(task)) |
| 1226 | 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 | 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 | 1513 | spin_unlock_irq(&callback_lock); |
| 1510 | 1514 | |
| 1511 | 1515 | if (adding || deleting) |
| 1512 | − update_tasks_cpumask(parent); | |
| 1516 | + update_tasks_cpumask(parent, tmp->new_cpus); | |
| 1513 | 1517 | |
| 1514 | 1518 | /* |
| 1515 | 1519 | * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary. |
| @@ -1661,7 +1665,7 @@ update_parent_subparts: · 145 unmodified lines | ||
| 1661 | 1665 | WARN_ON(!is_in_v2_mode() && |
| 1662 | 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 | 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 | 2318 | if (parent->child_ecpus_count) |
| 2315 | 2319 | update_sibling_cpumasks(parent, cs, &tmpmask); |
| @@ -3348,7 +3352,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs, · 1032 unmodified lines | ||
| 3348 | 3352 | * as the tasks will be migrated to an ancestor. |
| 3349 | 3353 | */ |
| 3350 | 3354 | if (cpus_updated && !cpumask_empty(cs->cpus_allowed)) |
| 3351 | − update_tasks_cpumask(cs); | |
| 3355 | + update_tasks_cpumask(cs, new_cpus); | |
| 3352 | 3356 | if (mems_updated && !nodes_empty(cs->mems_allowed)) |
| 3353 | 3357 | update_tasks_nodemask(cs); |
| 3354 | 3358 | |
| @@ -3385,7 +3389,7 @@ hotplug_update_tasks(struct cpuset *cs, · 30 unmodified lines | ||
| 3385 | 3389 | spin_unlock_irq(&callback_lock); |
| 3386 | 3390 | |
| 3387 | 3391 | if (cpus_updated) |
| 3388 | − update_tasks_cpumask(cs); | |
| 3392 | + update_tasks_cpumask(cs, new_cpus); | |
| 3389 | 3393 | if (mems_updated) |
| 3390 | 3394 | update_tasks_nodemask(cs); |
| 3391 | 3395 | } |
| @@ -3692,15 +3696,38 @@ void __init cpuset_init_smp(void) · 300 unmodified lines | ||
| 3692 | 3696 | * Description: Returns the cpumask_var_t cpus_allowed of the cpuset |
| 3693 | 3697 | * attached to the specified @tsk. Guaranteed to return some non-empty |
| 3694 | 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 | 3702 | void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) |
| 3699 | 3703 | { |
| 3700 | 3704 | unsigned long flags; |
| 3705 | + struct cpuset *cs; | |
| 3701 | 3706 | |
| 3702 | 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 | 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 | 4814 | cpc = per_cpu_ptr(pmu->cpu_pmu_context, event->cpu); |
| 4815 | 4815 | epc = &cpc->epc; |
| 4816 | − | |
| 4816 | + raw_spin_lock_irq(&ctx->lock); | |
| 4817 | 4817 | if (!epc->ctx) { |
| 4818 | 4818 | atomic_set(&epc->refcount, 1); |
| 4819 | 4819 | epc->embedded = 1; |
| 4820 | − raw_spin_lock_irq(&ctx->lock); | |
| 4821 | 4820 | list_add(&epc->pmu_ctx_entry, &ctx->pmu_ctx_list); |
| 4822 | 4821 | epc->ctx = ctx; |
| 4823 | − raw_spin_unlock_irq(&ctx->lock); | |
| 4824 | 4822 | } else { |
| 4825 | 4823 | WARN_ON_ONCE(epc->ctx != ctx); |
| 4826 | 4824 | atomic_inc(&epc->refcount); |
| 4827 | 4825 | } |
| 4828 | − | |
| 4826 | + raw_spin_unlock_irq(&ctx->lock); | |
| 4829 | 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 | 4895 | static void put_pmu_ctx(struct perf_event_pmu_context *epc) |
| 4898 | 4896 | { |
| 4897 | + struct perf_event_context *ctx = epc->ctx; | |
| 4899 | 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 | 4909 | return; |
| 4903 | 4910 | |
| 4904 | − if (epc->ctx) { | |
| 4905 | − struct perf_event_context *ctx = epc->ctx; | |
| 4911 | + WARN_ON_ONCE(list_empty(&epc->pmu_ctx_entry)); | |
| 4906 | 4912 | |
| 4907 | − /* | |
| 4908 | − * XXX | |
| 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 | − } | |
| 4913 | + list_del_init(&epc->pmu_ctx_entry); | |
| 4914 | + epc->ctx = NULL; | |
| 4922 | 4915 | |
| 4923 | 4916 | WARN_ON_ONCE(!list_empty(&epc->pinned_active)); |
| 4924 | 4917 | WARN_ON_ONCE(!list_empty(&epc->flexible_active)); |
| 4925 | 4918 | |
| 4919 | + raw_spin_unlock_irqrestore(&ctx->lock, flags); | |
| 4920 | + | |
| 4926 | 4921 | if (epc->embedded) |
| 4927 | 4922 | return; |
| 4928 | 4923 | |
| @@ -1915,7 +1915,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d) · 1914 unmodified lines | ||
| 1915 | 1915 | |
| 1916 | 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 | 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 | 9148 | if (val > 100) |
| 9149 | 9149 | return -EINVAL; |
| 9150 | 9150 | |
| 9151 | − if (!val) | |
| 9152 | − val = 1; | |
| 9153 | − | |
| 9154 | 9151 | tr->buffer_percent = val; |
| 9155 | 9152 | |
| 9156 | 9153 | (*ppos)++; |
| @@ -763,6 +763,7 @@ config DEBUG_KMEMLEAK · 762 unmodified lines | ||
| 763 | 763 | select KALLSYMS |
| 764 | 764 | select CRC32 |
| 765 | 765 | select STACKDEPOT |
| 766 | + select STACKDEPOT_ALWAYS_INIT if !DEBUG_KMEMLEAK_DEFAULT_OFF | |
| 766 | 767 | help |
| 767 | 768 | Say Y here if you want to enable the memory leak |
| 768 | 769 | detector. The memory allocation/freeing is traced in a way |
| @@ -1216,7 +1217,7 @@ config SCHED_DEBUG · 447 unmodified lines | ||
| 1216 | 1217 | depends on DEBUG_KERNEL && PROC_FS |
| 1217 | 1218 | default y |
| 1218 | 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 | 1221 | that can help debug the scheduler. The runtime overhead of this |
| 1221 | 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 | 49 | return 0; |
| 50 | 50 | } |
| 51 | 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 | 670 | unsigned char piv) |
| 671 | 671 | { |
| 672 | 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 | 676 | WARN_ON(1); |
| 676 | 677 | return 0; |
| 677 | 678 | } |
| 678 | − switch (mte_node_type(mn)) { | |
| 679 | + switch (type) { | |
| 679 | 680 | case maple_arange_64: |
| 680 | 681 | return node->ma64.pivot[piv]; |
| 681 | 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 | 4888 | unsigned long *pivots, *gaps; |
| 4888 | 4889 | void __rcu **slots; |
| 4889 | 4890 | unsigned long gap = 0; |
| 4890 | − unsigned long max, min, index; | |
| 4891 | + unsigned long max, min; | |
| 4891 | 4892 | unsigned char offset; |
| 4892 | 4893 | |
| 4893 | 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 | 4910 | min = mas_safe_min(mas, pivots, --offset); |
| 4910 | 4911 | |
| 4911 | 4912 | max = mas_safe_pivot(mas, pivots, offset, type); |
| 4912 | − index = mas->index; | |
| 4913 | − while (index <= max) { | |
| 4913 | + while (mas->index <= max) { | |
| 4914 | 4914 | gap = 0; |
| 4915 | 4915 | if (gaps) |
| 4916 | 4916 | gap = gaps[offset]; |
| @@ -4941,10 +4941,8 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 24 unmodified lines | ||
| 4941 | 4941 | min = mas_safe_min(mas, pivots, offset); |
| 4942 | 4942 | } |
| 4943 | 4943 | |
| 4944 | − if (unlikely(index > max)) { | |
| 4945 | − mas_set_err(mas, -EBUSY); | |
| 4946 | − return false; | |
| 4947 | − } | |
| 4944 | + if (unlikely((mas->index > max) || (size - 1 > max - mas->index))) | |
| 4945 | + goto no_space; | |
| 4948 | 4946 | |
| 4949 | 4947 | if (unlikely(ma_is_leaf(type))) { |
| 4950 | 4948 | mas->offset = offset; |
| @@ -4961,9 +4959,11 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size) · 10 unmodified lines | ||
| 4961 | 4959 | return false; |
| 4962 | 4960 | |
| 4963 | 4961 | ascend: |
| 4964 | − if (mte_is_root(mas->node)) | |
| 4965 | − mas_set_err(mas, -EBUSY); | |
| 4962 | + if (!mte_is_root(mas->node)) | |
| 4963 | + return false; | |
| 4966 | 4964 | |
| 4965 | +no_space: | |
| 4966 | + mas_set_err(mas, -EBUSY); | |
| 4967 | 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 | 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 | 2605 | static DEFINE_MTREE(tree); |
| 2521 | 2606 | static int maple_tree_seed(void) |
| 2522 | 2607 | { |
| @@ -2765,6 +2850,10 @@ static int maple_tree_seed(void) · 242 unmodified lines | ||
| 2765 | 2850 | check_bnode_min_spanning(&tree); |
| 2766 | 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 | 2857 | #if defined(BENCH) |
| 2769 | 2858 | skip: |
| 2770 | 2859 | #endif |
| @@ -5051,6 +5051,9 @@ again: · 5050 unmodified lines | ||
| 5051 | 5051 | entry = huge_pte_clear_uffd_wp(entry); |
| 5052 | 5052 | set_huge_pte_at(dst, addr, dst_pte, entry); |
| 5053 | 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 | 5058 | * We copy the pte marker only if the dst vma has |
| 5056 | 5059 | * uffd-wp enabled. |
| @@ -847,6 +847,10 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address, · 846 unmodified lines | ||
| 847 | 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 | 854 | static int find_pmd_or_thp_or_none(struct mm_struct *mm, |
| 851 | 855 | unsigned long address, |
| 852 | 856 | pmd_t **pmd) |
| @@ -865,8 +869,12 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm, · 12 unmodified lines | ||
| 865 | 869 | #endif |
| 866 | 870 | if (pmd_none(pmde)) |
| 867 | 871 | return SCAN_PMD_NONE; |
| 872 | + if (!pmd_present(pmde)) | |
| 873 | + return SCAN_PMD_NULL; | |
| 868 | 874 | if (pmd_trans_huge(pmde)) |
| 869 | 875 | return SCAN_PMD_MAPPED; |
| 876 | + if (pmd_devmap(pmde)) | |
| 877 | + return SCAN_PMD_NULL; | |
| 870 | 878 | if (pmd_bad(pmde)) |
| 871 | 879 | return SCAN_PMD_NULL; |
| 872 | 880 | return SCAN_SUCCEED; |
| @@ -1642,7 +1650,7 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff, · 769 unmodified lines | ||
| 1642 | 1650 | * has higher cost too. It would also probably require locking |
| 1643 | 1651 | * the anon_vma. |
| 1644 | 1652 | */ |
| 1645 | − if (vma->anon_vma) { | |
| 1653 | + if (READ_ONCE(vma->anon_vma)) { | |
| 1646 | 1654 | result = SCAN_PAGE_ANON; |
| 1647 | 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 | 1678 | result = SCAN_PTE_MAPPED_HUGEPAGE; |
| 1671 | 1679 | if ((cc->is_khugepaged || is_target) && |
| 1672 | 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 | 1694 | * When a vma is registered with uffd-wp, we can't |
| 1675 | 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 | 2070 | return -EINVAL; |
| 2071 | 2071 | if (strcmp(str, "off") == 0) |
| 2072 | 2072 | kmemleak_disable(); |
| 2073 | − else if (strcmp(str, "on") == 0) | |
| 2073 | + else if (strcmp(str, "on") == 0) { | |
| 2074 | 2074 | kmemleak_skip_disable = 1; |
| 2075 | + stack_depot_want_early_init(); | |
| 2076 | + } | |
| 2075 | 2077 | else |
| 2076 | 2078 | return -EINVAL; |
| 2077 | 2079 | return 0; |
| @@ -2093,7 +2095,6 @@ void __init kmemleak_init(void) · 15 unmodified lines | ||
| 2093 | 2095 | if (kmemleak_error) |
| 2094 | 2096 | return; |
| 2095 | 2097 | |
| 2096 | − stack_depot_init(); | |
| 2097 | 2098 | jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE); |
| 2098 | 2099 | jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000); |
| 2099 | 2100 | |
| @@ -63,7 +63,6 @@ · 62 unmodified lines | ||
| 63 | 63 | #include <linux/resume_user_mode.h> |
| 64 | 64 | #include <linux/psi.h> |
| 65 | 65 | #include <linux/seq_buf.h> |
| 66 | −#include <linux/parser.h> | |
| 67 | 66 | #include "internal.h" |
| 68 | 67 | #include <net/sock.h> |
| 69 | 68 | #include <net/ip.h> |
| @@ -2393,8 +2392,7 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg, · 2323 unmodified lines | ||
| 2393 | 2392 | psi_memstall_enter(&pflags); |
| 2394 | 2393 | nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages, |
| 2395 | 2394 | gfp_mask, |
| 2396 | − MEMCG_RECLAIM_MAY_SWAP, | |
| 2397 | − NULL); | |
| 2395 | + MEMCG_RECLAIM_MAY_SWAP); | |
| 2398 | 2396 | psi_memstall_leave(&pflags); |
| 2399 | 2397 | } while ((memcg = parent_mem_cgroup(memcg)) && |
| 2400 | 2398 | !mem_cgroup_is_root(memcg)); |
| @@ -2685,8 +2683,7 @@ retry: · 284 unmodified lines | ||
| 2685 | 2683 | |
| 2686 | 2684 | psi_memstall_enter(&pflags); |
| 2687 | 2685 | nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages, |
| 2688 | − gfp_mask, reclaim_options, | |
| 2689 | − NULL); | |
| 2686 | + gfp_mask, reclaim_options); | |
| 2690 | 2687 | psi_memstall_leave(&pflags); |
| 2691 | 2688 | |
| 2692 | 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 | 3505 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, |
| 3509 | − memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP, | |
| 3510 | − NULL)) { | |
| 3506 | + memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP)) { | |
| 3511 | 3507 | ret = -EBUSY; |
| 3512 | 3508 | break; |
| 3513 | 3509 | } |
| @@ -3618,8 +3614,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg) · 104 unmodified lines | ||
| 3618 | 3614 | return -EINTR; |
| 3619 | 3615 | |
| 3620 | 3616 | if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, |
| 3621 | − MEMCG_RECLAIM_MAY_SWAP, | |
| 3622 | − NULL)) | |
| 3617 | + MEMCG_RECLAIM_MAY_SWAP)) | |
| 3623 | 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 | 6426 | reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high, |
| 6432 | − GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP, | |
| 6433 | − NULL); | |
| 6427 | + GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP); | |
| 6434 | 6428 | |
| 6435 | 6429 | if (!reclaimed && !nr_retries--) |
| 6436 | 6430 | break; |
| @@ -6479,8 +6473,7 @@ static ssize_t memory_max_write(struct kernfs_open_file *of, · 42 unmodified lines | ||
| 6479 | 6473 | |
| 6480 | 6474 | if (nr_reclaims) { |
| 6481 | 6475 | if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max, |
| 6482 | − GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP, | |
| 6483 | − NULL)) | |
| 6476 | + GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP)) | |
| 6484 | 6477 | nr_reclaims--; |
| 6485 | 6478 | continue; |
| 6486 | 6479 | } |
| @@ -6603,54 +6596,21 @@ static ssize_t memory_oom_group_write(struct kernfs_open_file *of, · 116 unmodified lines | ||
| 6603 | 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 | 6599 | static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, |
| 6617 | 6600 | size_t nbytes, loff_t off) |
| 6618 | 6601 | { |
| 6619 | 6602 | struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); |
| 6620 | 6603 | unsigned int nr_retries = MAX_RECLAIM_RETRIES; |
| 6621 | 6604 | unsigned long nr_to_reclaim, nr_reclaimed = 0; |
| 6622 | − unsigned int reclaim_options = MEMCG_RECLAIM_MAY_SWAP | | |
| 6623 | − MEMCG_RECLAIM_PROACTIVE; | |
| 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; | |
| 6605 | + unsigned int reclaim_options; | |
| 6606 | + int err; | |
| 6636 | 6607 | |
| 6637 | 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) { | |
| 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 | − | |
| 6613 | + reclaim_options = MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_PROACTIVE; | |
| 6654 | 6614 | while (nr_reclaimed < nr_to_reclaim) { |
| 6655 | 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 | 6628 | reclaimed = try_to_free_mem_cgroup_pages(memcg, |
| 6669 | 6629 | nr_to_reclaim - nr_reclaimed, |
| 6670 | − GFP_KERNEL, reclaim_options, | |
| 6671 | − &nodemask); | |
| 6630 | + GFP_KERNEL, reclaim_options); | |
| 6672 | 6631 | |
| 6673 | 6632 | if (!reclaimed && !nr_retries--) |
| 6674 | 6633 | return -EAGAIN; |
| @@ -828,12 +828,8 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, · 827 unmodified lines | ||
| 828 | 828 | return -EBUSY; |
| 829 | 829 | return -ENOENT; |
| 830 | 830 | } else if (is_pte_marker_entry(entry)) { |
| 831 | − /* | |
| 832 | − * We're copying the pgtable should only because dst_vma has | |
| 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); | |
| 831 | + if (is_swapin_error_entry(entry) || userfaultfd_wp(dst_vma)) | |
| 832 | + set_pte_at(dst_mm, addr, dst_pte, pte); | |
| 837 | 833 | return 0; |
| 838 | 834 | } |
| 839 | 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 | 3626 | * Be careful so that we will only recover a special uffd-wp pte into a |
| 3631 | 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 | 3634 | pte_clear(vmf->vma->vm_mm, vmf->address, vmf->pte); |
| 3635 | 3635 | pte_unmap_unlock(vmf->pte, vmf->ptl); |
| 3636 | 3636 | return 0; |
| @@ -600,7 +600,8 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask, · 599 unmodified lines | ||
| 600 | 600 | |
| 601 | 601 | /* With MPOL_MF_MOVE, we migrate only unshared hugepage. */ |
| 602 | 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 | 605 | if (isolate_hugetlb(page, qp->pagelist) && |
| 605 | 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 | 245 | newpte = pte_swp_mksoft_dirty(newpte); |
| 246 | 246 | if (pte_swp_uffd_wp(oldpte)) |
| 247 | 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 | 256 | * If this is uffd-wp pte marker and we'd like |
| 251 | 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 | |
| 1031 | − * the already existing vma, vma_merge() will merge this extension with | |
| 1032 | − * the already existing vma (expand operation itself) and possibly also | |
| 1033 | − * with the next vma if it becomes adjacent to the expanded vma and | |
| 1034 | − * otherwise compatible. | |
| 1030 | + * Function vma_merge() is called on the extension we | |
| 1031 | + * are adding to the already existing vma, vma_merge() | |
| 1032 | + * will merge this extension with the already existing | |
| 1033 | + * vma (expand operation itself) and possibly also with | |
| 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 | 1046 | vma->vm_flags, vma->anon_vma, vma->vm_file, |
| 1038 | 1047 | extension_pgoff, vma_policy(vma), |
| 1039 | 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 | 1053 | if (!vma) { |
| 1041 | 1054 | vm_unacct_memory(pages); |
| 1042 | 1055 | ret = -ENOMEM; |
| @@ -1100,6 +1100,7 @@ start_over: · 1099 unmodified lines | ||
| 1100 | 1100 | goto check_out; |
| 1101 | 1101 | pr_debug("scan_swap_map of si %d failed to find offset\n", |
| 1102 | 1102 | si->type); |
| 1103 | + cond_resched(); | |
| 1103 | 1104 | |
| 1104 | 1105 | spin_lock(&swap_avail_lock); |
| 1105 | 1106 | nextsi: |
| @@ -3323,13 +3323,16 @@ void lru_gen_migrate_mm(struct mm_struct *mm) · 3322 unmodified lines | ||
| 3323 | 3323 | if (mem_cgroup_disabled()) |
| 3324 | 3324 | return; |
| 3325 | 3325 | |
| 3326 | + /* migration can happen before addition */ | |
| 3327 | + if (!mm->lru_gen.memcg) | |
| 3328 | + return; | |
| 3329 | + | |
| 3326 | 3330 | rcu_read_lock(); |
| 3327 | 3331 | memcg = mem_cgroup_from_task(task); |
| 3328 | 3332 | rcu_read_unlock(); |
| 3329 | 3333 | if (memcg == mm->lru_gen.memcg) |
| 3330 | 3334 | return; |
| 3331 | 3335 | |
| 3332 | − VM_WARN_ON_ONCE(!mm->lru_gen.memcg); | |
| 3333 | 3336 | VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list)); |
| 3334 | 3337 | |
| 3335 | 3338 | lru_gen_del_mm(mm); |
| @@ -6754,8 +6757,7 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg, · 3418 unmodified lines | ||
| 6754 | 6757 | unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, |
| 6755 | 6758 | unsigned long nr_pages, |
| 6756 | 6759 | gfp_t gfp_mask, |
| 6757 | − unsigned int reclaim_options, | |
| 6758 | − nodemask_t *nodemask) | |
| 6760 | + unsigned int reclaim_options) | |
| 6759 | 6761 | { |
| 6760 | 6762 | unsigned long nr_reclaimed; |
| 6761 | 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 | 6772 | .may_unmap = 1, |
| 6771 | 6773 | .may_swap = !!(reclaim_options & MEMCG_RECLAIM_MAY_SWAP), |
| 6772 | 6774 | .proactive = !!(reclaim_options & MEMCG_RECLAIM_PROACTIVE), |
| 6773 | − .nodemask = nodemask, | |
| 6774 | 6775 | }; |
| 6775 | 6776 | /* |
| 6776 | 6777 | * Traverse the ZONELIST_FALLBACK zonelist of the current node to put |
| @@ -113,7 +113,23 @@ · 112 unmodified lines | ||
| 113 | 113 | * have room for two bit at least. |
| 114 | 114 | */ |
| 115 | 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 | 133 | #define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS - OBJ_TAG_BITS) |
| 118 | 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 | 238 | * Handle of allocated object. |
| 223 | 239 | */ |
| 224 | 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 | 294 | /* links the zspage to the lru list in the pool */ |
| 273 | 295 | struct list_head lru; |
| 274 | 296 | bool under_reclaim; |
| 275 | − /* list of unfreed handles whose objects have been reclaimed */ | |
| 276 | − unsigned long *deferred_handles; | |
| 277 | 297 | #endif |
| 278 | 298 | |
| 279 | 299 | struct zs_pool *pool; |
| @@ -897,7 +917,8 @@ static unsigned long handle_to_obj(unsigned long handle) · 617 unmodified lines | ||
| 897 | 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 | 923 | unsigned long handle; |
| 903 | 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 | 929 | } else |
| 909 | 930 | handle = *(unsigned long *)obj; |
| 910 | 931 | |
| 911 | − if (!(handle & OBJ_ALLOCATED_TAG)) | |
| 932 | + if (!(handle & tag)) | |
| 912 | 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 | 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 | 953 | static void reset_page(struct page *page) |
| 919 | 954 | { |
| 920 | 955 | __ClearPageMovable(page); |
| @@ -946,22 +981,36 @@ unlock: · 25 unmodified lines | ||
| 946 | 981 | } |
| 947 | 982 | |
| 948 | 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 | 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) { | |
| 957 | − unsigned long nxt_handle = handle_to_obj(handle); | |
| 997 | + while (1) { | |
| 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 | 1007 | cache_free_handle(pool, handle); |
| 960 | − handle = nxt_handle; | |
| 1008 | + obj_idx++; | |
| 961 | 1009 | } |
| 962 | 1010 | } |
| 963 | 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 | 1014 | #endif |
| 966 | 1015 | |
| 967 | 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 | 1028 | VM_BUG_ON(fg != ZS_EMPTY); |
| 980 | 1029 | |
| 981 | 1030 | /* Free all deferred handles from zs_free */ |
| 982 | − free_handles(pool, zspage); | |
| 1031 | + free_handles(pool, class, zspage); | |
| 983 | 1032 | |
| 984 | 1033 | next = page = get_first_page(zspage); |
| 985 | 1034 | do { |
| @@ -1067,7 +1116,6 @@ static void init_zspage(struct size_class *class, struct zspage *zspage) · 81 unmodified lines | ||
| 1067 | 1116 | #ifdef CONFIG_ZPOOL |
| 1068 | 1117 | INIT_LIST_HEAD(&zspage->lru); |
| 1069 | 1118 | zspage->under_reclaim = false; |
| 1070 | − zspage->deferred_handles = NULL; | |
| 1071 | 1119 | #endif |
| 1072 | 1120 | |
| 1073 | 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 | 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 | 1621 | struct link_free *link; |
| 1574 | 1622 | struct zspage *zspage; |
| @@ -1582,15 +1630,29 @@ static void obj_free(int class_size, unsigned long obj) · 7 unmodified lines | ||
| 1582 | 1630 | zspage = get_zspage(f_page); |
| 1583 | 1631 | |
| 1584 | 1632 | vaddr = kmap_atomic(f_page); |
| 1585 | − | |
| 1586 | − /* Insert this object in containing zspage's freelist */ | |
| 1587 | 1633 | link = (struct link_free *)(vaddr + f_offset); |
| 1588 | − if (likely(!ZsHugePage(zspage))) | |
| 1589 | − link->next = get_freeobj(zspage) << OBJ_TAG_BITS; | |
| 1590 | − else | |
| 1591 | − f_page->index = 0; | |
| 1634 | + | |
| 1635 | + if (handle) { | |
| 1636 | +#ifdef CONFIG_ZPOOL | |
| 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 | 1655 | kunmap_atomic(vaddr); |
| 1593 | − set_freeobj(zspage, f_objidx); | |
| 1594 | 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 | 1677 | zspage = get_zspage(f_page); |
| 1616 | 1678 | class = zspage_class(pool, zspage); |
| 1617 | 1679 | |
| 1618 | − obj_free(class->size, obj); | |
| 1619 | 1680 | class_stat_dec(class, OBJ_USED, 1); |
| 1620 | 1681 | |
| 1621 | 1682 | #ifdef CONFIG_ZPOOL |
| @@ -1624,15 +1685,15 @@ void zs_free(struct zs_pool *pool, unsigned long handle) · 2 unmodified lines | ||
| 1624 | 1685 | * Reclaim needs the handles during writeback. It'll free |
| 1625 | 1686 | * them along with the zspage when it's done with them. |
| 1626 | 1687 | * |
| 1627 | − * Record current deferred handle at the memory location | |
| 1628 | − * whose address is given by handle. | |
| 1688 | + * Record current deferred handle in the object's header. | |
| 1629 | 1689 | */ |
| 1630 | − record_obj(handle, (unsigned long)zspage->deferred_handles); | |
| 1631 | − zspage->deferred_handles = (unsigned long *)handle; | |
| 1690 | + obj_free(class->size, obj, &handle); | |
| 1632 | 1691 | spin_unlock(&pool->lock); |
| 1633 | 1692 | return; |
| 1634 | 1693 | } |
| 1635 | 1694 | #endif |
| 1695 | + obj_free(class->size, obj, NULL); | |
| 1696 | + | |
| 1636 | 1697 | fullness = fix_fullness_group(class, zspage); |
| 1637 | 1698 | if (fullness == ZS_EMPTY) |
| 1638 | 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 | 1778 | * return handle. |
| 1718 | 1779 | */ |
| 1719 | −static unsigned long find_alloced_obj(struct size_class *class, | |
| 1720 | − struct page *page, int *obj_idx) | |
| 1780 | +static unsigned long find_tagged_obj(struct size_class *class, | |
| 1781 | + struct page *page, int *obj_idx, int tag) | |
| 1721 | 1782 | { |
| 1722 | 1783 | unsigned int offset; |
| 1723 | 1784 | int index = *obj_idx; |
| @@ -1728,7 +1789,7 @@ static unsigned long find_alloced_obj(struct size_class *class, · 4 unmodified lines | ||
| 1728 | 1789 | offset += class->size * index; |
| 1729 | 1790 | |
| 1730 | 1791 | while (offset < PAGE_SIZE) { |
| 1731 | − if (obj_allocated(page, addr + offset, &handle)) | |
| 1792 | + if (obj_tagged(page, addr + offset, &handle, tag)) | |
| 1732 | 1793 | break; |
| 1733 | 1794 | |
| 1734 | 1795 | offset += class->size; |
| @@ -1742,6 +1803,28 @@ static unsigned long find_alloced_obj(struct size_class *class, · 7 unmodified lines | ||
| 1742 | 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 | 1828 | struct zs_compact_control { |
| 1746 | 1829 | /* Source spage for migration which could be a subpage of zspage */ |
| 1747 | 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 | 1867 | zs_object_copy(class, free_obj, used_obj); |
| 1785 | 1868 | obj_idx++; |
| 1786 | 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 | 1873 | /* Remember last position in this iteration */ |
| @@ -2478,6 +2561,90 @@ void zs_destroy_pool(struct zs_pool *pool) · 687 unmodified lines | ||
| 2478 | 2561 | EXPORT_SYMBOL_GPL(zs_destroy_pool); |
| 2479 | 2562 | |
| 2480 | 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 | 2648 | static int zs_reclaim_page(struct zs_pool *pool, unsigned int retries) |
| 2482 | 2649 | { |
| 2483 | 2650 | int i, obj_idx, ret = 0; |
| @@ -2561,6 +2728,12 @@ next: · 77 unmodified lines | ||
| 2561 | 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 | 2737 | putback_zspage(class, zspage); |
| 2565 | 2738 | list_add(&zspage->lru, &pool->lru); |
| 2566 | 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 | 165 | * leaving this function. |
| 166 | 166 | */ |
| 167 | 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 | 208 | if (!ecu && j1939_address_is_unicast(skcb->addr.sa)) |
| 169 | 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 | 269 | (n->nud_state == NUD_NOARP) || |
| 270 | 270 | (tbl->is_multicast && |
| 271 | 271 | tbl->is_multicast(n->primary_key)) || |
| 272 | − time_after(tref, n->updated)) | |
| 272 | + !time_in_range(n->updated, tref, jiffies)) | |
| 273 | 273 | remove = true; |
| 274 | 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 | 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 | 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 | 303 | if (unlikely(mod_timer(&n->timer, when))) { |
| 294 | 304 | printk("NEIGH: BUG, double timer add, state is %x\n", |
| 295 | 305 | n->nud_state); |
| @@ -1001,12 +1011,14 @@ static void neigh_periodic_work(struct work_struct *work) · 705 unmodified lines | ||
| 1001 | 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 | 1016 | n->used = n->confirmed; |
| 1006 | 1017 | |
| 1007 | 1018 | if (refcount_read(&n->refcnt) == 1 && |
| 1008 | 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 | 1022 | *np = n->next; |
| 1011 | 1023 | neigh_mark_dead(n); |
| 1012 | 1024 | write_unlock(&n->lock); |
| @@ -1531,6 +1531,8 @@ set_sndbuf: · 1530 unmodified lines | ||
| 1531 | 1531 | ret = -EINVAL; |
| 1532 | 1532 | break; |
| 1533 | 1533 | } |
| 1534 | + if ((u8)val == SOCK_TXREHASH_DEFAULT) | |
| 1535 | + val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash); | |
| 1534 | 1536 | /* Paired with READ_ONCE() in tcp_rtx_synack() */ |
| 1535 | 1537 | WRITE_ONCE(sk->sk_txrehash, (u8)val); |
| 1536 | 1538 | break; |
| @@ -3454,7 +3456,6 @@ void sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid) · 1917 unmodified lines | ||
| 3454 | 3456 | sk->sk_pacing_rate = ~0UL; |
| 3455 | 3457 | WRITE_ONCE(sk->sk_pacing_shift, 10); |
| 3456 | 3458 | sk->sk_incoming_cpu = -1; |
| 3457 | − sk->sk_txrehash = SOCK_TXREHASH_DEFAULT; | |
| 3458 | 3459 | |
| 3459 | 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 | 205 | goto err_xa_alloc; |
| 206 | 206 | |
| 207 | 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 | 209 | if (ret) |
| 210 | 210 | goto err_register_netdevice_notifier; |
| 211 | 211 | |
| @@ -266,8 +266,7 @@ void devlink_free(struct devlink *devlink) · 54 unmodified lines | ||
| 266 | 266 | xa_destroy(&devlink->snapshot_ids); |
| 267 | 267 | xa_destroy(&devlink->ports); |
| 268 | 268 | |
| 269 | − WARN_ON_ONCE(unregister_netdevice_notifier_net(devlink_net(devlink), | |
| 270 | − &devlink->netdevice_nb)); | |
| 269 | + WARN_ON_ONCE(unregister_netdevice_notifier(&devlink->netdevice_nb)); | |
| 271 | 270 | |
| 272 | 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 | 8430 | break; |
| 8431 | 8431 | case NETDEV_REGISTER: |
| 8432 | 8432 | case NETDEV_CHANGENAME: |
| 8433 | + if (devlink_net(devlink) != dev_net(netdev)) | |
| 8434 | + return NOTIFY_OK; | |
| 8433 | 8435 | /* Set the netdev on top of previously set type. Note this |
| 8434 | 8436 | * event happens also during net namespace change so here |
| 8435 | 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 | 8441 | netdev); |
| 8440 | 8442 | break; |
| 8441 | 8443 | case NETDEV_UNREGISTER: |
| 8444 | + if (devlink_net(devlink) != dev_net(netdev)) | |
| 8445 | + return NOTIFY_OK; | |
| 8442 | 8446 | /* Clear netdev pointer, but not the type. This event happens |
| 8443 | 8447 | * also during net namespace change so we need to clear |
| 8444 | 8448 | * pointer to netdev that is going to another net namespace. |
| @@ -347,6 +347,7 @@ lookup_protocol: · 346 unmodified lines | ||
| 347 | 347 | sk->sk_destruct = inet_sock_destruct; |
| 348 | 348 | sk->sk_protocol = protocol; |
| 349 | 349 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; |
| 350 | + sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); | |
| 350 | 351 | |
| 351 | 352 | inet->uc_ttl = -1; |
| 352 | 353 | inet->mc_loop = 1; |
| @@ -1246,9 +1246,6 @@ int inet_csk_listen_start(struct sock *sk) · 1245 unmodified lines | ||
| 1246 | 1246 | sk->sk_ack_backlog = 0; |
| 1247 | 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 | 1249 | /* There is race window here: we announce ourselves listening, |
| 1253 | 1250 | * but this transition is still not validated by get_port(). |
| 1254 | 1251 | * It is OK, because this socket enters to hash table only |
| @@ -222,6 +222,7 @@ lookup_protocol: · 221 unmodified lines | ||
| 222 | 222 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
| 223 | 223 | np->repflow = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; |
| 224 | 224 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; |
| 225 | + sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); | |
| 225 | 226 | |
| 226 | 227 | /* Init the ipv4 part of the socket since we can have sockets |
| 227 | 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 | 1003 | int addrlen = sizeof(struct sockaddr_in); |
| 1004 | 1004 | struct sockaddr_storage addr; |
| 1005 | − struct mptcp_sock *msk; | |
| 1006 | 1005 | struct socket *ssock; |
| 1006 | + struct sock *newsk; | |
| 1007 | 1007 | int backlog = 1024; |
| 1008 | 1008 | int err; |
| 1009 | 1009 | |
| @@ -1012,11 +1012,13 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, · 2 unmodified lines | ||
| 1012 | 1012 | if (err) |
| 1013 | 1013 | return err; |
| 1014 | 1014 | |
| 1015 | − msk = mptcp_sk(entry->lsk->sk); | |
| 1016 | − if (!msk) | |
| 1015 | + newsk = entry->lsk->sk; | |
| 1016 | + if (!newsk) | |
| 1017 | 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 | 1022 | if (!ssock) |
| 1021 | 1023 | return -EINVAL; |
| 1022 | 1024 | |
| @@ -2902,6 +2902,7 @@ bool __mptcp_close(struct sock *sk, long timeout) · 2901 unmodified lines | ||
| 2902 | 2902 | struct mptcp_subflow_context *subflow; |
| 2903 | 2903 | struct mptcp_sock *msk = mptcp_sk(sk); |
| 2904 | 2904 | bool do_cancel_work = false; |
| 2905 | + int subflows_alive = 0; | |
| 2905 | 2906 | |
| 2906 | 2907 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 2907 | 2908 | |
| @@ -2928,6 +2929,8 @@ cleanup: · 20 unmodified lines | ||
| 2928 | 2929 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 2929 | 2930 | bool slow = lock_sock_fast_nested(ssk); |
| 2930 | 2931 | |
| 2932 | + subflows_alive += ssk->sk_state != TCP_CLOSE; | |
| 2933 | + | |
| 2931 | 2934 | /* since the close timeout takes precedence on the fail one, |
| 2932 | 2935 | * cancel the latter |
| 2933 | 2936 | */ |
| @@ -2943,6 +2946,12 @@ cleanup: · 9 unmodified lines | ||
| 2943 | 2946 | } |
| 2944 | 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 | 2955 | sock_hold(sk); |
| 2947 | 2956 | pr_debug("msk=%p state=%d", sk, sk->sk_state); |
| 2948 | 2957 | if (msk->token) |
| @@ -760,14 +760,21 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname, · 759 unmodified lines | ||
| 760 | 760 | static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int optname, |
| 761 | 761 | sockptr_t optval, unsigned int optlen) |
| 762 | 762 | { |
| 763 | + struct sock *sk = (struct sock *)msk; | |
| 763 | 764 | struct socket *sock; |
| 765 | + int ret = -EINVAL; | |
| 764 | 766 | |
| 765 | 767 | /* Limit to first subflow, before the connection establishment */ |
| 768 | + lock_sock(sk); | |
| 766 | 769 | sock = __mptcp_nmpc_socket(msk); |
| 767 | 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 | 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 | 1400 | mptcp_for_each_subflow(msk, subflow) { |
| 1401 | 1401 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 1402 | 1402 | int err = sock_error(ssk); |
| 1403 | + int ssk_state; | |
| 1403 | 1404 | |
| 1404 | 1405 | if (!err) |
| 1405 | 1406 | continue; |
| @@ -1410,7 +1411,14 @@ void __mptcp_error_report(struct sock *sk) · 4 unmodified lines | ||
| 1410 | 1411 | if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk)) |
| 1411 | 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 | 1422 | sk->sk_err = -err; |
| 1415 | 1423 | |
| 1416 | 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 | 1690 | if (err) |
| 1683 | 1691 | return err; |
| 1684 | 1692 | |
| 1685 | − lock_sock(sf->sk); | |
| 1693 | + lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING); | |
| 1686 | 1694 | |
| 1687 | 1695 | /* the newly created socket has to be in the same cgroup as its parent */ |
| 1688 | 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 | 104 | spin_lock_irqsave(&q->lock, flags); |
| 105 | 105 | head = &q->zcookie_head; |
| 106 | 106 | if (!list_empty(head)) { |
| 107 | − info = list_entry(head, struct rds_msg_zcopy_info, | |
| 108 | − rs_zcookie_next); | |
| 109 | − if (info && rds_zcookie_add(info, cookie)) { | |
| 107 | + info = list_first_entry(head, struct rds_msg_zcopy_info, | |
| 108 | + rs_zcookie_next); | |
| 109 | + if (rds_zcookie_add(info, cookie)) { | |
| 110 | 110 | spin_unlock_irqrestore(&q->lock, flags); |
| 111 | 111 | kfree(rds_info_from_znotifier(znotif)); |
| 112 | 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 | 433 | while (m) { |
| 434 | 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 | 437 | break; |
| 438 | 438 | m &= ~(1 << prio); |
| 439 | 439 | |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * Based on code and translator idea by: Florian Westphal <fw@strlen.de> |
| 6 | 6 | */ |
| 7 | 7 | #include <linux/compat.h> |
| 8 | +#include <linux/nospec.h> | |
| 8 | 9 | #include <linux/xfrm.h> |
| 9 | 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 | 303 | nla_for_each_attr(nla, attrs, len, remaining) { |
| 303 | 304 | int err; |
| 304 | 305 | |
| 305 | − switch (type) { | |
| 306 | + switch (nlh_src->nlmsg_type) { | |
| 306 | 307 | case XFRM_MSG_NEWSPDINFO: |
| 307 | 308 | err = xfrm_nla_cpy(dst, nla, nla_len(nla)); |
| 308 | 309 | break; |
| @@ -437,6 +438,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla, · 128 unmodified lines | ||
| 437 | 438 | NL_SET_ERR_MSG(extack, "Bad attribute"); |
| 438 | 439 | return -EOPNOTSUPP; |
| 439 | 440 | } |
| 441 | + type = array_index_nospec(type, XFRMA_MAX + 1); | |
| 440 | 442 | if (nla_len(nla) < compat_policy[type].len) { |
| 441 | 443 | NL_SET_ERR_MSG(extack, "Attribute bad length"); |
| 442 | 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 | 279 | goto out; |
| 280 | 280 | |
| 281 | 281 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
| 282 | − ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)), | |
| 283 | − ipipv6_hdr(skb)); | |
| 282 | + ipv6_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipipv6_hdr(skb)); | |
| 284 | 283 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
| 285 | 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 | 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 | 359 | static int xfrmi_rcv_cb(struct sk_buff *skb, int err) |
| 314 | 360 | { |
| 315 | 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 | 993 | static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = { |
| 948 | − .handler = xfrm6_rcv, | |
| 949 | − .input_handler = xfrm_input, | |
| 994 | + .handler = xfrmi6_rcv, | |
| 995 | + .input_handler = xfrmi6_input, | |
| 950 | 996 | .cb_handler = xfrmi_rcv_cb, |
| 951 | 997 | .err_handler = xfrmi6_err, |
| 952 | 998 | .priority = 10, |
| @@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = { · 43 unmodified lines | ||
| 996 | 1042 | #endif |
| 997 | 1043 | |
| 998 | 1044 | static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = { |
| 999 | − .handler = xfrm4_rcv, | |
| 1000 | − .input_handler = xfrm_input, | |
| 1045 | + .handler = xfrmi4_rcv, | |
| 1046 | + .input_handler = xfrmi4_input, | |
| 1001 | 1047 | .cb_handler = xfrmi_rcv_cb, |
| 1002 | 1048 | .err_handler = xfrmi4_err, |
| 1003 | 1049 | .priority = 10, |
| @@ -336,7 +336,7 @@ static void xfrm_policy_timer(struct timer_list *t) · 335 unmodified lines | ||
| 336 | 336 | } |
| 337 | 337 | if (xp->lft.hard_use_expires_seconds) { |
| 338 | 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 | 340 | if (tmo <= 0) |
| 341 | 341 | goto expired; |
| 342 | 342 | if (tmo < next) |
| @@ -354,7 +354,7 @@ static void xfrm_policy_timer(struct timer_list *t) · 11 unmodified lines | ||
| 354 | 354 | } |
| 355 | 355 | if (xp->lft.soft_use_expires_seconds) { |
| 356 | 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 | 358 | if (tmo <= 0) { |
| 359 | 359 | warn = 1; |
| 360 | 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 | 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 | 3667 | pols[0] = pol; |
| 3667 | 3668 | npols++; |
| @@ -3676,7 +3677,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, · 8 unmodified lines | ||
| 3676 | 3677 | xfrm_pol_put(pols[0]); |
| 3677 | 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 | 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 | 3745 | goto reject; |
| 3743 | 3746 | } |
| 3744 | 3747 | |
| 3748 | + if (if_id) | |
| 3749 | + secpath_reset(skb); | |
| 3750 | + | |
| 3745 | 3751 | xfrm_pols_put(pols, npols); |
| 3746 | 3752 | return 1; |
| 3747 | 3753 | } |
| @@ -577,7 +577,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 576 unmodified lines | ||
| 577 | 577 | if (x->km.state == XFRM_STATE_EXPIRED) |
| 578 | 578 | goto expired; |
| 579 | 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 | 581 | x->curlft.add_time - now; |
| 582 | 582 | if (tmo <= 0) { |
| 583 | 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 | 594 | next = tmo; |
| 595 | 595 | } |
| 596 | 596 | if (x->lft.hard_use_expires_seconds) { |
| 597 | − long tmo = x->lft.hard_use_expires_seconds + | |
| 598 | − (x->curlft.use_time ? : now) - now; | |
| 597 | + time64_t tmo = x->lft.hard_use_expires_seconds + | |
| 598 | + (READ_ONCE(x->curlft.use_time) ? : now) - now; | |
| 599 | 599 | if (tmo <= 0) |
| 600 | 600 | goto expired; |
| 601 | 601 | if (tmo < next) |
| @@ -604,7 +604,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) · 2 unmodified lines | ||
| 604 | 604 | if (x->km.dying) |
| 605 | 605 | goto resched; |
| 606 | 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 | 608 | x->curlft.add_time - now; |
| 609 | 609 | if (tmo <= 0) { |
| 610 | 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 | 618 | if (x->lft.soft_use_expires_seconds) { |
| 619 | − long tmo = x->lft.soft_use_expires_seconds + | |
| 620 | − (x->curlft.use_time ? : now) - now; | |
| 619 | + time64_t tmo = x->lft.soft_use_expires_seconds + | |
| 620 | + (READ_ONCE(x->curlft.use_time) ? : now) - now; | |
| 621 | 621 | if (tmo <= 0) |
| 622 | 622 | warn = 1; |
| 623 | 623 | else if (tmo < next) |
| @@ -1906,7 +1906,7 @@ out: · 1282 unmodified lines | ||
| 1906 | 1906 | |
| 1907 | 1907 | hrtimer_start(&x1->mtimer, ktime_set(1, 0), |
| 1908 | 1908 | HRTIMER_MODE_REL_SOFT); |
| 1909 | − if (x1->curlft.use_time) | |
| 1909 | + if (READ_ONCE(x1->curlft.use_time)) | |
| 1910 | 1910 | xfrm_state_check_expire(x1); |
| 1911 | 1911 | |
| 1912 | 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 | 1941 | xfrm_dev_state_update_curlft(x); |
| 1942 | 1942 | |
| 1943 | − if (!x->curlft.use_time) | |
| 1944 | − x->curlft.use_time = ktime_get_real_seconds(); | |
| 1943 | + if (!READ_ONCE(x->curlft.use_time)) | |
| 1944 | + WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds()); | |
| 1945 | 1945 | |
| 1946 | 1946 | if (x->curlft.bytes >= x->lft.hard_byte_limit || |
| 1947 | 1947 | x->curlft.packets >= x->lft.hard_packet_limit) { |
| @@ -66,9 +66,13 @@ endif · 65 unmodified lines | ||
| 66 | 66 | # Don't stop modules_install even if we can't sign external modules. |
| 67 | 67 | # |
| 68 | 68 | ifeq ($(CONFIG_MODULE_SIG_ALL),y) |
| 69 | +ifeq ($(filter pkcs11:%, $(CONFIG_MODULE_SIG_KEY)),) | |
| 69 | 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 | 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 | 76 | $(if $(KBUILD_EXTMOD),|| true) |
| 73 | 77 | else |
| 74 | 78 | quiet_cmd_sign := |
| @@ -246,7 +246,7 @@ test_vlan_ingress_modify() · 245 unmodified lines | ||
| 246 | 246 | bridge vlan add dev $swp2 vid 300 |
| 247 | 247 | |
| 248 | 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 | 250 | action vlan modify id 300 \ |
| 251 | 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 | 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 | 245 | static void guest_exec(void) |
| 241 | 246 | { |
| 242 | 247 | int (*code)(void) = (int (*)(void))TEST_EXEC_GVA; |
| @@ -304,7 +309,7 @@ static struct uffd_args { · 61 unmodified lines | ||
| 304 | 309 | |
| 305 | 310 | /* Returns true to continue the test, and false if it should be skipped. */ |
| 306 | 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 | 314 | uint64_t addr = msg->arg.pagefault.address; |
| 310 | 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 | 319 | TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, |
| 315 | 320 | "The only expected UFFD mode is MISSING"); |
| 316 | − ASSERT_EQ(!!(flags & UFFD_PAGEFAULT_FLAG_WRITE), expect_write); | |
| 317 | 321 | ASSERT_EQ(addr, (uint64_t)args->hva); |
| 318 | 322 | |
| 319 | 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 | 341 | return 0; |
| 338 | 342 | } |
| 339 | 343 | |
| 340 | −static int uffd_pt_write_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) | |
| 344 | +static int uffd_pt_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 | 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 | 471 | struct userspace_mem_region *data_region, *pt_region; |
| 473 | 472 | bool continue_test = true; |
| 473 | + uint64_t pte_gpa, pte_pg; | |
| 474 | 474 | |
| 475 | 475 | data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); |
| 476 | 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 | 480 | if (cmd == CMD_SKIP_TEST) |
| 479 | 481 | continue_test = false; |
| @@ -486,13 +488,13 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd) · 6 unmodified lines | ||
| 486 | 488 | TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0), |
| 487 | 489 | "Missing write in dirty log"); |
| 488 | 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 | 492 | "Missing s1ptw write in dirty log"); |
| 491 | 493 | if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG) |
| 492 | 494 | TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0), |
| 493 | 495 | "Unexpected write in dirty log"); |
| 494 | 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 | 498 | "Unexpected s1ptw write in dirty log"); |
| 497 | 499 | |
| 498 | 500 | return continue_test; |
| @@ -797,7 +799,7 @@ static void help(char *name) · 298 unmodified lines | ||
| 797 | 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 | 804 | .name = SCAT3(dirty_log, _access, _with_af), \ |
| 803 | 805 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -805,13 +807,12 @@ static void help(char *name) · 1 unmodified line | ||
| 805 | 807 | .guest_prepare = { _PREPARE(_with_af), \ |
| 806 | 808 | _PREPARE(_access) }, \ |
| 807 | 809 | .guest_test = _access, \ |
| 808 | − .guest_test_check = { _CHECK(_with_af), _test_check, \ | |
| 809 | − guest_check_s1ptw_wr_in_dirty_log}, \ | |
| 810 | + .guest_test_check = { _CHECK(_with_af), _test_check, _pt_check }, \ | |
| 810 | 811 | .expected_events = { 0 }, \ |
| 811 | 812 | } |
| 812 | 813 | |
| 813 | 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 | 817 | .name = SCAT3(uffd_and_dirty_log, _access, _with_af), \ |
| 817 | 818 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -820,16 +821,17 @@ static void help(char *name) · 2 unmodified lines | ||
| 820 | 821 | _PREPARE(_access) }, \ |
| 821 | 822 | .guest_test = _access, \ |
| 822 | 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 | 825 | .uffd_data_handler = _uffd_data_handler, \ |
| 825 | − .uffd_pt_handler = uffd_pt_write_handler, \ | |
| 826 | + .uffd_pt_handler = uffd_pt_handler, \ | |
| 826 | 827 | .expected_events = { .uffd_faults = _uffd_faults, }, \ |
| 827 | 828 | } |
| 828 | 829 | |
| 829 | 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 | 833 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 834 | + .pt_memslot_flags = KVM_MEM_READONLY, \ | |
| 833 | 835 | .guest_prepare = { _PREPARE(_access) }, \ |
| 834 | 836 | .guest_test = _access, \ |
| 835 | 837 | .mmio_handler = _mmio_handler, \ |
| @@ -840,6 +842,7 @@ static void help(char *name) · 4 unmodified lines | ||
| 840 | 842 | { \ |
| 841 | 843 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 842 | 844 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 845 | + .pt_memslot_flags = KVM_MEM_READONLY, \ | |
| 843 | 846 | .guest_test = _access, \ |
| 844 | 847 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 845 | 848 | .expected_events = { .fail_vcpu_runs = 1 }, \ |
| @@ -848,9 +851,9 @@ static void help(char *name) · 2 unmodified lines | ||
| 848 | 851 | #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits, \ |
| 849 | 852 | _test_check) \ |
| 850 | 853 | { \ |
| 851 | − .name = SCAT3(ro_memslot, _access, _with_af), \ | |
| 854 | + .name = SCAT2(ro_memslot, _access), \ | |
| 852 | 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 | 857 | .guest_prepare = { _PREPARE(_access) }, \ |
| 855 | 858 | .guest_test = _access, \ |
| 856 | 859 | .guest_test_check = { _test_check }, \ |
| @@ -862,7 +865,7 @@ static void help(char *name) · 5 unmodified lines | ||
| 862 | 865 | { \ |
| 863 | 866 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ |
| 864 | 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 | 869 | .guest_test = _access, \ |
| 867 | 870 | .guest_test_check = { _test_check }, \ |
| 868 | 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 | 878 | .name = SCAT2(ro_memslot_uffd, _access), \ |
| 876 | 879 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 880 | + .pt_memslot_flags = KVM_MEM_READONLY, \ | |
| 877 | 881 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 878 | 882 | .guest_prepare = { _PREPARE(_access) }, \ |
| 879 | 883 | .guest_test = _access, \ |
| 880 | 884 | .uffd_data_handler = _uffd_data_handler, \ |
| 881 | − .uffd_pt_handler = uffd_pt_write_handler, \ | |
| 885 | + .uffd_pt_handler = uffd_pt_handler, \ | |
| 882 | 886 | .mmio_handler = _mmio_handler, \ |
| 883 | 887 | .expected_events = { .mmio_exits = _mmio_exits, \ |
| 884 | 888 | .uffd_faults = _uffd_faults }, \ |
| @@ -889,10 +893,11 @@ static void help(char *name) · 4 unmodified lines | ||
| 889 | 893 | { \ |
| 890 | 894 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 891 | 895 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 896 | + .pt_memslot_flags = KVM_MEM_READONLY, \ | |
| 892 | 897 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 893 | 898 | .guest_test = _access, \ |
| 894 | 899 | .uffd_data_handler = _uffd_data_handler, \ |
| 895 | − .uffd_pt_handler = uffd_pt_write_handler, \ | |
| 900 | + .uffd_pt_handler = uffd_pt_handler, \ | |
| 896 | 901 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 897 | 902 | .expected_events = { .fail_vcpu_runs = 1, \ |
| 898 | 903 | .uffd_faults = _uffd_faults }, \ |
| @@ -933,44 +938,51 @@ static struct test_desc tests[] = { · 34 unmodified lines | ||
| 933 | 938 | * (S1PTW). |
| 934 | 939 | */ |
| 935 | 940 | TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 936 | − uffd_data_read_handler, uffd_pt_write_handler, 2), | |
| 937 | − /* no_af should also lead to a PT write. */ | |
| 941 | + uffd_data_handler, uffd_pt_handler, 2), | |
| 938 | 942 | TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 939 | − uffd_data_read_handler, uffd_pt_write_handler, 2), | |
| 940 | − /* Note how that cas invokes the read handler. */ | |
| 943 | + uffd_data_handler, uffd_pt_handler, 2), | |
| 941 | 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 | 947 | * Can't test guest_at with_af as it's IMPDEF whether the AF is set. |
| 945 | 948 | * The S1PTW fault should still be marked as a write. |
| 946 | 949 | */ |
| 947 | 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 | 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 | 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 | 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 | 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 | 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 | 964 | * Try accesses when the data and PT memory regions are both |
| 962 | 965 | * tracked for dirty logging. |
| 963 | 966 | */ |
| 964 | − TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log), | |
| 965 | − /* no_af should also lead to a PT write. */ | |
| 966 | − 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), | |
| 968 | − TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log), | |
| 969 | − TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log), | |
| 970 | − TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log), | |
| 971 | − TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log), | |
| 972 | − TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log), | |
| 973 | − TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log), | |
| 967 | + TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log, | |
| 968 | + guest_check_s1ptw_wr_in_dirty_log), | |
| 969 | + TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log, | |
| 970 | + guest_check_no_s1ptw_wr_in_dirty_log), | |
| 971 | + TEST_DIRTY_LOG(guest_ld_preidx, with_af, | |
| 972 | + guest_check_no_write_in_dirty_log, | |
| 973 | + guest_check_s1ptw_wr_in_dirty_log), | |
| 974 | + TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log, | |
| 975 | + guest_check_no_s1ptw_wr_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 | 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 | 992 | * fault, and nothing in the dirty log. Any S1PTW should result in |
| 981 | 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, | |
| 984 | − guest_check_no_write_in_dirty_log), | |
| 985 | − /* no_af should also lead to a PT write. */ | |
| 986 | − TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, uffd_data_read_handler, 2, | |
| 987 | − guest_check_no_write_in_dirty_log), | |
| 988 | − TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, uffd_data_read_handler, | |
| 989 | − 2, guest_check_no_write_in_dirty_log), | |
| 990 | − TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, 0, 1, | |
| 991 | − guest_check_no_write_in_dirty_log), | |
| 992 | − TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, uffd_data_read_handler, 2, | |
| 993 | − guest_check_no_write_in_dirty_log), | |
| 994 | − TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, uffd_data_write_handler, | |
| 995 | − 2, guest_check_write_in_dirty_log), | |
| 996 | − TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, uffd_data_read_handler, 2, | |
| 997 | − guest_check_write_in_dirty_log), | |
| 998 | − TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, uffd_data_write_handler, | |
| 999 | − 2, guest_check_write_in_dirty_log), | |
| 995 | + TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, | |
| 996 | + uffd_data_handler, 2, | |
| 997 | + guest_check_no_write_in_dirty_log, | |
| 998 | + guest_check_s1ptw_wr_in_dirty_log), | |
| 999 | + TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, | |
| 1000 | + uffd_data_handler, 2, | |
| 1001 | + guest_check_no_write_in_dirty_log, | |
| 1002 | + guest_check_no_s1ptw_wr_in_dirty_log), | |
| 1003 | + TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, | |
| 1004 | + uffd_data_handler, | |
| 1005 | + 2, guest_check_no_write_in_dirty_log, | |
| 1006 | + guest_check_s1ptw_wr_in_dirty_log), | |
| 1007 | + TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, uffd_no_handler, 1, | |
| 1008 | + guest_check_no_write_in_dirty_log, | |
| 1009 | + guest_check_s1ptw_wr_in_dirty_log), | |
| 1010 | + TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, | |
| 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 | 1026 | TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af, |
| 1001 | − uffd_data_write_handler, 2, | |
| 1002 | − guest_check_write_in_dirty_log), | |
| 1003 | − | |
| 1027 | + uffd_data_handler, 2, | |
| 1028 | + guest_check_write_in_dirty_log, | |
| 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 | 1032 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an |
| 1007 | 1033 | * MMIO exit, writes with no syndrome (e.g., CAS) result in a |
| 1008 | 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 | 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 | 1048 | * for dirty logging at the same time. The expected result is that |
| 1023 | 1049 | * for writes there should be no write in the dirty log. The |
| 1024 | 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 | 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 | 1073 | * holes tracked with userfaultfd. The expected result is the |
| 1048 | 1074 | * union of both userfaultfd and read-only behaviors. For example, |
| 1049 | 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 | 1077 | * no userfaultfd write fault. Reads result in userfaultfd getting |
| 1052 | 1078 | * triggered. |
| 1053 | 1079 | */ |
| 1054 | − TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, | |
| 1055 | − uffd_data_read_handler, 2), | |
| 1056 | − TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, | |
| 1057 | − uffd_data_read_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), | |
| 1080 | + TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, uffd_data_handler, 2), | |
| 1081 | + TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, uffd_data_handler, 2), | |
| 1082 | + TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, uffd_no_handler, 1), | |
| 1083 | + TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, uffd_data_handler, 2), | |
| 1062 | 1084 | TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1, |
| 1063 | − uffd_data_write_handler, 2), | |
| 1064 | − TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, | |
| 1065 | − uffd_data_read_handler, 2), | |
| 1066 | − TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, | |
| 1067 | − uffd_no_handler, 1), | |
| 1068 | − TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, | |
| 1069 | − uffd_no_handler, 1), | |
| 1085 | + uffd_data_handler, 2), | |
| 1086 | + TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, uffd_data_handler, 2), | |
| 1087 | + TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, uffd_no_handler, 1), | |
| 1088 | + TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, uffd_no_handler, 1), | |
| 1070 | 1089 | |
| 1071 | 1090 | { 0 } |
| 1072 | 1091 | }; |
| @@ -893,14 +893,14 @@ sysctl_set() · 892 unmodified lines | ||
| 893 | 893 | local value=$1; shift |
| 894 | 894 | |
| 895 | 895 | SYSCTL_ORIG[$key]=$(sysctl -n $key) |
| 896 | − sysctl -qw $key=$value | |
| 896 | + sysctl -qw $key="$value" | |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | 899 | sysctl_restore() |
| 900 | 900 | { |
| 901 | 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 | 906 | forwarding_enable() |
| @@ -498,6 +498,12 @@ kill_events_pids() · 497 unmodified lines | ||
| 498 | 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 | 507 | pm_nl_set_limits() |
| 502 | 508 | { |
| 503 | 509 | local ns=$1 |
| @@ -1687,6 +1693,7 @@ chk_subflow_nr() · 1183 unmodified lines | ||
| 1687 | 1693 | local subflow_nr=$3 |
| 1688 | 1694 | local cnt1 |
| 1689 | 1695 | local cnt2 |
| 1696 | + local dump_stats | |
| 1690 | 1697 | |
| 1691 | 1698 | if [ -n "${need_title}" ]; then |
| 1692 | 1699 | printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}" |
| @@ -1704,7 +1711,12 @@ chk_subflow_nr() · 11 unmodified lines | ||
| 1704 | 1711 | echo "[ ok ]" |
| 1705 | 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 | 1722 | chk_link_usage() |
| @@ -3083,7 +3095,7 @@ endpoint_tests() · 1372 unmodified lines | ||
| 3083 | 3095 | pm_nl_set_limits $ns1 2 2 |
| 3084 | 3096 | pm_nl_set_limits $ns2 2 2 |
| 3085 | 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 | 3100 | wait_mpj $ns1 |
| 3089 | 3101 | pm_nl_check_endpoint 1 "creation" \ |
| @@ -3096,14 +3108,14 @@ endpoint_tests() · 6 unmodified lines | ||
| 3096 | 3108 | pm_nl_add_endpoint $ns2 10.0.2.2 flags signal |
| 3097 | 3109 | pm_nl_check_endpoint 0 "modif is allowed" \ |
| 3098 | 3110 | $ns2 10.0.2.2 id 1 flags signal |
| 3099 | − wait | |
| 3111 | + kill_tests_wait | |
| 3100 | 3112 | fi |
| 3101 | 3113 | |
| 3102 | 3114 | if reset "delete and re-add"; then |
| 3103 | 3115 | pm_nl_set_limits $ns1 1 1 |
| 3104 | 3116 | pm_nl_set_limits $ns2 1 1 |
| 3105 | 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 | 3120 | wait_mpj $ns2 |
| 3109 | 3121 | pm_nl_del_endpoint $ns2 2 10.0.2.2 |
| @@ -3113,7 +3125,7 @@ endpoint_tests() · 3 unmodified lines | ||
| 3113 | 3125 | pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow |
| 3114 | 3126 | wait_mpj $ns2 |
| 3115 | 3127 | chk_subflow_nr "" "after re-add" 2 |
| 3116 | − wait | |
| 3128 | + kill_tests_wait | |
| 3117 | 3129 | fi |
| 3118 | 3130 | } |
| 3119 | 3131 | |
| @@ -293,19 +293,11 @@ setup-vm() { · 292 unmodified lines | ||
| 293 | 293 | elif [[ -n $vtype && $vtype == "vnifilterg" ]]; then |
| 294 | 294 | # Add per vni group config with 'bridge vni' api |
| 295 | 295 | if [ -n "$group" ]; then |
| 296 | − if [ "$family" == "v4" ]; then | |
| 297 | − if [ $mcast -eq 1 ]; then | |
| 298 | − bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group $group | |
| 299 | − else | |
| 300 | − bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote $group | |
| 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 | |
| 296 | + if [ $mcast -eq 1 ]; then | |
| 297 | + bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group $group | |
| 298 | + else | |
| 299 | + bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote $group | |
| 300 | + fi | |
| 309 | 301 | fi |
| 310 | 302 | fi |
| 311 | 303 | done |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <stdio.h> |
| 18 | 18 | #include <unistd.h> |
| 19 | 19 | #include <sys/mman.h> |
| 20 | −#define __USE_GNU | |
| 21 | 20 | #include <fcntl.h> |
| 22 | 21 | |
| 23 | 22 | #define MIN_FREE_PAGES 20 |