> Looking at the code for uhci, its clearly busted.
> 
> The code needs to set a suspended flag (under a lock), and check that it 
> is not set when servicing interrupts.

Such a flag already exists: uhcip->uhci_hc_soft_state / UHCI_CTLR_SUSPEND_STATE,
and it is set and tested protected by the uhci_int_mutex lock.

Problem is that uhci_cpr_suspend() temporarily releases the uhci_int_mutex
lock while calling delay(), and apparently it releases the lock before
the uhci hw is really stopped.  And before the uhcip->uhci_hc_soft_state
flag is set to UHCI_CTLR_SUSPEND_STATE.  That delay() call is exactly where
my Toshiba Laptop is hanging, when I try to S3-suspend it.



> But, I see another problem, which is that perhaps the code is not 
> clearing the interrupts when it disables them in uhci_cpr_suspend().   
> Still, it seems like the device should not be generating interrupts to 
> the hardware if the interrupt enable status bit is cleared.  *That* 
> sounds like a potential hardware bug.

Yes, looks like 

- either a new new uhci interrupt is generated between lines 831 .. 834
  (which seems unlikely, because so far, the S3-suspend hang happens
  every time)
  
- or the Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); doesn't have an 
  effect immediately - so that we can receive at least one more uhci
  interrupt while we're inside the delay call at line 839.

   816  /*
   817   * uhci_cpr_suspend
   818   */
   819  static int
   820  uhci_cpr_suspend(uhci_state_t   *uhcip)
   821  {
   822          USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
   823              "uhci_cpr_suspend:");
   824
   825          /* Call into the root hub and suspend it */
   826          if (usba_hubdi_detach(uhcip->uhci_dip, DDI_SUSPEND) != 
DDI_SUCCESS) {
   827
   828                  return (DDI_FAILURE);
   829          }
   830
   831          mutex_enter(&uhcip->uhci_int_mutex);
   832
   833          /* Disable interrupts */
   834          Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
   835
   836          mutex_exit(&uhcip->uhci_int_mutex);
   837
   838          /* Wait for SOF time to handle the scheduled interrupt */
   839          delay(drv_usectohz(UHCI_TIMEWAIT));


Btw. the uhci controller im my Toshiba Tecra S1 laptop is part of an
Intel ICH4-M chipset.



>     -- Garrett
> 
> J??rgen Keil wrote:
> > Can anyone reproduce a hanging system when trying to use S3 suspend-to-ram,
> > immediately after the first uhci driver instance gets suspended?
> > Most likely this is an issue only on systems where uhci is sharing
> > it's interrupt vector with other devices.
> >
> > My Toshiba Tecra S1 laptop used to be able to enter S3 suspend-to-ram
> > mode.
> >
> > Seems that since the putback for 6681221 "Solaris hangs during early boot
> > when EHCI-2 is enabled from BIOS" S3-suspend is broken.  As soon as the 
> > first
> > uhci controller gets suspended (uhci0), system hangs (with an interrupt 
> > storm?).
> > The laptop doesn't reach S3-STR state any more.
> >
> > There is an interrupt pending for uhci0 (intr_status == 1), but interrupts
> > are supposed to be disabled (intr_reg == 0), so the code returns from
> > uhci_intr without acknowledging the pending interrupt (lines 954 - 952 in 
> > uhci.c) .
> > Interrupt handler is immediately re-entered; there's no more progress with
> > S3-suspend.
> >
> > usr/src/uts/common/io/usb/hcd/uhci/uhci.c:
> >    940          /* Get the status of the interrupts */
> >    941          intr_status = Get_OpReg16(USBSTS);
> >    942          intr_reg = Get_OpReg16(USBINTR);
> >    943
> >    944          USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
> >    945              "uhci_intr: intr_status = %x, intr_reg = %x",
> >    946              intr_status, intr_reg);
> >    947
> >    948          /*
> >    949           * If uhci interrupts are all disabled, the driver should 
> > return
> >    950           * unclaimed.
> >    951           * HC Process Error and Host System Error interrupts cannot 
> > be
> >    952           * disabled by intr register, and need to be judged 
> > separately.
> >    953           */
> >    954          if (((intr_reg & ENABLE_ALL_INTRS) == 0) &&
> >    955              ((intr_status & USBSTS_REG_HC_PROCESS_ERR) == 0) &&
> >    956              ((intr_status & USBSTS_REG_HOST_SYS_ERR) == 0)) {
> >    957
> >    958                  USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
> >    959                      "uhci_intr: interrupts disabled, unclaim");
> >    960                  mutex_exit(&uhcip->uhci_int_mutex);
> >    961
> >    962                  return (DDI_INTR_UNCLAIMED);
> >    963          }
> >  
> >  
> > This message posted from opensolaris.org
> > _______________________________________________
> > laptop-discuss mailing list
> > laptop-discuss at opensolaris.org
> >   


Reply via email to