]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 08:30:42 +0000 (09:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 08:30:42 +0000 (09:30 +0100)
added patches:
ata-sata_highbank-fix-of-node-reference-leak-in-highbank_initialize_phys.patch
bpf-revert-bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch
scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch
usb-dwc2-fix-hcd-port-connection-race.patch
usb-dwc2-fix-hcd-resume.patch
usb-dwc2-hcd-fix-getportstatus-setportfeature.patch

queue-6.12/ata-sata_highbank-fix-of-node-reference-leak-in-highbank_initialize_phys.patch [new file with mode: 0644]
queue-6.12/bpf-revert-bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch [new file with mode: 0644]
queue-6.12/scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/usb-dwc2-fix-hcd-port-connection-race.patch [new file with mode: 0644]
queue-6.12/usb-dwc2-fix-hcd-resume.patch [new file with mode: 0644]
queue-6.12/usb-dwc2-hcd-fix-getportstatus-setportfeature.patch [new file with mode: 0644]

diff --git a/queue-6.12/ata-sata_highbank-fix-of-node-reference-leak-in-highbank_initialize_phys.patch b/queue-6.12/ata-sata_highbank-fix-of-node-reference-leak-in-highbank_initialize_phys.patch
new file mode 100644 (file)
index 0000000..fc72738
--- /dev/null
@@ -0,0 +1,30 @@
+From 676fe1f6f74db988191dab5df3bf256908177072 Mon Sep 17 00:00:00 2001
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Date: Thu, 5 Dec 2024 19:30:14 +0900
+Subject: ata: sata_highbank: fix OF node reference leak in highbank_initialize_phys()
+
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+
+commit 676fe1f6f74db988191dab5df3bf256908177072 upstream.
+
+The OF node reference obtained by of_parse_phandle_with_args() is not
+released on early return. Add a of_node_put() call before returning.
+
+Fixes: 8996b89d6bc9 ("ata: add platform driver for Calxeda AHCI controller")
+Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/sata_highbank.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/ata/sata_highbank.c
++++ b/drivers/ata/sata_highbank.c
+@@ -348,6 +348,7 @@ static int highbank_initialize_phys(stru
+                       phy_nodes[phy] = phy_data.np;
+                       cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
+                       if (cphy_base[phy] == NULL) {
++                              of_node_put(phy_data.np);
+                               return 0;
+                       }
+                       phy_count += 1;
diff --git a/queue-6.12/bpf-revert-bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch b/queue-6.12/bpf-revert-bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch
new file mode 100644 (file)
index 0000000..ae49390
--- /dev/null
@@ -0,0 +1,331 @@
+From c00d738e1673ab801e1577e4e3c780ccf88b1a5b Mon Sep 17 00:00:00 2001
+From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Date: Fri, 13 Dec 2024 14:19:27 -0800
+Subject: bpf: Revert "bpf: Mark raw_tp arguments with PTR_MAYBE_NULL"
+
+From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+
+commit c00d738e1673ab801e1577e4e3c780ccf88b1a5b upstream.
+
+This patch reverts commit
+cb4158ce8ec8 ("bpf: Mark raw_tp arguments with PTR_MAYBE_NULL"). The
+patch was well-intended and meant to be as a stop-gap fixing branch
+prediction when the pointer may actually be NULL at runtime. Eventually,
+it was supposed to be replaced by an automated script or compiler pass
+detecting possibly NULL arguments and marking them accordingly.
+
+However, it caused two main issues observed for production programs and
+failed to preserve backwards compatibility. First, programs relied on
+the verifier not exploring == NULL branch when pointer is not NULL, thus
+they started failing with a 'dereference of scalar' error.  Next,
+allowing raw_tp arguments to be modified surfaced the warning in the
+verifier that warns against reg->off when PTR_MAYBE_NULL is set.
+
+More information, context, and discusson on both problems is available
+in [0]. Overall, this approach had several shortcomings, and the fixes
+would further complicate the verifier's logic, and the entire masking
+scheme would have to be removed eventually anyway.
+
+Hence, revert the patch in preparation of a better fix avoiding these
+issues to replace this commit.
+
+  [0]: https://lore.kernel.org/bpf/20241206161053.809580-1-memxor@gmail.com
+
+Reported-by: Manu Bretelle <chantra@meta.com>
+Fixes: cb4158ce8ec8 ("bpf: Mark raw_tp arguments with PTR_MAYBE_NULL")
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://lore.kernel.org/r/20241213221929.3495062-2-memxor@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/bpf.h                                      |    6 -
+ kernel/bpf/btf.c                                         |    5 
+ kernel/bpf/verifier.c                                    |   79 +--------------
+ tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c |    6 -
+ 4 files changed, 9 insertions(+), 87 deletions(-)
+
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -3471,10 +3471,4 @@ static inline bool bpf_is_subprog(const
+       return prog->aux->func_idx != 0;
+ }
+-static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog)
+-{
+-      return prog->type == BPF_PROG_TYPE_TRACING &&
+-             prog->expected_attach_type == BPF_TRACE_RAW_TP;
+-}
+-
+ #endif /* _LINUX_BPF_H */
+--- a/kernel/bpf/btf.c
++++ b/kernel/bpf/btf.c
+@@ -6564,10 +6564,7 @@ bool btf_ctx_access(int off, int size, e
+       if (prog_args_trusted(prog))
+               info->reg_type |= PTR_TRUSTED;
+-      /* Raw tracepoint arguments always get marked as maybe NULL */
+-      if (bpf_prog_is_raw_tp(prog))
+-              info->reg_type |= PTR_MAYBE_NULL;
+-      else if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
++      if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
+               info->reg_type |= PTR_MAYBE_NULL;
+       if (tgt_prog) {
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -418,25 +418,6 @@ static struct btf_record *reg_btf_record
+       return rec;
+ }
+-static bool mask_raw_tp_reg_cond(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) {
+-      return reg->type == (PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL) &&
+-             bpf_prog_is_raw_tp(env->prog) && !reg->ref_obj_id;
+-}
+-
+-static bool mask_raw_tp_reg(const struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+-{
+-      if (!mask_raw_tp_reg_cond(env, reg))
+-              return false;
+-      reg->type &= ~PTR_MAYBE_NULL;
+-      return true;
+-}
+-
+-static void unmask_raw_tp_reg(struct bpf_reg_state *reg, bool result)
+-{
+-      if (result)
+-              reg->type |= PTR_MAYBE_NULL;
+-}
+-
+ static bool subprog_is_global(const struct bpf_verifier_env *env, int subprog)
+ {
+       struct bpf_func_info_aux *aux = env->prog->aux->func_info_aux;
+@@ -6618,7 +6599,6 @@ static int check_ptr_to_btf_access(struc
+       const char *field_name = NULL;
+       enum bpf_type_flag flag = 0;
+       u32 btf_id = 0;
+-      bool mask;
+       int ret;
+       if (!env->allow_ptr_leaks) {
+@@ -6690,21 +6670,7 @@ static int check_ptr_to_btf_access(struc
+       if (ret < 0)
+               return ret;
+-      /* For raw_tp progs, we allow dereference of PTR_MAYBE_NULL
+-       * trusted PTR_TO_BTF_ID, these are the ones that are possibly
+-       * arguments to the raw_tp. Since internal checks in for trusted
+-       * reg in check_ptr_to_btf_access would consider PTR_MAYBE_NULL
+-       * modifier as problematic, mask it out temporarily for the
+-       * check. Don't apply this to pointers with ref_obj_id > 0, as
+-       * those won't be raw_tp args.
+-       *
+-       * We may end up applying this relaxation to other trusted
+-       * PTR_TO_BTF_ID with maybe null flag, since we cannot
+-       * distinguish PTR_MAYBE_NULL tagged for arguments vs normal
+-       * tagging, but that should expand allowed behavior, and not
+-       * cause regression for existing behavior.
+-       */
+-      mask = mask_raw_tp_reg(env, reg);
++
+       if (ret != PTR_TO_BTF_ID) {
+               /* just mark; */
+@@ -6765,13 +6731,8 @@ static int check_ptr_to_btf_access(struc
+               clear_trusted_flags(&flag);
+       }
+-      if (atype == BPF_READ && value_regno >= 0) {
++      if (atype == BPF_READ && value_regno >= 0)
+               mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
+-              /* We've assigned a new type to regno, so don't undo masking. */
+-              if (regno == value_regno)
+-                      mask = false;
+-      }
+-      unmask_raw_tp_reg(reg, mask);
+       return 0;
+ }
+@@ -7146,7 +7107,7 @@ static int check_mem_access(struct bpf_v
+               if (!err && t == BPF_READ && value_regno >= 0)
+                       mark_reg_unknown(env, regs, value_regno);
+       } else if (base_type(reg->type) == PTR_TO_BTF_ID &&
+-                 (mask_raw_tp_reg_cond(env, reg) || !type_may_be_null(reg->type))) {
++                 !type_may_be_null(reg->type)) {
+               err = check_ptr_to_btf_access(env, regs, regno, off, size, t,
+                                             value_regno);
+       } else if (reg->type == CONST_PTR_TO_MAP) {
+@@ -8844,7 +8805,6 @@ static int check_func_arg(struct bpf_ver
+       enum bpf_reg_type type = reg->type;
+       u32 *arg_btf_id = NULL;
+       int err = 0;
+-      bool mask;
+       if (arg_type == ARG_DONTCARE)
+               return 0;
+@@ -8885,11 +8845,11 @@ static int check_func_arg(struct bpf_ver
+           base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK)
+               arg_btf_id = fn->arg_btf_id[arg];
+-      mask = mask_raw_tp_reg(env, reg);
+       err = check_reg_type(env, regno, arg_type, arg_btf_id, meta);
++      if (err)
++              return err;
+-      err = err ?: check_func_arg_reg_off(env, reg, regno, arg_type);
+-      unmask_raw_tp_reg(reg, mask);
++      err = check_func_arg_reg_off(env, reg, regno, arg_type);
+       if (err)
+               return err;
+@@ -9684,17 +9644,14 @@ static int btf_check_func_arg_match(stru
+                               return ret;
+               } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
+                       struct bpf_call_arg_meta meta;
+-                      bool mask;
+                       int err;
+                       if (register_is_null(reg) && type_may_be_null(arg->arg_type))
+                               continue;
+                       memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */
+-                      mask = mask_raw_tp_reg(env, reg);
+                       err = check_reg_type(env, regno, arg->arg_type, &arg->btf_id, &meta);
+                       err = err ?: check_func_arg_reg_off(env, reg, regno, arg->arg_type);
+-                      unmask_raw_tp_reg(reg, mask);
+                       if (err)
+                               return err;
+               } else {
+@@ -12009,7 +11966,6 @@ static int check_kfunc_args(struct bpf_v
+               enum bpf_arg_type arg_type = ARG_DONTCARE;
+               u32 regno = i + 1, ref_id, type_size;
+               bool is_ret_buf_sz = false;
+-              bool mask = false;
+               int kf_arg_type;
+               t = btf_type_skip_modifiers(btf, args[i].type, NULL);
+@@ -12068,15 +12024,12 @@ static int check_kfunc_args(struct bpf_v
+                       return -EINVAL;
+               }
+-              mask = mask_raw_tp_reg(env, reg);
+               if ((is_kfunc_trusted_args(meta) || is_kfunc_rcu(meta)) &&
+                   (register_is_null(reg) || type_may_be_null(reg->type)) &&
+                       !is_kfunc_arg_nullable(meta->btf, &args[i])) {
+                       verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i);
+-                      unmask_raw_tp_reg(reg, mask);
+                       return -EACCES;
+               }
+-              unmask_raw_tp_reg(reg, mask);
+               if (reg->ref_obj_id) {
+                       if (is_kfunc_release(meta) && meta->ref_obj_id) {
+@@ -12134,24 +12087,16 @@ static int check_kfunc_args(struct bpf_v
+                       if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta))
+                               break;
+-                      /* Allow passing maybe NULL raw_tp arguments to
+-                       * kfuncs for compatibility. Don't apply this to
+-                       * arguments with ref_obj_id > 0.
+-                       */
+-                      mask = mask_raw_tp_reg(env, reg);
+                       if (!is_trusted_reg(reg)) {
+                               if (!is_kfunc_rcu(meta)) {
+                                       verbose(env, "R%d must be referenced or trusted\n", regno);
+-                                      unmask_raw_tp_reg(reg, mask);
+                                       return -EINVAL;
+                               }
+                               if (!is_rcu_reg(reg)) {
+                                       verbose(env, "R%d must be a rcu pointer\n", regno);
+-                                      unmask_raw_tp_reg(reg, mask);
+                                       return -EINVAL;
+                               }
+                       }
+-                      unmask_raw_tp_reg(reg, mask);
+                       fallthrough;
+               case KF_ARG_PTR_TO_CTX:
+               case KF_ARG_PTR_TO_DYNPTR:
+@@ -12174,9 +12119,7 @@ static int check_kfunc_args(struct bpf_v
+               if (is_kfunc_release(meta) && reg->ref_obj_id)
+                       arg_type |= OBJ_RELEASE;
+-              mask = mask_raw_tp_reg(env, reg);
+               ret = check_func_arg_reg_off(env, reg, regno, arg_type);
+-              unmask_raw_tp_reg(reg, mask);
+               if (ret < 0)
+                       return ret;
+@@ -12353,7 +12296,6 @@ static int check_kfunc_args(struct bpf_v
+                       ref_tname = btf_name_by_offset(btf, ref_t->name_off);
+                       fallthrough;
+               case KF_ARG_PTR_TO_BTF_ID:
+-                      mask = mask_raw_tp_reg(env, reg);
+                       /* Only base_type is checked, further checks are done here */
+                       if ((base_type(reg->type) != PTR_TO_BTF_ID ||
+                            (bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) &&
+@@ -12362,11 +12304,9 @@ static int check_kfunc_args(struct bpf_v
+                               verbose(env, "expected %s or socket\n",
+                                       reg_type_str(env, base_type(reg->type) |
+                                                         (type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS)));
+-                              unmask_raw_tp_reg(reg, mask);
+                               return -EINVAL;
+                       }
+                       ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i);
+-                      unmask_raw_tp_reg(reg, mask);
+                       if (ret < 0)
+                               return ret;
+                       break;
+@@ -13336,7 +13276,7 @@ static int sanitize_check_bounds(struct
+  */
+ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+                                  struct bpf_insn *insn,
+-                                 struct bpf_reg_state *ptr_reg,
++                                 const struct bpf_reg_state *ptr_reg,
+                                  const struct bpf_reg_state *off_reg)
+ {
+       struct bpf_verifier_state *vstate = env->cur_state;
+@@ -13350,7 +13290,6 @@ static int adjust_ptr_min_max_vals(struc
+       struct bpf_sanitize_info info = {};
+       u8 opcode = BPF_OP(insn->code);
+       u32 dst = insn->dst_reg;
+-      bool mask;
+       int ret;
+       dst_reg = &regs[dst];
+@@ -13377,14 +13316,11 @@ static int adjust_ptr_min_max_vals(struc
+               return -EACCES;
+       }
+-      mask = mask_raw_tp_reg(env, ptr_reg);
+       if (ptr_reg->type & PTR_MAYBE_NULL) {
+               verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n",
+                       dst, reg_type_str(env, ptr_reg->type));
+-              unmask_raw_tp_reg(ptr_reg, mask);
+               return -EACCES;
+       }
+-      unmask_raw_tp_reg(ptr_reg, mask);
+       switch (base_type(ptr_reg->type)) {
+       case PTR_TO_CTX:
+@@ -19934,7 +19870,6 @@ static int convert_ctx_accesses(struct b
+                * for this case.
+                */
+               case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED:
+-              case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL:
+                       if (type == BPF_READ) {
+                               if (BPF_MODE(insn->code) == BPF_MEM)
+                                       insn->code = BPF_LDX | BPF_PROBE_MEM |
+--- a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
++++ b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
+@@ -7,11 +7,7 @@
+ #include "bpf_misc.h"
+ SEC("tp_btf/bpf_testmod_test_nullable_bare")
+-/* This used to be a failure test, but raw_tp nullable arguments can now
+- * directly be dereferenced, whether they have nullable annotation or not,
+- * and don't need to be explicitly checked.
+- */
+-__success
++__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
+ int BPF_PROG(handle_tp_btf_nullable_bare1, struct bpf_testmod_test_read_ctx *nullable_ctx)
+ {
+       return nullable_ctx->len;
diff --git a/queue-6.12/scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch b/queue-6.12/scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch
new file mode 100644 (file)
index 0000000..e1a2fc9
--- /dev/null
@@ -0,0 +1,42 @@
+From f103396ae31851d00b561ff9f8a32a441953ff8b Mon Sep 17 00:00:00 2001
+From: liuderong <liuderong@oppo.com>
+Date: Fri, 6 Dec 2024 15:29:42 +0800
+Subject: scsi: ufs: core: Update compl_time_stamp_local_clock after completing a cqe
+
+From: liuderong <liuderong@oppo.com>
+
+commit f103396ae31851d00b561ff9f8a32a441953ff8b upstream.
+
+lrbp->compl_time_stamp_local_clock is set to zero after sending a sqe
+but it is not updated after completing a cqe.  Thus the printed
+information in ufshcd_print_tr() will always be zero.
+
+Update lrbp->cmpl_time_stamp_local_clock after completing a cqe.
+
+Log sample:
+
+ufshcd-qcom 1d84000.ufshc: UPIU[8] - issue time 8750227249 us
+ufshcd-qcom 1d84000.ufshc: UPIU[8] - complete time 0 us
+
+Fixes: c30d8d010b5e ("scsi: ufs: core: Prepare for completion in MCQ")
+Reviewed-by: Bean Huo <beanhuo@micron.com>
+Reviewed-by: Peter Wang <peter.wang@mediatek.com>
+Signed-off-by: liuderong <liuderong@oppo.com>
+Link: https://lore.kernel.org/r/1733470182-220841-1-git-send-email-liuderong@oppo.com
+Reviewed-by: Avri Altman <avri.altman@wdc.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ufs/core/ufshcd.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -5566,6 +5566,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba
+       lrbp = &hba->lrb[task_tag];
+       lrbp->compl_time_stamp = ktime_get();
++      lrbp->compl_time_stamp_local_clock = local_clock();
+       cmd = lrbp->cmd;
+       if (cmd) {
+               if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
index 1671f9c33d692350384b2c9aa45cd35eab8ad4c0..930df99310c95f902c3f0db89f77e2f175792b5a 100644 (file)
@@ -36,3 +36,9 @@ gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch
 gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch
 gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch
 usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch
+bpf-revert-bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch
+ata-sata_highbank-fix-of-node-reference-leak-in-highbank_initialize_phys.patch
+usb-dwc2-fix-hcd-resume.patch
+usb-dwc2-hcd-fix-getportstatus-setportfeature.patch
+usb-dwc2-fix-hcd-port-connection-race.patch
+scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch
diff --git a/queue-6.12/usb-dwc2-fix-hcd-port-connection-race.patch b/queue-6.12/usb-dwc2-fix-hcd-port-connection-race.patch
new file mode 100644 (file)
index 0000000..c01e9e2
--- /dev/null
@@ -0,0 +1,68 @@
+From 1cf1bd88f129f3bd647fead4dca270a5894274bb Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 2 Dec 2024 01:16:31 +0100
+Subject: usb: dwc2: Fix HCD port connection race
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+commit 1cf1bd88f129f3bd647fead4dca270a5894274bb upstream.
+
+On Raspberry Pis without onboard USB hub frequent device reconnects
+can trigger a interrupt storm after DWC2 entered host clock gating.
+This is caused by a race between _dwc2_hcd_suspend() and the port
+interrupt, which sets port_connect_status. The issue occurs if
+port_connect_status is still 1, but there is no connection anymore:
+
+usb 1-1: USB disconnect, device number 25
+dwc2 3f980000.usb: _dwc2_hcd_suspend: port_connect_status: 1
+dwc2 3f980000.usb: Entering host clock gating.
+Disabling IRQ #66
+irq 66: nobody cared (try booting with the "irqpoll" option)
+CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.12.0-gc1bb81b13202-dirty #322
+Hardware name: BCM2835
+Call trace:
+ unwind_backtrace from show_stack+0x10/0x14
+ show_stack from dump_stack_lvl+0x50/0x64
+ dump_stack_lvl from __report_bad_irq+0x38/0xc0
+ __report_bad_irq from note_interrupt+0x2ac/0x2f4
+ note_interrupt from handle_irq_event+0x88/0x8c
+ handle_irq_event from handle_level_irq+0xb4/0x1ac
+ handle_level_irq from generic_handle_domain_irq+0x24/0x34
+ generic_handle_domain_irq from bcm2836_chained_handle_irq+0x24/0x28
+ bcm2836_chained_handle_irq from generic_handle_domain_irq+0x24/0x34
+ generic_handle_domain_irq from generic_handle_arch_irq+0x34/0x44
+ generic_handle_arch_irq from __irq_svc+0x88/0xb0
+ Exception stack(0xc1d01f20 to 0xc1d01f68)
+ 1f20: 0004ef3c 00000001 00000000 00000000 c1d09780 c1f6bb5c c1d04e54 c1c60ca8
+ 1f40: c1d04e94 00000000 00000000 c1d092a8 c1f6af20 c1d01f70 c1211b98 c1212f40
+ 1f60: 60000013 ffffffff
+ __irq_svc from default_idle_call+0x1c/0xb0
+ default_idle_call from do_idle+0x21c/0x284
+ do_idle from cpu_startup_entry+0x28/0x2c
+ cpu_startup_entry from kernel_init+0x0/0x12c
+handlers:
+ [<e3a25c00>] dwc2_handle_common_intr
+ [<58bf98a3>] usb_hcd_irq
+Disabling IRQ #66
+
+So avoid this by reading the connection status directly.
+
+Fixes: 113f86d0c302 ("usb: dwc2: Update partial power down entering by system suspend")
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Link: https://lore.kernel.org/r/20241202001631.75473-4-wahrenst@gmx.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/hcd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -4345,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_
+       if (hsotg->bus_suspended)
+               goto skip_power_saving;
+-      if (hsotg->flags.b.port_connect_status == 0)
++      if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
+               goto skip_power_saving;
+       switch (hsotg->params.power_down) {
diff --git a/queue-6.12/usb-dwc2-fix-hcd-resume.patch b/queue-6.12/usb-dwc2-fix-hcd-resume.patch
new file mode 100644 (file)
index 0000000..09d6c69
--- /dev/null
@@ -0,0 +1,71 @@
+From 336f72d3cbf5cc17df2947bbbd2ba6e2509f17e8 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 2 Dec 2024 01:16:29 +0100
+Subject: usb: dwc2: Fix HCD resume
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+commit 336f72d3cbf5cc17df2947bbbd2ba6e2509f17e8 upstream.
+
+The Raspberry Pi can suffer on interrupt storms on HCD resume. The dwc2
+driver sometimes misses to enable HCD_FLAG_HW_ACCESSIBLE before re-enabling
+the interrupts. This causes a situation where both handler ignore a incoming
+port interrupt and force the upper layers to disable the dwc2 interrupt
+line. This leaves the USB interface in a unusable state:
+
+irq 66: nobody cared (try booting with the "irqpoll" option)
+CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W          6.10.0-rc3
+Hardware name: BCM2835
+Call trace:
+unwind_backtrace from show_stack+0x10/0x14
+show_stack from dump_stack_lvl+0x50/0x64
+dump_stack_lvl from __report_bad_irq+0x38/0xc0
+__report_bad_irq from note_interrupt+0x2ac/0x2f4
+note_interrupt from handle_irq_event+0x88/0x8c
+handle_irq_event from handle_level_irq+0xb4/0x1ac
+handle_level_irq from generic_handle_domain_irq+0x24/0x34
+generic_handle_domain_irq from bcm2836_chained_handle_irq+0x24/0x28
+bcm2836_chained_handle_irq from generic_handle_domain_irq+0x24/0x34
+generic_handle_domain_irq from generic_handle_arch_irq+0x34/0x44
+generic_handle_arch_irq from __irq_svc+0x88/0xb0
+Exception stack(0xc1b01f20 to 0xc1b01f68)
+1f20: 0005c0d4 00000001 00000000 00000000 c1b09780 c1d6b32c c1b04e54 c1a5eae8
+1f40: c1b04e90 00000000 00000000 00000000 c1d6a8a0 c1b01f70 c11d2da8 c11d4160
+1f60: 60000013 ffffffff
+__irq_svc from default_idle_call+0x1c/0xb0
+default_idle_call from do_idle+0x21c/0x284
+do_idle from cpu_startup_entry+0x28/0x2c
+cpu_startup_entry from kernel_init+0x0/0x12c
+handlers:
+[<f539e0f4>] dwc2_handle_common_intr
+[<75cd278b>] usb_hcd_irq
+Disabling IRQ #66
+
+So enable the HCD_FLAG_HW_ACCESSIBLE flag in case there is a port
+connection.
+
+Fixes: c74c26f6e398 ("usb: dwc2: Fix partial power down exiting by system resume")
+Closes: https://lore.kernel.org/linux-usb/3fd0c2fb-4752-45b3-94eb-42352703e1fd@gmx.net/T/
+Link: https://lore.kernel.org/all/5e8cbce0-3260-2971-484f-fc73a3b2bd28@synopsys.com/
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Link: https://lore.kernel.org/r/20241202001631.75473-2-wahrenst@gmx.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/hcd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
+index cb54390e7de4..26a320c1979a 100644
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -4431,6 +4431,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
+        * Power Down mode.
+        */
+       if (hprt0 & HPRT0_CONNSTS) {
++              set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+               hsotg->lx_state = DWC2_L0;
+               goto unlock;
+       }
+-- 
+2.47.1
+
diff --git a/queue-6.12/usb-dwc2-hcd-fix-getportstatus-setportfeature.patch b/queue-6.12/usb-dwc2-hcd-fix-getportstatus-setportfeature.patch
new file mode 100644 (file)
index 0000000..bcd1ed5
--- /dev/null
@@ -0,0 +1,66 @@
+From a8d3e4a734599c7d0f6735f8db8a812e503395dd Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 2 Dec 2024 01:16:30 +0100
+Subject: usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+commit a8d3e4a734599c7d0f6735f8db8a812e503395dd upstream.
+
+On Rasperry Pis without onboard USB hub the power cycle during
+power connect init only disable the port but never enabled it again:
+
+  usb usb1-port1: attempt power cycle
+
+The port relevant part in dwc2_hcd_hub_control() is skipped in case
+port_connect_status = 0 under the assumption the core is or will be soon
+in device mode. But this assumption is wrong, because after ClearPortFeature
+USB_PORT_FEAT_POWER the port_connect_status will also be 0 and
+SetPortFeature (incl. USB_PORT_FEAT_POWER) will be a no-op.
+
+Fix the behavior of dwc2_hcd_hub_control() by replacing the
+port_connect_status check with dwc2_is_device_mode().
+
+Link: https://github.com/raspberrypi/linux/issues/6247
+Fixes: 7359d482eb4d ("staging: HCD files for the DWC2 driver")
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Link: https://lore.kernel.org/r/20241202001631.75473-3-wahrenst@gmx.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/hcd.c |   16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct d
+                       port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+               }
+-              if (!hsotg->flags.b.port_connect_status) {
++              if (dwc2_is_device_mode(hsotg)) {
+                       /*
+-                       * The port is disconnected, which means the core is
+-                       * either in device mode or it soon will be. Just
+-                       * return 0's for the remainder of the port status
++                       * Just return 0's for the remainder of the port status
+                        * since the port register can't be read if the core
+                        * is in device mode.
+                        */
+@@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct d
+               if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
+                       goto error;
+-              if (!hsotg->flags.b.port_connect_status) {
++              if (dwc2_is_device_mode(hsotg)) {
+                       /*
+-                       * The port is disconnected, which means the core is
+-                       * either in device mode or it soon will be. Just
+-                       * return without doing anything since the port
+-                       * register can't be written if the core is in device
+-                       * mode.
++                       * Just return 0's for the remainder of the port status
++                       * since the port register can't be read if the core
++                       * is in device mode.
+                        */
+                       break;
+               }