]> Git Repo - linux.git/commitdiff
Merge tag 'irq-core-2024-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Tue, 17 Sep 2024 05:09:17 +0000 (07:09 +0200)
committerLinus Torvalds <[email protected]>
Tue, 17 Sep 2024 05:09:17 +0000 (07:09 +0200)
Pull irq updates from Thomas Gleixner:
 "Core:

   - Remove a global lock in the affinity setting code

     The lock protects a cpumask for intermediate results and the lock
     causes a bottleneck on simultaneous start of multiple virtual
     machines. Replace the lock and the static cpumask with a per CPU
     cpumask which is nicely serialized by raw spinlock held when
     executing this code.

   - Provide support for giving a suffix to interrupt domain names.

     That's required to support devices with subfunctions so that the
     domain names are distinct even if they originate from the same
     device node.

   - The usual set of cleanups and enhancements all over the place

  Drivers:

   - Support for longarch AVEC interrupt chip

   - Refurbishment of the Armada driver so it can be extended for new
     variants.

   - The usual set of cleanups and enhancements all over the place"

* tag 'irq-core-2024-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (73 commits)
  genirq: Use cpumask_intersects()
  genirq/cpuhotplug: Use cpumask_intersects()
  irqchip/apple-aic: Only access system registers on SoCs which provide them
  irqchip/apple-aic: Add a new "Global fast IPIs only" feature level
  irqchip/apple-aic: Skip unnecessary enabling of use_fast_ipi
  dt-bindings: apple,aic: Document A7-A11 compatibles
  irqdomain: Use IS_ERR_OR_NULL() in irq_domain_trim_hierarchy()
  genirq/msi: Use kmemdup_array() instead of kmemdup()
  genirq/proc: Change the return value for set affinity permission error
  genirq/proc: Use irq_move_pending() in show_irq_affinity()
  genirq/proc: Correctly set file permissions for affinity control files
  genirq: Get rid of global lock in irq_do_set_affinity()
  genirq: Fix typo in struct comment
  irqchip/loongarch-avec: Add AVEC irqchip support
  irqchip/loongson-pch-msi: Prepare get_pch_msi_handle() for AVECINTC
  irqchip/loongson-eiointc: Rename CPUHP_AP_IRQ_LOONGARCH_STARTING
  LoongArch: Architectural preparation for AVEC irqchip
  LoongArch: Move irqchip function prototypes to irq-loongson.h
  irqchip/loongson-pch-msi: Switch to MSI parent domains
  softirq: Remove unused 'action' parameter from action callback
  ...

1  2 
arch/loongarch/include/asm/loongarch.h
arch/loongarch/kernel/irq.c
arch/loongarch/kernel/paravirt.c
arch/loongarch/kernel/smp.c
block/blk-mq.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-loongarch-cpu.c
drivers/irqchip/irq-mbigen.c
include/linux/cpuhotplug.h
net/core/dev.c

index 24a3f4925cfb24a4606dd34470b7fde881e7de19,631d249b3ef268ebefd118feaaf79d9b4f0c3e20..04bf1a7f903a216ac980169eafe71b5fea005384
  #define  CPUCFG6_PMP                  BIT(0)
  #define  CPUCFG6_PAMVER                       GENMASK(3, 1)
  #define  CPUCFG6_PMNUM                        GENMASK(7, 4)
 +#define  CPUCFG6_PMNUM_SHIFT          4
  #define  CPUCFG6_PMBITS                       GENMASK(13, 8)
  #define  CPUCFG6_UPM                  BIT(14)
  
  
  /*
   * CPUCFG index area: 0x40000000 -- 0x400000ff
 - * SW emulation for KVM hypervirsor
 + * SW emulation for KVM hypervirsor, see arch/loongarch/include/uapi/asm/kvm_para.h
   */
 -#define CPUCFG_KVM_BASE                       0x40000000
 -#define CPUCFG_KVM_SIZE                       0x100
 -
 -#define CPUCFG_KVM_SIG                        (CPUCFG_KVM_BASE + 0)
 -#define  KVM_SIGNATURE                        "KVM\0"
 -#define CPUCFG_KVM_FEATURE            (CPUCFG_KVM_BASE + 4)
 -#define  KVM_FEATURE_IPI              BIT(1)
 -#define  KVM_FEATURE_STEAL_TIME               BIT(2)
  
  #ifndef __ASSEMBLY__
  
  #define  CSR_ESTAT_EXC_WIDTH          6
  #define  CSR_ESTAT_EXC                        (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT)
  #define  CSR_ESTAT_IS_SHIFT           0
