All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions
@ 2023-07-18 11:25 Xu Yang
  2023-07-18 11:26 ` [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule Xu Yang
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Xu Yang @ 2023-07-18 11:25 UTC (permalink / raw)
  To: stern; +Cc: gregkh, linux-usb, xu.yang_2, jun.li

This will add itd/sitd_unlink_urb() functions in case of the driver needs
to unlink these urbs manually.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 drivers/usb/host/ehci-sched.c | 94 +++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index bd542b6fc46b..b95a8bc4d3ba 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1805,6 +1805,67 @@ static void itd_link_urb(
 	enable_periodic(ehci);
 }
 
+/* unlink itd/sitd from the periodic list */
+static inline void
+unlink(struct ehci_hcd *ehci, unsigned frame, void *ptr)
+{
+	union ehci_shadow	*prev = &ehci->pshadow[frame];
+	__hc32			*hw_p = &ehci->periodic[frame];
+	union ehci_shadow	here = *prev;
+
+	while (here.ptr && here.ptr != ptr) {
+		prev = periodic_next_shadow(ehci, prev,
+			Q_NEXT_TYPE(ehci, *hw_p));
+		hw_p = shadow_next_periodic(ehci, &here,
+			Q_NEXT_TYPE(ehci, *hw_p));
+		here = *prev;
+	}
+
+	*prev = *periodic_next_shadow(ehci, &here,
+			Q_NEXT_TYPE(ehci, *hw_p));
+
+	if (!ehci->use_dummy_qh ||
+		*shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)
+		!= EHCI_LIST_END(ehci)))
+		*hw_p = *shadow_next_periodic(ehci, &here,
+					Q_NEXT_TYPE(ehci, *hw_p));
+	else
+		*hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma);
+}
+
+static void itd_unlink_urb(
+	struct ehci_hcd         *ehci,
+	struct urb              *urb
+)
+{
+	struct ehci_itd         *itd, *n;
+	struct ehci_iso_stream	*stream = urb->hcpriv;
+
+	if (unlikely(list_empty(&stream->td_list)))
+		return;
+
+	list_for_each_entry_safe(itd, n, &stream->td_list, itd_list) {
+		if (itd->urb != urb)
+			continue;
+		unlink(ehci, itd->frame, itd);
+		itd->urb = NULL;
+		list_move_tail(&itd->itd_list, &stream->free_list);
+	}
+
+	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+	if (unlikely(list_empty(&stream->td_list)))
+		ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth;
+
+	ehci_urb_done(ehci, urb, -ENOENT);
+
+	--ehci->isoc_count;
+	disable_periodic(ehci);
+
+	list_splice_tail_init(&stream->free_list,
+			&ehci->cached_itd_list);
+	start_free_itds(ehci);
+}
+
 #define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 
 /* Process and recycle a completed ITD.  Return true iff its urb completed,
@@ -2196,6 +2257,39 @@ static void sitd_link_urb(
 	enable_periodic(ehci);
 }
 
+static void sitd_unlink_urb(
+	struct ehci_hcd         *ehci,
+	struct urb              *urb
+)
+{
+	struct ehci_sitd         *sitd, *n;
+	struct ehci_iso_stream	*stream = urb->hcpriv;
+
+	if (unlikely(list_empty(&stream->td_list)))
+		return;
+
+	list_for_each_entry_safe(sitd, n, &stream->td_list, sitd_list) {
+		if (sitd->urb != urb)
+			continue;
+		unlink(ehci, sitd->frame, sitd);
+		sitd->urb = NULL;
+		list_move_tail(&sitd->sitd_list, &stream->free_list);
+	}
+
+	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+	if (unlikely(list_empty(&stream->td_list)))
+		ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth;
+
+	ehci_urb_done(ehci, urb, -ENOENT);
+
+	--ehci->isoc_count;
+	disable_periodic(ehci);
+
+	list_splice_tail_init(&stream->free_list,
+			&ehci->cached_sitd_list);
+	start_free_itds(ehci);
+}
+
 /*-------------------------------------------------------------------------*/
 
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-07-18 11:25 [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions Xu Yang
@ 2023-07-18 11:26 ` Xu Yang
  2023-07-18 14:53   ` Alan Stern
  2023-07-21  3:50 ` [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions kernel test robot
  2023-07-23 18:10 ` kernel test robot
  2 siblings, 1 reply; 10+ messages in thread
From: Xu Yang @ 2023-07-18 11:26 UTC (permalink / raw)
  To: stern; +Cc: gregkh, linux-usb, xu.yang_2, jun.li

In current design, the ehci driver will not unlink itd/sitds from the
hardware list when dequeue isochronous urbs. Rather just wait until they
complete normally or their time slot expires. However, this will cause
issues if the controller has stopped periodic schedule before finished
all periodic schedule. The urb will not be done forever in this case and
then usb_kill/poison_urb() will always wait there.

The ChipIdea IP exactly has a bug: if frame babble occurs during periodic
transfer, PE (PORTSC.bit2) will be cleared and the controller will stop
periodic schedule immediately. So if the user tries to kill or poison
related urb, it will wait there since the urb can't be done forever.

This patch will check if this issue occurs, then it will unlink itd/sitds
from the hardware list depends on the result.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 drivers/usb/host/ehci-hcd.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a1930db0da1c..26dc1d1ae5e8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -930,10 +930,41 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 
 	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
 		/*
-		 * We don't expedite dequeue for isochronous URBs.
+		 * 1. We don't expedite dequeue for isochronous URBs.
 		 * Just wait until they complete normally or their
 		 * time slot expires.
+		 *
+		 * 2. The ChipIdea IP has a bug: if frame babble occurs,
+		 * PE will be cleared and the controller will stop periodic
+		 * schedule. So if we don't force dequeue this urb, it
+		 * won't be done forever. Here, a force dequeue is needed
+		 * for this case.
 		 */
+		unsigned 		i = HCS_N_PORTS (ehci->hcs_params);
+		bool 			need_force_dequeue = false;
+
+		while (i--) {
+			int pstatus;
+
+			pstatus = ehci_readl(ehci,
+					&ehci->regs->port_status[i]);
+
+			/* Any cleared PE means controller has stopped
+			 * periodic schedule.
+			 */
+			if (!(pstatus & PORT_PE)) {
+				need_force_dequeue = true;
+				break;
+			}
+		}
+
+		if (!need_force_dequeue)
+			goto done;
+
+		if (urb->dev->speed == USB_SPEED_HIGH)
+			itd_unlink_urb(ehci, urb);
+		else
+			sitd_unlink_urb(ehci, urb);
 	} else {
 		qh = (struct ehci_qh *) urb->hcpriv;
 		qh->unlink_reason |= QH_UNLINK_REQUESTED;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-07-18 11:26 ` [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule Xu Yang
@ 2023-07-18 14:53   ` Alan Stern
  2023-07-29  6:55     ` [EXT] " Xu Yang
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2023-07-18 14:53 UTC (permalink / raw)
  To: Xu Yang; +Cc: gregkh, linux-usb, jun.li

On Tue, Jul 18, 2023 at 07:26:00PM +0800, Xu Yang wrote:
> In current design, the ehci driver will not unlink itd/sitds from the
> hardware list when dequeue isochronous urbs. Rather just wait until they
> complete normally or their time slot expires. However, this will cause
> issues if the controller has stopped periodic schedule before finished
> all periodic schedule. The urb will not be done forever in this case and
> then usb_kill/poison_urb() will always wait there.
> 
> The ChipIdea IP exactly has a bug: if frame babble occurs during periodic
> transfer, PE (PORTSC.bit2) will be cleared and the controller will stop
> periodic schedule immediately. So if the user tries to kill or poison
> related urb, it will wait there since the urb can't be done forever.
> 
> This patch will check if this issue occurs, then it will unlink itd/sitds
> from the hardware list depends on the result.

This is not the right approach.  There already is code in the driver for 
unlinking itds/sitds when the periodic schedule isn't running: See how 
the "live" variable is used in scan_isoc().  You don't need to add new 
code to do the same thing, you simply have to make sure that live is set 
to false if the controller has stopped the periodic schedule 
unexpectedly.

(Be very careful about handling the case where CMD_PSE is set and 
STS_PSS is clear.  This can happen when the controller has been told to 
start the periodic schedule but it hasn't done so yet.)

Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions
  2023-07-18 11:25 [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions Xu Yang
  2023-07-18 11:26 ` [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule Xu Yang
@ 2023-07-21  3:50 ` kernel test robot
  2023-07-23 18:10 ` kernel test robot
  2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-07-21  3:50 UTC (permalink / raw)
  To: Xu Yang, stern; +Cc: oe-kbuild-all, gregkh, linux-usb, xu.yang_2, jun.li

Hi Xu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on usb/usb-testing]
[also build test WARNING on usb/usb-next usb/usb-linus char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus westeri-thunderbolt/next linus/master v6.5-rc2 next-20230720]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Xu-Yang/usb-ehci-unlink-itd-sitds-from-hardware-list-if-the-controller-has-stopped-periodic-schedule/20230718-192747
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link:    https://lore.kernel.org/r/20230718112600.3969141-1-xu.yang_2%40nxp.com
patch subject: [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions
config: parisc-randconfig-r071-20230717 (https://download.01.org/0day-ci/archive/20230721/202307211120.NLiBSqJH-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230721/202307211120.NLiBSqJH-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202307211120.NLiBSqJH-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/usb/host/ehci-hcd.c: note: in included file:
   drivers/usb/host/ehci-q.c:1390:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] old_current @@     got int @@
   drivers/usb/host/ehci-q.c:1390:27: sparse:     expected restricted __le32 [usertype] old_current
   drivers/usb/host/ehci-q.c:1390:27: sparse:     got int
   drivers/usb/host/ehci-hcd.c:568:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] old_current @@     got int @@
   drivers/usb/host/ehci-hcd.c:568:27: sparse:     expected restricted __le32 [usertype] old_current
   drivers/usb/host/ehci-hcd.c:568:27: sparse:     got int
   drivers/usb/host/ehci-hcd.c: note: in included file:
>> drivers/usb/host/ehci-sched.c:1829:17: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected restricted __le32 [usertype] tag @@     got int @@
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     expected restricted __le32 [usertype] tag
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     got int
>> drivers/usb/host/ehci-sched.c:1829:17: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected restricted __le32 [usertype] tag @@     got int @@
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     expected restricted __le32 [usertype] tag
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     got int

vim +1829 drivers/usb/host/ehci-sched.c

  1807	
  1808	/* unlink itd/sitd from the periodic list */
  1809	static inline void
  1810	unlink(struct ehci_hcd *ehci, unsigned frame, void *ptr)
  1811	{
  1812		union ehci_shadow	*prev = &ehci->pshadow[frame];
  1813		__hc32			*hw_p = &ehci->periodic[frame];
  1814		union ehci_shadow	here = *prev;
  1815	
  1816		while (here.ptr && here.ptr != ptr) {
  1817			prev = periodic_next_shadow(ehci, prev,
  1818				Q_NEXT_TYPE(ehci, *hw_p));
  1819			hw_p = shadow_next_periodic(ehci, &here,
  1820				Q_NEXT_TYPE(ehci, *hw_p));
  1821			here = *prev;
  1822		}
  1823	
  1824		*prev = *periodic_next_shadow(ehci, &here,
  1825				Q_NEXT_TYPE(ehci, *hw_p));
  1826	
  1827		if (!ehci->use_dummy_qh ||
  1828			*shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)
> 1829			!= EHCI_LIST_END(ehci)))
  1830			*hw_p = *shadow_next_periodic(ehci, &here,
  1831						Q_NEXT_TYPE(ehci, *hw_p));
  1832		else
  1833			*hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma);
  1834	}
  1835	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions
  2023-07-18 11:25 [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions Xu Yang
  2023-07-18 11:26 ` [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule Xu Yang
  2023-07-21  3:50 ` [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions kernel test robot
@ 2023-07-23 18:10 ` kernel test robot
  2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-07-23 18:10 UTC (permalink / raw)
  To: Xu Yang, stern; +Cc: oe-kbuild-all, gregkh, linux-usb, xu.yang_2, jun.li

Hi Xu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on usb/usb-testing]
[also build test WARNING on usb/usb-next usb/usb-linus char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus westeri-thunderbolt/next linus/master v6.5-rc2 next-20230721]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Xu-Yang/usb-ehci-unlink-itd-sitds-from-hardware-list-if-the-controller-has-stopped-periodic-schedule/20230718-192747
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link:    https://lore.kernel.org/r/20230718112600.3969141-1-xu.yang_2%40nxp.com
patch subject: [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions
config: microblaze-randconfig-r072-20230723 (https://download.01.org/0day-ci/archive/20230724/202307240103.vWzkF4eB-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230724/202307240103.vWzkF4eB-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202307240103.vWzkF4eB-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/usb/host/ehci-hcd.c: note: in included file:
   drivers/usb/host/ehci-q.c:1390:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __hc32 [usertype] old_current @@     got int @@
   drivers/usb/host/ehci-q.c:1390:27: sparse:     expected restricted __hc32 [usertype] old_current
   drivers/usb/host/ehci-q.c:1390:27: sparse:     got int
   drivers/usb/host/ehci-hcd.c: note: in included file:
   drivers/usb/host/ehci-mem.c:187:24: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __hc32 [usertype] *periodic @@     got restricted __le32 [usertype] * @@
   drivers/usb/host/ehci-mem.c:187:24: sparse:     expected restricted __hc32 [usertype] *periodic
   drivers/usb/host/ehci-mem.c:187:24: sparse:     got restricted __le32 [usertype] *
   drivers/usb/host/ehci-hcd.c:568:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __hc32 [usertype] old_current @@     got int @@
   drivers/usb/host/ehci-hcd.c:568:27: sparse:     expected restricted __hc32 [usertype] old_current
   drivers/usb/host/ehci-hcd.c:568:27: sparse:     got int
   drivers/usb/host/ehci-hcd.c: note: in included file:
>> drivers/usb/host/ehci-sched.c:1829:17: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected restricted __hc32 [usertype] tag @@     got int @@
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     expected restricted __hc32 [usertype] tag
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     got int
>> drivers/usb/host/ehci-sched.c:1829:17: sparse: sparse: incorrect type in argument 3 (different base types) @@     expected restricted __hc32 [usertype] tag @@     got int @@
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     expected restricted __hc32 [usertype] tag
   drivers/usb/host/ehci-sched.c:1829:17: sparse:     got int

vim +1829 drivers/usb/host/ehci-sched.c

  1807	
  1808	/* unlink itd/sitd from the periodic list */
  1809	static inline void
  1810	unlink(struct ehci_hcd *ehci, unsigned frame, void *ptr)
  1811	{
  1812		union ehci_shadow	*prev = &ehci->pshadow[frame];
  1813		__hc32			*hw_p = &ehci->periodic[frame];
  1814		union ehci_shadow	here = *prev;
  1815	
  1816		while (here.ptr && here.ptr != ptr) {
  1817			prev = periodic_next_shadow(ehci, prev,
  1818				Q_NEXT_TYPE(ehci, *hw_p));
  1819			hw_p = shadow_next_periodic(ehci, &here,
  1820				Q_NEXT_TYPE(ehci, *hw_p));
  1821			here = *prev;
  1822		}
  1823	
  1824		*prev = *periodic_next_shadow(ehci, &here,
  1825				Q_NEXT_TYPE(ehci, *hw_p));
  1826	
  1827		if (!ehci->use_dummy_qh ||
  1828			*shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)
> 1829			!= EHCI_LIST_END(ehci)))
  1830			*hw_p = *shadow_next_periodic(ehci, &here,
  1831						Q_NEXT_TYPE(ehci, *hw_p));
  1832		else
  1833			*hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma);
  1834	}
  1835	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [EXT] Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-07-18 14:53   ` Alan Stern
@ 2023-07-29  6:55     ` Xu Yang
  2023-07-29 14:53       ` Alan Stern
  0 siblings, 1 reply; 10+ messages in thread
From: Xu Yang @ 2023-07-29  6:55 UTC (permalink / raw)
  To: Alan Stern; +Cc: gregkh, linux-usb, Jun Li

Hi Alan,

> On Tue, Jul 18, 2023 at 07:26:00PM +0800, Xu Yang wrote:
> > In current design, the ehci driver will not unlink itd/sitds from the
> > hardware list when dequeue isochronous urbs. Rather just wait until they
> > complete normally or their time slot expires. However, this will cause
> > issues if the controller has stopped periodic schedule before finished
> > all periodic schedule. The urb will not be done forever in this case and
> > then usb_kill/poison_urb() will always wait there.
> >
> > The ChipIdea IP exactly has a bug: if frame babble occurs during periodic
> > transfer, PE (PORTSC.bit2) will be cleared and the controller will stop
> > periodic schedule immediately. So if the user tries to kill or poison
> > related urb, it will wait there since the urb can't be done forever.
> >
> > This patch will check if this issue occurs, then it will unlink itd/sitds
> > from the hardware list depends on the result.
> 
> This is not the right approach.  There already is code in the driver for
> unlinking itds/sitds when the periodic schedule isn't running: See how
> the "live" variable is used in scan_isoc().  You don't need to add new
> code to do the same thing, you simply have to make sure that live is set
> to false if the controller has stopped the periodic schedule
> unexpectedly.
> 
> (Be very careful about handling the case where CMD_PSE is set and
> STS_PSS is clear.  This can happen when the controller has been told to
> start the periodic schedule but it hasn't done so yet.)

Many thanks for your comments and suggestions.

Yes, there is a "live" variable in scan_isoc() to handle the case where
root hub has stopped periodic schedule. I have rechecked the root cause
of the issue , that is the USB controller has disabled the port (PE cleared)
and asserted USBERRINT when frame babble is detected, but PEC is not
asserted. Therefore, the SW didn't aware that port has been disabled. 
The periodic schedule keeps running at this moment. Then the SW keeps
sending packets to this port, but all of the transfers will fail. But periodic
schedule will also be disabled after a period of time. Finally, all of the linked
itds are penging there. The code can't enter into scan_isoc() if only USBERRINT
is asserted.

For this issue, I think the SW needs to aware that the port has been disabled
although PEC not asserted by HW. I will send another patch to fix this issue
later.

Thanks,
Xu Yang 

> 
> Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [EXT] Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-07-29  6:55     ` [EXT] " Xu Yang
@ 2023-07-29 14:53       ` Alan Stern
  2023-08-08 10:03         ` Xu Yang
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2023-07-29 14:53 UTC (permalink / raw)
  To: Xu Yang; +Cc: gregkh, linux-usb, Jun Li

On Sat, Jul 29, 2023 at 06:55:07AM +0000, Xu Yang wrote:
> Many thanks for your comments and suggestions.
> 
> Yes, there is a "live" variable in scan_isoc() to handle the case where
> root hub has stopped periodic schedule. I have rechecked the root cause
> of the issue , that is the USB controller has disabled the port (PE cleared)
> and asserted USBERRINT when frame babble is detected, but PEC is not
> asserted. Therefore, the SW didn't aware that port has been disabled. 
> The periodic schedule keeps running at this moment. Then the SW keeps
> sending packets to this port, but all of the transfers will fail. But periodic
> schedule will also be disabled after a period of time. Finally, all of the linked
> itds are penging there. The code can't enter into scan_isoc() if only USBERRINT
> is asserted.

That's not true.  The io_watchdog timer continues to fire periodically 
(at 100 ms intervals) as long as isoc_count > 0.  The timer's handler is 
ehci_work(), which calls scan_isoc() if isoc_count > 0.

> For this issue, I think the SW needs to aware that the port has been disabled
> although PEC not asserted by HW. I will send another patch to fix this issue
> later.

Yes, that sounds like a nasty problem.  The kernel wouldn't realize 
that the device had disconnected.

Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [EXT] Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-07-29 14:53       ` Alan Stern
@ 2023-08-08 10:03         ` Xu Yang
  2023-08-08 15:13           ` Alan Stern
  0 siblings, 1 reply; 10+ messages in thread
From: Xu Yang @ 2023-08-08 10:03 UTC (permalink / raw)
  To: Alan Stern; +Cc: gregkh, linux-usb, Jun Li

Hi Alan,

> On Sat, Jul 29, 2023 at 06:55:07AM +0000, Xu Yang wrote:
> > Many thanks for your comments and suggestions.
> >
> > Yes, there is a "live" variable in scan_isoc() to handle the case where
> > root hub has stopped periodic schedule. I have rechecked the root cause
> > of the issue , that is the USB controller has disabled the port (PE cleared)
> > and asserted USBERRINT when frame babble is detected, but PEC is not
> > asserted. Therefore, the SW didn't aware that port has been disabled.
> > The periodic schedule keeps running at this moment. Then the SW keeps
> > sending packets to this port, but all of the transfers will fail. But periodic
> > schedule will also be disabled after a period of time. Finally, all of the linked
> > itds are penging there. The code can't enter into scan_isoc() if only USBERRINT
> > is asserted.
> 
> That's not true.  The io_watchdog timer continues to fire periodically
> (at 100 ms intervals) as long as isoc_count > 0.  The timer's handler is
> ehci_work(), which calls scan_isoc() if isoc_count > 0.

Yes, the io_watchdog timer will cleanup the isoc periodically as long as
isoc_count > 0. 

I did see all of the linked itds are pending there in my case at the end. After my
debug, I found the chipidea/host.c had set ehci->need_io_watchdog to 0 which
will have impact on turn_on_io_watchdog().

The host has enabled 1 intr endpoint and 2 isoc endpoints from USB camera.
Therefore, ehci->intr_count is always 1 and ehci->isoc_count is changing from
time to time during camera is running. When PE is cleared by HW, isoc_count
may be decreased to 0 after scan_isoc(). When turn_on_io_watchdog() is called,
EHCI_HRTIMER_IO_WATCHDOG event will not be enabled due to isoc_count=0
and need_io_watchdog=0 too. When isoc urb is submited again, enable_periodic()
will still not enable EHCI_HRTIMER_IO_WATCHDOG event due to periodic_count>0.
Then, the linked itds are pending there as long as intr urb has not been completed.

Thanks,
Xu Yang

> 
> > For this issue, I think the SW needs to aware that the port has been disabled
> > although PEC not asserted by HW. I will send another patch to fix this issue
> > later.
> 
> Yes, that sounds like a nasty problem.  The kernel wouldn't realize
> that the device had disconnected.
> 
> Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [EXT] Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-08-08 10:03         ` Xu Yang
@ 2023-08-08 15:13           ` Alan Stern
  2023-08-09  2:06             ` Xu Yang
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2023-08-08 15:13 UTC (permalink / raw)
  To: Xu Yang; +Cc: gregkh, linux-usb, Jun Li

On Tue, Aug 08, 2023 at 10:03:39AM +0000, Xu Yang wrote:
> Hi Alan,
> 
> > On Sat, Jul 29, 2023 at 06:55:07AM +0000, Xu Yang wrote:
> > > Many thanks for your comments and suggestions.
> > >
> > > Yes, there is a "live" variable in scan_isoc() to handle the case where
> > > root hub has stopped periodic schedule. I have rechecked the root cause
> > > of the issue , that is the USB controller has disabled the port (PE cleared)
> > > and asserted USBERRINT when frame babble is detected, but PEC is not
> > > asserted. Therefore, the SW didn't aware that port has been disabled.
> > > The periodic schedule keeps running at this moment. Then the SW keeps
> > > sending packets to this port, but all of the transfers will fail. But periodic
> > > schedule will also be disabled after a period of time. Finally, all of the linked
> > > itds are penging there. The code can't enter into scan_isoc() if only USBERRINT
> > > is asserted.
> > 
> > That's not true.  The io_watchdog timer continues to fire periodically
> > (at 100 ms intervals) as long as isoc_count > 0.  The timer's handler is
> > ehci_work(), which calls scan_isoc() if isoc_count > 0.
> 
> Yes, the io_watchdog timer will cleanup the isoc periodically as long as
> isoc_count > 0. 
> 
> I did see all of the linked itds are pending there in my case at the end. After my
> debug, I found the chipidea/host.c had set ehci->need_io_watchdog to 0 which
> will have impact on turn_on_io_watchdog().
> 
> The host has enabled 1 intr endpoint and 2 isoc endpoints from USB camera.
> Therefore, ehci->intr_count is always 1 and ehci->isoc_count is changing from
> time to time during camera is running. When PE is cleared by HW, isoc_count
> may be decreased to 0 after scan_isoc(). When turn_on_io_watchdog() is called,
> EHCI_HRTIMER_IO_WATCHDOG event will not be enabled due to isoc_count=0
> and need_io_watchdog=0 too. When isoc urb is submited again, enable_periodic()
> will still not enable EHCI_HRTIMER_IO_WATCHDOG event due to periodic_count>0.

Ooh, that's a bug.  enable_periodic() should call turn_on_io_watchdog() 
no matter what value periodic_count has.  Would you like to fix it?

Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [EXT] Re: [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule
  2023-08-08 15:13           ` Alan Stern
@ 2023-08-09  2:06             ` Xu Yang
  0 siblings, 0 replies; 10+ messages in thread
From: Xu Yang @ 2023-08-09  2:06 UTC (permalink / raw)
  To: Alan Stern; +Cc: gregkh, linux-usb, Jun Li

Hi Alan,

> On Tue, Aug 08, 2023 at 10:03:39AM +0000, Xu Yang wrote:
> > Hi Alan,
> >
> > > On Sat, Jul 29, 2023 at 06:55:07AM +0000, Xu Yang wrote:
> > > > Many thanks for your comments and suggestions.
> > > >
> > > > Yes, there is a "live" variable in scan_isoc() to handle the case where
> > > > root hub has stopped periodic schedule. I have rechecked the root cause
> > > > of the issue , that is the USB controller has disabled the port (PE cleared)
> > > > and asserted USBERRINT when frame babble is detected, but PEC is not
> > > > asserted. Therefore, the SW didn't aware that port has been disabled.
> > > > The periodic schedule keeps running at this moment. Then the SW keeps
> > > > sending packets to this port, but all of the transfers will fail. But periodic
> > > > schedule will also be disabled after a period of time. Finally, all of the linked
> > > > itds are penging there. The code can't enter into scan_isoc() if only USBERRINT
> > > > is asserted.
> > >
> > > That's not true.  The io_watchdog timer continues to fire periodically
> > > (at 100 ms intervals) as long as isoc_count > 0.  The timer's handler is
> > > ehci_work(), which calls scan_isoc() if isoc_count > 0.
> >
> > Yes, the io_watchdog timer will cleanup the isoc periodically as long as
> > isoc_count > 0.
> >
> > I did see all of the linked itds are pending there in my case at the end. After my
> > debug, I found the chipidea/host.c had set ehci->need_io_watchdog to 0 which
> > will have impact on turn_on_io_watchdog().
> >
> > The host has enabled 1 intr endpoint and 2 isoc endpoints from USB camera.
> > Therefore, ehci->intr_count is always 1 and ehci->isoc_count is changing from
> > time to time during camera is running. When PE is cleared by HW, isoc_count
> > may be decreased to 0 after scan_isoc(). When turn_on_io_watchdog() is called,
> > EHCI_HRTIMER_IO_WATCHDOG event will not be enabled due to isoc_count=0
> > and need_io_watchdog=0 too. When isoc urb is submited again, enable_periodic()
> > will still not enable EHCI_HRTIMER_IO_WATCHDOG event due to periodic_count>0.
> 
> Ooh, that's a bug.  enable_periodic() should call turn_on_io_watchdog()
> no matter what value periodic_count has.  Would you like to fix it?

Sure. Will try to fix it.

Thanks,
Xu Yang

> 
> Alan Stern

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-08-09  2:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-18 11:25 [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions Xu Yang
2023-07-18 11:26 ` [PATCH 2/2] usb: ehci: unlink itd/sitds from hardware list if the controller has stopped periodic schedule Xu Yang
2023-07-18 14:53   ` Alan Stern
2023-07-29  6:55     ` [EXT] " Xu Yang
2023-07-29 14:53       ` Alan Stern
2023-08-08 10:03         ` Xu Yang
2023-08-08 15:13           ` Alan Stern
2023-08-09  2:06             ` Xu Yang
2023-07-21  3:50 ` [PATCH 1/2] usb: host: ehci-sched: add itd/sitd_unlink_urb() functions kernel test robot
2023-07-23 18:10 ` kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.