- #define  CSR_ESTAT_IS_WIDTH           14
- #define  CSR_ESTAT_IS                 (_ULCAST_(0x3fff) << CSR_ESTAT_IS_SHIFT)
+ #define  CSR_ESTAT_IS_WIDTH           15
+ #define  CSR_ESTAT_IS                 (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT)
  
  #define LOONGARCH_CSR_ERA             0x6     /* ERA */
  
  
  #define LOONGARCH_CSR_CTAG            0x98    /* TagLo + TagHi */
  
+ #define LOONGARCH_CSR_ISR0            0xa0
+ #define LOONGARCH_CSR_ISR1            0xa1
+ #define LOONGARCH_CSR_ISR2            0xa2
+ #define LOONGARCH_CSR_ISR3            0xa3
+ #define LOONGARCH_CSR_IRR             0xa4
  #define LOONGARCH_CSR_PRID            0xc0
  
  /* Shadow MCSR : 0xc0 ~ 0xff */
  /*
   * CSR_ECFG IM
   */
- #define ECFG0_IM              0x00001fff
+ #define ECFG0_IM              0x00005fff
  #define ECFGB_SIP0            0
  #define ECFGF_SIP0            (_ULCAST_(1) << ECFGB_SIP0)
  #define ECFGB_SIP1            1
  #define  IOCSRF_EIODECODE             BIT_ULL(9)
  #define  IOCSRF_FLATMODE              BIT_ULL(10)
  #define  IOCSRF_VM                    BIT_ULL(11)
+ #define  IOCSRF_AVEC                  BIT_ULL(15)
  
  #define LOONGARCH_IOCSR_VENDOR                0x10
  
  #define  IOCSR_MISC_FUNC_SOFT_INT     BIT_ULL(10)
  #define  IOCSR_MISC_FUNC_TIMER_RESET  BIT_ULL(21)
  #define  IOCSR_MISC_FUNC_EXT_IOI_EN   BIT_ULL(48)
+ #define  IOCSR_MISC_FUNC_AVEC_EN      BIT_ULL(51)
  
  #define LOONGARCH_IOCSR_CPUTEMP               0x428
  
@@@ -1380,9 -1396,10 +1389,10 @@@ __BUILD_CSR_OP(tlbidx
  #define INT_TI                11      /* Timer */
  #define INT_IPI               12
  #define INT_NMI               13
+ #define INT_AVEC      14
  
  /* ExcCodes corresponding to interrupts */
- #define EXCCODE_INT_NUM               (INT_NMI + 1)
+ #define EXCCODE_INT_NUM               (INT_AVEC + 1)
  #define EXCCODE_INT_START     64
  #define EXCCODE_INT_END               (EXCCODE_INT_START + EXCCODE_INT_NUM - 1)
  
index adac8fcbb2aca482b29996337693010e18b7a705,414f5249d70a5ce012ed5cb9a09a9648275b80f3..d129039b368b09a97d06fff47a59f89e581ff672
@@@ -87,6 -87,18 +87,18 @@@ static void __init init_vec_parent_grou
        acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse);
  }
  
+ int __init arch_probe_nr_irqs(void)
+ {
+       int nr_io_pics = bitmap_weight(loongson_sysconf.cores_io_master, NR_CPUS);
+       if (!cpu_has_avecint)
+               nr_irqs = (64 + NR_VECTORS * nr_io_pics);
+       else
+               nr_irqs = (64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics));
+       return NR_IRQS_LEGACY;
+ }
  void __init init_IRQ(void)
  {
        int i;
        mp_ops.init_ipi();
  #endif
  
 -      for (i = 0; i < NR_IRQS; i++)
 -              irq_set_noprobe(i);
 -
        for_each_possible_cpu(i) {
                page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, order);
  
index 708eda025ed880ca4ae6dcd795cd01fb38a10c06,4d736a4e488dd08b451f73a3ab744b53b7c712e4..a5fc61f8b3482cfb93d12a44f65ab8a7c83b4f0f
@@@ -13,7 -13,6 +13,7 @@@ static int has_steal_clock
  struct static_key paravirt_steal_enabled;
  struct static_key paravirt_steal_rq_enabled;
  static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
 +DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key);
  
  static u64 native_steal_clock(int cpu)
  {
@@@ -135,6 -134,11 +135,11 @@@ static irqreturn_t pv_ipi_interrupt(in
                info->ipi_irqs[IPI_IRQ_WORK]++;
        }
  
+       if (action & SMP_CLEAR_VECTOR) {
+               complete_irq_moving();
+               info->ipi_irqs[IPI_CLEAR_VECTOR]++;
+       }
        return IRQ_HANDLED;
  }
  
@@@ -152,14 -156,11 +157,14 @@@ static void pv_init_ipi(void
  }
  #endif
  
 -static bool kvm_para_available(void)
 +bool kvm_para_available(void)
  {
        int config;
        static int hypervisor_type;
  
 +      if (!cpu_has_hypervisor)
 +              return false;
 +
        if (!hypervisor_type) {
                config = read_cpucfg(CPUCFG_KVM_SIG);
                if (!memcmp(&config, KVM_SIGNATURE, 4))
        return hypervisor_type == HYPERVISOR_KVM;
  }
  
 -int __init pv_ipi_init(void)
 +unsigned int kvm_arch_para_features(void)
  {
 -      int feature;
 +      static unsigned int feature;
  
 -      if (!cpu_has_hypervisor)
 -              return 0;
        if (!kvm_para_available())
                return 0;
  
 -      feature = read_cpucfg(CPUCFG_KVM_FEATURE);
 -      if (!(feature & KVM_FEATURE_IPI))
 +      if (!feature)
 +              feature = read_cpucfg(CPUCFG_KVM_FEATURE);
 +
 +      return feature;
 +}
 +
 +int __init pv_ipi_init(void)
 +{
 +      if (!kvm_para_has_feature(KVM_FEATURE_IPI))
                return 0;
  
  #ifdef CONFIG_SMP
@@@ -215,7 -211,7 +220,7 @@@ static int pv_enable_steal_time(void
        }
  
        addr |= KVM_STEAL_PHYS_VALID;
 -      kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, addr);
 +      kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), addr);
  
        return 0;
  }
  static void pv_disable_steal_time(void)
  {
        if (has_steal_clock)
 -              kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, 0);
 +              kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), 0);
  }
  
  #ifdef CONFIG_SMP
@@@ -267,9 -263,15 +272,9 @@@ static struct notifier_block pv_reboot_
  
  int __init pv_time_init(void)
  {
 -      int r, feature;
 +      int r;
  
 -      if (!cpu_has_hypervisor)
 -              return 0;
 -      if (!kvm_para_available())
 -              return 0;
 -
 -      feature = read_cpucfg(CPUCFG_KVM_FEATURE);
 -      if (!(feature & KVM_FEATURE_STEAL_TIME))
 +      if (!kvm_para_has_feature(KVM_FEATURE_STEAL_TIME))
                return 0;
  
        has_steal_clock = 1;
  
        return 0;
  }
 +
 +int __init pv_spinlock_init(void)
 +{
 +      if (!cpu_has_hypervisor)
 +              return 0;
 +
 +      static_branch_enable(&virt_spin_lock_key);
 +
 +      return 0;
 +}
index 482b3c7e3042d844cf5078f473d7f4db3eb4dc14,4adbbef3450acbcd39ed298e8f0564e32909b43f..9afc2d8b341419df404be792a1d756cc962049b3
@@@ -72,6 -72,7 +72,7 @@@ static const char *ipi_types[NR_IPI] __
        [IPI_RESCHEDULE] = "Rescheduling interrupts",
        [IPI_CALL_FUNCTION] = "Function call interrupts",
        [IPI_IRQ_WORK] = "IRQ work interrupts",
+       [IPI_CLEAR_VECTOR] = "Clear vector interrupts",
  };
  
  void show_ipi_list(struct seq_file *p, int prec)
@@@ -248,6 -249,11 +249,11 @@@ static irqreturn_t loongson_ipi_interru
                per_cpu(irq_stat, cpu).ipi_irqs[IPI_IRQ_WORK]++;
        }
  
+       if (action & SMP_CLEAR_VECTOR) {
+               complete_irq_moving();
+               per_cpu(irq_stat, cpu).ipi_irqs[IPI_CLEAR_VECTOR]++;
+       }
        return IRQ_HANDLED;
  }
  
@@@ -476,7 -482,7 +482,7 @@@ core_initcall(ipi_pm_init)
  #endif
  
  /* Preload SMP state for boot cpu */
 -void smp_prepare_boot_cpu(void)
 +void __init smp_prepare_boot_cpu(void)
  {
        unsigned int cpu, node, rr_node;
  
                        rr_node = next_node_in(rr_node, node_online_map);
                }
        }
 +
 +      pv_spinlock_init();
  }
  
  /* called from main before smp_init() */
diff --combined block/blk-mq.c
index 3f1f7d0b3ff35ec0a6a61192dc317fe0fbec2c55,aa28157b1aafcb1dfe4169b6dda8d224a03ebd09..831c5cf5d874077fbe27a02bd1be1f3e2d28e17b
@@@ -1128,7 -1128,7 +1128,7 @@@ static void blk_complete_reqs(struct ll
                rq->q->mq_ops->complete(rq);
  }
  
- static __latent_entropy void blk_done_softirq(struct softirq_action *h)
+ static __latent_entropy void blk_done_softirq(void)
  {
        blk_complete_reqs(this_cpu_ptr(&blk_cpu_done));
  }
@@@ -2753,7 -2753,6 +2753,7 @@@ static void blk_mq_dispatch_plug_list(s
  void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
  {
        struct request *rq;
 +      unsigned int depth;
  
        /*
         * We may have been called recursively midway through handling
         */
        if (plug->rq_count == 0)
                return;
 +      depth = plug->rq_count;
        plug->rq_count = 0;
  
        if (!plug->multiple_queues && !plug->has_elevator && !from_schedule) {
  
                rq = rq_list_peek(&plug->mq_list);
                q = rq->q;
 +              trace_block_unplug(q, depth, true);
  
                /*
                 * Peek first request and see if we have a ->queue_rqs() hook.
@@@ -2942,7 -2939,7 +2942,7 @@@ void blk_mq_submit_bio(struct bio *bio
        struct blk_plug *plug = current->plug;
        const int is_sync = op_is_sync(bio->bi_opf);
        struct blk_mq_hw_ctx *hctx;
 -      unsigned int nr_segs = 1;
 +      unsigned int nr_segs;
        struct request *rq;
        blk_status_t ret;
  
                goto queue_exit;
        }
  
 -      if (unlikely(bio_may_exceed_limits(bio, &q->limits))) {
 -              bio = __bio_split_to_limits(bio, &q->limits, &nr_segs);
 -              if (!bio)
 -                      goto queue_exit;
 -      }
 +      bio = __bio_split_to_limits(bio, &q->limits, &nr_segs);
 +      if (!bio)
 +              goto queue_exit;
 +
        if (!bio_integrity_prep(bio))
                goto queue_exit;
  
index 74f21e03d4a3749e3ff68d8e599c1d0ac9b9b357,0efa3443c32303eb8ce5cca255765c5bfc44e22c..ce87205e3e8237109493092958b90a9ccab80d1b
@@@ -930,7 -930,7 +930,7 @@@ static void __gic_handle_irq_from_irqso
        __gic_handle_nmi(irqnr, regs);
  }
  
- static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
  {
        if (unlikely(gic_supports_nmi() && !interrupts_enabled(regs)))
                __gic_handle_irq_from_irqsoff(regs);
@@@ -1154,8 -1154,14 +1154,8 @@@ static void gic_update_rdist_properties
                        gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
  }
  
 -static void gic_cpu_sys_reg_init(void)
 +static void gic_cpu_sys_reg_enable(void)
  {
 -      int i, cpu = smp_processor_id();
 -      u64 mpidr = gic_cpu_to_affinity(cpu);
 -      u64 need_rss = MPIDR_RS(mpidr);
 -      bool group0;
 -      u32 pribits;
 -
        /*
         * Need to check that the SRE bit has actually been set. If
         * not, it means that SRE is disabled at EL2. We're going to
        if (!gic_enable_sre())
                pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
  
 +}
 +
 +static void gic_cpu_sys_reg_init(void)
 +{
 +      int i, cpu = smp_processor_id();
 +      u64 mpidr = gic_cpu_to_affinity(cpu);
 +      u64 need_rss = MPIDR_RS(mpidr);
 +      bool group0;
 +      u32 pribits;
 +
        pribits = gic_get_pribits();
  
        group0 = gic_has_group0();
@@@ -1337,7 -1333,6 +1337,7 @@@ static int gic_check_rdist(unsigned in
  
  static int gic_starting_cpu(unsigned int cpu)
  {
 +      gic_cpu_sys_reg_enable();
        gic_cpu_init();
  
        if (gic_dist_supports_lpis())
@@@ -1503,7 -1498,6 +1503,7 @@@ static int gic_cpu_pm_notifier(struct n
        if (cmd == CPU_PM_EXIT) {
                if (gic_dist_security_disabled())
                        gic_enable_redist(true);
 +              gic_cpu_sys_reg_enable();
                gic_cpu_sys_reg_init();
        } else if (cmd == CPU_PM_ENTER && gic_dist_security_disabled()) {
                gic_write_grpen1(0);
@@@ -2076,7 -2070,6 +2076,7 @@@ static int __init gic_init_bases(phys_a
  
        gic_update_rdist_properties();
  
 +      gic_cpu_sys_reg_enable();
        gic_prio_init();
        gic_dist_init();
        gic_cpu_init();
index b35903a06902f73e719626205b0ba765d2319269,bcbd7fd331786974003831261a8310d755bdad98..e62dab4c97fcf543020abd5b190b7e81d05c6619
  #include <asm/loongarch.h>
  #include <asm/setup.h>
  
+ #include "irq-loongson.h"
  static struct irq_domain *irq_domain;
  struct fwnode_handle *cpuintc_handle;
  
  static u32 lpic_gsi_to_irq(u32 gsi)
  {
 +      int irq = 0;
 +
        /* Only pch irqdomain transferring is required for LoongArch. */
        if (gsi >= GSI_MIN_PCH_IRQ && gsi <= GSI_MAX_PCH_IRQ)
 -              return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH);
 +              irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH);
  
 -      return 0;
 +      return (irq > 0) ? irq : 0;
  }
  
  static struct fwnode_handle *lpic_get_gsi_domain_id(u32 gsi)
@@@ -140,7 -140,10 +142,10 @@@ static int __init acpi_cascade_irqdomai
        if (r < 0)
                return r;
  
-       return 0;
+       if (cpu_has_avecint)
+               r = avecintc_acpi_init(irq_domain);
+       return r;
  }
  
  static int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
index 53cc08387588f106fb696050b8212a268e948517,12919836dadba4706eac4edb21ea284a9c2b2ca9..6f69f4e5dbacda4fb4fab04a18d433105e687ee7
@@@ -64,20 -64,6 +64,20 @@@ struct mbigen_device 
        void __iomem            *base;
  };
  
 +static inline unsigned int get_mbigen_node_offset(unsigned int nid)
 +{
 +      unsigned int offset = nid * MBIGEN_NODE_OFFSET;
 +
 +      /*
 +       * To avoid touched clear register in unexpected way, we need to directly
 +       * skip clear register when access to more than 10 mbigen nodes.
 +       */
 +      if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
 +              offset += MBIGEN_NODE_OFFSET;
 +
 +      return offset;
 +}
 +
  static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
  {
        unsigned int nid, pin;
@@@ -86,7 -72,8 +86,7 @@@
        nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
        pin = hwirq % IRQS_PER_MBIGEN_NODE;
  
 -      return pin * 4 + nid * MBIGEN_NODE_OFFSET
 -                      + REG_MBIGEN_VEC_OFFSET;
 +      return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
  }
  
  static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
        *mask = 1 << (irq_ofst % 32);
        ofst = irq_ofst / 32 * 4;
  
 -      *addr = ofst + nid * MBIGEN_NODE_OFFSET
 -              + REG_MBIGEN_TYPE_OFFSET;
 +      *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
  }
  
  static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
@@@ -234,37 -222,27 +234,27 @@@ static int mbigen_of_create_domain(stru
                                   struct mbigen_device *mgn_chip)
  {
        struct platform_device *child;
-       struct device_node *np;
        u32 num_pins;
-       int ret = 0;
  
-       for_each_child_of_node(pdev->dev.of_node, np) {
+       for_each_child_of_node_scoped(pdev->dev.of_node, np) {
                if (!of_property_read_bool(np, "interrupt-controller"))
                        continue;
  
                child = of_platform_device_create(np, NULL, NULL);
-               if (!child) {
-                       ret = -ENOMEM;
-                       break;
-               }
+               if (!child)
+                       return -ENOMEM;
  
                if (of_property_read_u32(child->dev.of_node, "num-pins",
                                         &num_pins) < 0) {
                        dev_err(&pdev->dev, "No num-pins property\n");
-                       ret = -EINVAL;
-                       break;
+                       return -EINVAL;
                }
  
-               if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip)) {
-                       ret = -ENOMEM;
-                       break;
-               }
+               if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip))
+                       return -ENOMEM;
        }
  
-       if (ret)
-               of_node_put(np);
-       return ret;
+       return 0;
  }
  
  #ifdef CONFIG_ACPI
index 9316c39260e0e43d92ef0cbbf9f44dc9c9d18bee,55a726d317d451b7d36a89f7537a014219dbad41..f39186738d81b3024805e62b39aeac1f34728545
@@@ -100,6 -100,7 +100,6 @@@ enum cpuhp_state 
        CPUHP_WORKQUEUE_PREP,
        CPUHP_POWER_NUMA_PREPARE,
        CPUHP_HRTIMERS_PREPARE,
 -      CPUHP_PROFILE_PREPARE,
        CPUHP_X2APIC_PREPARE,
        CPUHP_SMPCFD_PREPARE,
        CPUHP_RELAY_PREPARE,
        CPUHP_AP_IRQ_ARMADA_XP_STARTING,
        CPUHP_AP_IRQ_BCM2836_STARTING,
        CPUHP_AP_IRQ_MIPS_GIC_STARTING,
-       CPUHP_AP_IRQ_LOONGARCH_STARTING,
+       CPUHP_AP_IRQ_EIOINTC_STARTING,
+       CPUHP_AP_IRQ_AVECINTC_STARTING,
        CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
        CPUHP_AP_IRQ_RISCV_IMSIC_STARTING,
 +      CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING,
        CPUHP_AP_ARM_MVEBU_COHERENCY,
        CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
        CPUHP_AP_PERF_X86_STARTING,
diff --combined net/core/dev.c
index 1e740faf9e783b047b2dc7d9fd4242e4e6c7317a,e24a3bcb496de7e35460cabe63e2112c5227c3a8..cd479f5f22f61c316cb236632eea73d5924c3156
  #include <net/page_pool/types.h>
  #include <net/page_pool/helpers.h>
  #include <net/rps.h>
 +#include <linux/phy_link_topology.h>
  
  #include "dev.h"
 +#include "devmem.h"
  #include "net-sysfs.h"
  
  static DEFINE_SPINLOCK(ptype_lock);
@@@ -3312,10 -3310,6 +3312,10 @@@ int skb_checksum_help(struct sk_buff *s
                return -EINVAL;
        }
  
 +      if (!skb_frags_readable(skb)) {
 +              return -EFAULT;
 +      }
 +
        /* Before computing a checksum, we should make sure no frag could
         * be modified by an external entity : checksum could be wrong.
         */
@@@ -3392,7 -3386,6 +3392,7 @@@ int skb_crc32c_csum_help(struct sk_buf
  out:
        return ret;
  }
 +EXPORT_SYMBOL(skb_crc32c_csum_help);
  
  __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
  {
@@@ -3438,9 -3431,8 +3438,9 @@@ static int illegal_highdma(struct net_d
        if (!(dev->features & NETIF_F_HIGHDMA)) {
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 +                      struct page *page = skb_frag_page(frag);
  
 -                      if (PageHighMem(skb_frag_page(frag)))
 +                      if (page && PageHighMem(page))
                                return 1;
                }
        }
@@@ -3713,7 -3705,7 +3713,7 @@@ struct sk_buff *validate_xmit_skb_list(
                next = skb->next;
                skb_mark_not_on_list(skb);
  
 -              /* in case skb wont be segmented, point to itself */
 +              /* in case skb won't be segmented, point to itself */
                skb->prev = skb;
  
                skb = validate_xmit_skb(skb, dev, again);
@@@ -4253,6 -4245,13 +4253,6 @@@ u16 dev_pick_tx_zero(struct net_device 
  }
  EXPORT_SYMBOL(dev_pick_tx_zero);
  
 -u16 dev_pick_tx_cpu_id(struct net_device *dev, struct sk_buff *skb,
 -                     struct net_device *sb_dev)
 -{
 -      return (u16)raw_smp_processor_id() % dev->real_num_tx_queues;
 -}
 -EXPORT_SYMBOL(dev_pick_tx_cpu_id);
 -
  u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb,
                     struct net_device *sb_dev)
  {
@@@ -5151,7 -5150,6 +5151,7 @@@ int do_xdp_generic(struct bpf_prog *xdp
                        bpf_net_ctx_clear(bpf_net_ctx);
                        return XDP_DROP;
                }
 +              bpf_net_ctx_clear(bpf_net_ctx);
        }
        return XDP_PASS;
  out_redir:
@@@ -5249,7 -5247,7 +5249,7 @@@ int netif_rx(struct sk_buff *skb
  }
  EXPORT_SYMBOL(netif_rx);
  
- static __latent_entropy void net_tx_action(struct softirq_action *h)
+ static __latent_entropy void net_tx_action(void)
  {
        struct softnet_data *sd = this_cpu_ptr(&softnet_data);
  
@@@ -5726,9 -5724,10 +5726,9 @@@ static void __netif_receive_skb_list_co
        struct packet_type *pt_curr = NULL;
        /* Current (common) orig_dev of sublist */
        struct net_device *od_curr = NULL;
 -      struct list_head sublist;
        struct sk_buff *skb, *next;
 +      LIST_HEAD(sublist);
  
 -      INIT_LIST_HEAD(&sublist);
        list_for_each_entry_safe(skb, next, head, list) {
                struct net_device *orig_dev = skb->dev;
                struct packet_type *pt_prev = NULL;
@@@ -5866,8 -5865,9 +5866,8 @@@ static int netif_receive_skb_internal(s
  void netif_receive_skb_list_internal(struct list_head *head)
  {
        struct sk_buff *skb, *next;
 -      struct list_head sublist;
 +      LIST_HEAD(sublist);
  
 -      INIT_LIST_HEAD(&sublist);
        list_for_each_entry_safe(skb, next, head, list) {
                net_timestamp_check(READ_ONCE(net_hotdata.tstamp_prequeue),
                                    skb);
@@@ -6920,7 -6920,7 +6920,7 @@@ static int napi_threaded_poll(void *dat
        return 0;
  }
  
- static __latent_entropy void net_rx_action(struct softirq_action *h)
+ static __latent_entropy void net_rx_action(void)
  {
        struct softnet_data *sd = this_cpu_ptr(&softnet_data);
        unsigned long time_limit = jiffies +
@@@ -9271,7 -9271,7 +9271,7 @@@ EXPORT_SYMBOL(netdev_port_same_parent_i
   */
  int dev_change_proto_down(struct net_device *dev, bool proto_down)
  {
 -      if (!(dev->priv_flags & IFF_CHANGE_PROTO_DOWN))
 +      if (!dev->change_proto_down)
                return -EOPNOTSUPP;
        if (!netif_device_present(dev))
                return -ENODEV;
@@@ -9368,20 -9368,6 +9368,20 @@@ u8 dev_xdp_prog_count(struct net_devic
  }
  EXPORT_SYMBOL_GPL(dev_xdp_prog_count);
  
 +int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
 +{
 +      if (!dev->netdev_ops->ndo_bpf)
 +              return -EOPNOTSUPP;
 +
 +      if (dev_get_min_mp_channel_count(dev)) {
 +              NL_SET_ERR_MSG(bpf->extack, "unable to propagate XDP to device using memory provider");
 +              return -EBUSY;
 +      }
 +
 +      return dev->netdev_ops->ndo_bpf(dev, bpf);
 +}
 +EXPORT_SYMBOL_GPL(dev_xdp_propagate);
 +
  u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
  {
        struct bpf_prog *prog = dev_xdp_prog(dev, mode);
@@@ -9410,11 -9396,6 +9410,11 @@@ static int dev_xdp_install(struct net_d
        struct netdev_bpf xdp;
        int err;
  
 +      if (dev_get_min_mp_channel_count(dev)) {
 +              NL_SET_ERR_MSG(extack, "unable to install XDP to device using memory provider");
 +              return -EBUSY;
 +      }
 +
        memset(&xdp, 0, sizeof(xdp));
        xdp.command = mode == XDP_MODE_HW ? XDP_SETUP_PROG_HW : XDP_SETUP_PROG;
        xdp.extack = extack;
@@@ -9839,20 -9820,6 +9839,20 @@@ err_out
        return err;
  }
  
 +u32 dev_get_min_mp_channel_count(const struct net_device *dev)
 +{
 +      int i;
 +
 +      ASSERT_RTNL();
 +
 +      for (i = dev->real_num_rx_queues - 1; i >= 0; i--)
 +              if (dev->_rx[i].mp_params.mp_priv)
 +                      /* The channel count is the idx plus 1. */
 +                      return i + 1;
 +
 +      return 0;
 +}
 +
  /**
   * dev_index_reserve() - allocate an ifindex in a namespace
   * @net: the applicable net namespace
@@@ -9944,15 -9911,6 +9944,15 @@@ static void netdev_sync_lower_features(
        }
  }
  
 +static bool netdev_has_ip_or_hw_csum(netdev_features_t features)
 +{
 +      netdev_features_t ip_csum_mask = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 +      bool ip_csum = (features & ip_csum_mask) == ip_csum_mask;
 +      bool hw_csum = features & NETIF_F_HW_CSUM;
 +
 +      return ip_csum || hw_csum;
 +}
 +
  static netdev_features_t netdev_fix_features(struct net_device *dev,
        netdev_features_t features)
  {
                features &= ~NETIF_F_LRO;
        }
  
 -      if (features & NETIF_F_HW_TLS_TX) {
 -              bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) ==
 -                      (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 -              bool hw_csum = features & NETIF_F_HW_CSUM;
 -
 -              if (!ip_csum && !hw_csum) {
 -                      netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
 -                      features &= ~NETIF_F_HW_TLS_TX;
 -              }
 +      if ((features & NETIF_F_HW_TLS_TX) && !netdev_has_ip_or_hw_csum(features)) {
 +              netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
 +              features &= ~NETIF_F_HW_TLS_TX;
        }
  
        if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) {
                features &= ~NETIF_F_HW_TLS_RX;
        }
  
 +      if ((features & NETIF_F_GSO_UDP_L4) && !netdev_has_ip_or_hw_csum(features)) {
 +              netdev_dbg(dev, "Dropping USO feature since no CSUM feature.\n");
 +              features &= ~NETIF_F_GSO_UDP_L4;
 +      }
 +
        return features;
  }
  
@@@ -10353,17 -10312,6 +10353,17 @@@ static void netdev_do_free_pcpu_stats(s
        }
  }
  
 +static void netdev_free_phy_link_topology(struct net_device *dev)
 +{
 +      struct phy_link_topology *topo = dev->link_topo;
 +
 +      if (IS_ENABLED(CONFIG_PHYLIB) && topo) {
 +              xa_destroy(&topo->phys);
 +              kfree(topo);
 +              dev->link_topo = NULL;
 +      }
 +}
 +
  /**
   * register_netdevice() - register a network device
   * @dev: device to register
@@@ -10911,7 -10859,7 +10911,7 @@@ noinline void netdev_core_stats_inc(str
                        return;
        }
  
 -      field = (__force unsigned long __percpu *)((__force void *)p + offset);
 +      field = (unsigned long __percpu *)((void __percpu *)p + offset);
        this_cpu_inc(*field);
  }
  EXPORT_SYMBOL_GPL(netdev_core_stats_inc);
@@@ -11142,7 -11090,6 +11142,7 @@@ struct net_device *alloc_netdev_mqs(in
  #ifdef CONFIG_NET_SCHED
        hash_init(dev->qdisc_hash);
  #endif
 +
        dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
        setup(dev);
  
        if (!dev->ethtool)
                goto free_all;
  
 -      strcpy(dev->name, name);
 +      strscpy(dev->name, name);
        dev->name_assign_type = name_assign_type;
        dev->group = INIT_NETDEV_GROUP;
        if (!dev->ethtool_ops)
@@@ -11235,8 -11182,6 +11235,8 @@@ void free_netdev(struct net_device *dev
        free_percpu(dev->xdp_bulkq);
        dev->xdp_bulkq = NULL;
  
 +      netdev_free_phy_link_topology(dev);
 +
        /*  Compatibility with error handling in drivers */
        if (dev->reg_state == NETREG_UNINITIALIZED ||
            dev->reg_state == NETREG_DUMMY) {
@@@ -11389,7 -11334,6 +11389,7 @@@ void unregister_netdevice_many_notify(s
                dev_tcx_uninstall(dev);
                dev_xdp_uninstall(dev);
                bpf_dev_bound_netdev_unregister(dev);
 +              dev_dmabuf_uninstall(dev);
  
                netdev_offload_xstats_disable_all(dev);
  
   *    @head: list of devices
   *
   *  Note: As most callers use a stack allocated list_head,
 - *  we force a list_del() to make sure stack wont be corrupted later.
 + *  we force a list_del() to make sure stack won't be corrupted later.
   */
  void unregister_netdevice_many(struct list_head *head)
  {
@@@ -11509,10 -11453,10 +11509,10 @@@ int __dev_change_net_namespace(struct n
  
        /* Don't allow namespace local devices to be moved. */
        err = -EINVAL;
 -      if (dev->features & NETIF_F_NETNS_LOCAL)
 +      if (dev->netns_local)
                goto out;
  
 -      /* Ensure the device has been registrered */
 +      /* Ensure the device has been registered */
        if (dev->reg_state != NETREG_REGISTERED)
                goto out;
  
@@@ -11891,7 -11835,7 +11891,7 @@@ static void __net_exit default_device_e
                char fb_name[IFNAMSIZ];
  
                /* Ignore unmoveable devices (i.e. loopback) */
 -              if (dev->features & NETIF_F_NETNS_LOCAL)
 +              if (dev->netns_local)
                        continue;
  
                /* Leave virtual devices for the generic cleanup */
@@@ -11952,7 -11896,7 +11952,7 @@@ static struct pernet_operations __net_i
  static void __init net_dev_struct_check(void)
  {
        /* TX read-mostly hotpath */
 -      CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, priv_flags);
 +      CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, priv_flags_fast);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, netdev_ops);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, header_ops);
        CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, _tx);
This page took 0.141015 seconds and 4 git commands to generate.