LCOV - code coverage report
Current view: top level - drivers/usb/host - ohci-hub.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 330 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 8 0.0 %
Branches: 0 184 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-1.0+
       2                 :            : /*
       3                 :            :  * OHCI HCD (Host Controller Driver) for USB.
       4                 :            :  *
       5                 :            :  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
       6                 :            :  * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
       7                 :            :  *
       8                 :            :  * This file is licenced under GPL
       9                 :            :  */
      10                 :            : 
      11                 :            : /*-------------------------------------------------------------------------*/
      12                 :            : 
      13                 :            : /*
      14                 :            :  * OHCI Root Hub ... the nonsharable stuff
      15                 :            :  */
      16                 :            : 
      17                 :            : #define dbg_port(hc,label,num,value) \
      18                 :            :         ohci_dbg (hc, \
      19                 :            :                 "%s roothub.portstatus [%d] " \
      20                 :            :                 "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
      21                 :            :                 label, num, value, \
      22                 :            :                 (value & RH_PS_PRSC) ? " PRSC" : "", \
      23                 :            :                 (value & RH_PS_OCIC) ? " OCIC" : "", \
      24                 :            :                 (value & RH_PS_PSSC) ? " PSSC" : "", \
      25                 :            :                 (value & RH_PS_PESC) ? " PESC" : "", \
      26                 :            :                 (value & RH_PS_CSC) ? " CSC" : "", \
      27                 :            :                 \
      28                 :            :                 (value & RH_PS_LSDA) ? " LSDA" : "", \
      29                 :            :                 (value & RH_PS_PPS) ? " PPS" : "", \
      30                 :            :                 (value & RH_PS_PRS) ? " PRS" : "", \
      31                 :            :                 (value & RH_PS_POCI) ? " POCI" : "", \
      32                 :            :                 (value & RH_PS_PSS) ? " PSS" : "", \
      33                 :            :                 \
      34                 :            :                 (value & RH_PS_PES) ? " PES" : "", \
      35                 :            :                 (value & RH_PS_CCS) ? " CCS" : "" \
      36                 :            :                 );
      37                 :            : 
      38                 :            : /*-------------------------------------------------------------------------*/
      39                 :            : 
      40                 :            : #define OHCI_SCHED_ENABLES \
      41                 :            :         (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
      42                 :            : 
      43                 :            : static void update_done_list(struct ohci_hcd *);
      44                 :            : static void ohci_work(struct ohci_hcd *);
      45                 :            : 
      46                 :            : #ifdef  CONFIG_PM
      47                 :          0 : static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
      48                 :            : __releases(ohci->lock)
      49                 :            : __acquires(ohci->lock)
      50                 :            : {
      51                 :          0 :         int                     status = 0;
      52                 :            : 
      53                 :          0 :         ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
      54   [ #  #  #  # ]:          0 :         switch (ohci->hc_control & OHCI_CTRL_HCFS) {
      55                 :            :         case OHCI_USB_RESUME:
      56                 :          0 :                 ohci_dbg (ohci, "resume/suspend?\n");
      57                 :          0 :                 ohci->hc_control &= ~OHCI_CTRL_HCFS;
      58                 :          0 :                 ohci->hc_control |= OHCI_USB_RESET;
      59                 :          0 :                 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
      60                 :          0 :                 (void) ohci_readl (ohci, &ohci->regs->control);
      61                 :            :                 /* FALL THROUGH */
      62                 :          0 :         case OHCI_USB_RESET:
      63                 :          0 :                 status = -EBUSY;
      64                 :          0 :                 ohci_dbg (ohci, "needs reinit!\n");
      65                 :          0 :                 goto done;
      66                 :          0 :         case OHCI_USB_SUSPEND:
      67         [ #  # ]:          0 :                 if (!ohci->autostop) {
      68                 :          0 :                         ohci_dbg (ohci, "already suspended\n");
      69                 :          0 :                         goto done;
      70                 :            :                 }
      71                 :            :         }
      72                 :          0 :         ohci_dbg (ohci, "%s root hub\n",
      73                 :            :                         autostop ? "auto-stop" : "suspend");
      74                 :            : 
      75                 :            :         /* First stop any processing */
      76   [ #  #  #  # ]:          0 :         if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) {
      77                 :          0 :                 ohci->hc_control &= ~OHCI_SCHED_ENABLES;
      78                 :          0 :                 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
      79                 :          0 :                 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
      80                 :          0 :                 ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);
      81                 :            : 
      82                 :            :                 /* sched disables take effect on the next frame,
      83                 :            :                  * then the last WDH could take 6+ msec
      84                 :            :                  */
      85                 :          0 :                 ohci_dbg (ohci, "stopping schedules ...\n");
      86                 :          0 :                 ohci->autostop = 0;
      87                 :          0 :                 spin_unlock_irq (&ohci->lock);
      88                 :          0 :                 msleep (8);
      89                 :          0 :                 spin_lock_irq (&ohci->lock);
      90                 :            :         }
      91                 :          0 :         update_done_list(ohci);
      92                 :          0 :         ohci_work(ohci);
      93                 :            : 
      94                 :            :         /*
      95                 :            :          * Some controllers don't handle "global" suspend properly if
      96                 :            :          * there are unsuspended ports.  For these controllers, put all
      97                 :            :          * the enabled ports into suspend before suspending the root hub.
      98                 :            :          */
      99         [ #  # ]:          0 :         if (ohci->flags & OHCI_QUIRK_GLOBAL_SUSPEND) {
     100                 :          0 :                 __hc32 __iomem  *portstat = ohci->regs->roothub.portstatus;
     101                 :          0 :                 int             i;
     102                 :          0 :                 unsigned        temp;
     103                 :            : 
     104         [ #  # ]:          0 :                 for (i = 0; i < ohci->num_ports; (++i, ++portstat)) {
     105                 :          0 :                         temp = ohci_readl(ohci, portstat);
     106         [ #  # ]:          0 :                         if ((temp & (RH_PS_PES | RH_PS_PSS)) ==
     107                 :            :                                         RH_PS_PES)
     108                 :          0 :                                 ohci_writel(ohci, RH_PS_PSS, portstat);
     109                 :            :                 }
     110                 :            :         }
     111                 :            : 
     112                 :            :         /* maybe resume can wake root hub */
     113   [ #  #  #  # ]:          0 :         if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
     114                 :          0 :                 ohci->hc_control |= OHCI_CTRL_RWE;
     115                 :            :         } else {
     116                 :          0 :                 ohci_writel(ohci, OHCI_INTR_RHSC | OHCI_INTR_RD,
     117                 :            :                                 &ohci->regs->intrdisable);
     118                 :          0 :                 ohci->hc_control &= ~OHCI_CTRL_RWE;
     119                 :            :         }
     120                 :            : 
     121                 :            :         /* Suspend hub ... this is the "global (to this bus) suspend" mode,
     122                 :            :          * which doesn't imply ports will first be individually suspended.
     123                 :            :          */
     124                 :          0 :         ohci->hc_control &= ~OHCI_CTRL_HCFS;
     125                 :          0 :         ohci->hc_control |= OHCI_USB_SUSPEND;
     126                 :          0 :         ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
     127                 :          0 :         (void) ohci_readl (ohci, &ohci->regs->control);
     128                 :            : 
     129                 :            :         /* no resumes until devices finish suspending */
     130         [ #  # ]:          0 :         if (!autostop) {
     131                 :          0 :                 ohci->next_statechange = jiffies + msecs_to_jiffies (5);
     132                 :          0 :                 ohci->autostop = 0;
     133                 :          0 :                 ohci->rh_state = OHCI_RH_SUSPENDED;
     134                 :            :         }
     135                 :            : 
     136                 :          0 : done:
     137                 :          0 :         return status;
     138                 :            : }
     139                 :            : 
     140                 :          0 : static inline struct ed *find_head (struct ed *ed)
     141                 :            : {
     142                 :            :         /* for bulk and control lists */
     143   [ #  #  #  # ]:          0 :         while (ed->ed_prev)
     144                 :            :                 ed = ed->ed_prev;
     145                 :          0 :         return ed;
     146                 :            : }
     147                 :            : 
     148                 :            : /* caller has locked the root hub */
     149                 :          0 : static int ohci_rh_resume (struct ohci_hcd *ohci)
     150                 :            : __releases(ohci->lock)
     151                 :            : __acquires(ohci->lock)
     152                 :            : {
     153                 :          0 :         struct usb_hcd          *hcd = ohci_to_hcd (ohci);
     154                 :          0 :         u32                     temp, enables;
     155                 :          0 :         int                     status = -EINPROGRESS;
     156                 :          0 :         int                     autostopped = ohci->autostop;
     157                 :            : 
     158                 :          0 :         ohci->autostop = 0;
     159                 :          0 :         ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
     160                 :            : 
     161         [ #  # ]:          0 :         if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
     162                 :            :                 /* this can happen after resuming a swsusp snapshot */
     163         [ #  # ]:          0 :                 if (ohci->rh_state != OHCI_RH_RUNNING) {
     164                 :            :                         ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
     165                 :            :                                         ohci->hc_control);
     166                 :            :                         status = -EBUSY;
     167                 :            :                 /* this happens when pmcore resumes HC then root */
     168                 :            :                 } else {
     169                 :            :                         ohci_dbg (ohci, "duplicate resume\n");
     170                 :            :                         status = 0;
     171                 :            :                 }
     172      [ #  #  # ]:          0 :         } else switch (ohci->hc_control & OHCI_CTRL_HCFS) {
     173                 :          0 :         case OHCI_USB_SUSPEND:
     174                 :          0 :                 ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
     175                 :          0 :                 ohci->hc_control |= OHCI_USB_RESUME;
     176                 :          0 :                 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
     177                 :          0 :                 (void) ohci_readl (ohci, &ohci->regs->control);
     178                 :            :                 ohci_dbg (ohci, "%s root hub\n",
     179                 :            :                                 autostopped ? "auto-start" : "resume");
     180                 :            :                 break;
     181                 :            :         case OHCI_USB_RESUME:
     182                 :            :                 /* HCFS changes sometime after INTR_RD */
     183                 :            :                 ohci_dbg(ohci, "%swakeup root hub\n",
     184                 :            :                                 autostopped ? "auto-" : "");
     185                 :            :                 break;
     186                 :            :         case OHCI_USB_OPER:
     187                 :            :                 /* this can happen after resuming a swsusp snapshot */
     188                 :            :                 ohci_dbg (ohci, "snapshot resume? reinit\n");
     189                 :            :                 status = -EBUSY;
     190                 :            :                 break;
     191                 :            :         default:                /* RESET, we lost power */
     192                 :            :                 ohci_dbg (ohci, "lost power\n");
     193                 :            :                 status = -EBUSY;
     194                 :            :         }
     195                 :          0 :         if (status == -EBUSY) {
     196         [ #  # ]:          0 :                 if (!autostopped) {
     197                 :          0 :                         spin_unlock_irq (&ohci->lock);
     198                 :          0 :                         status = ohci_restart (ohci);
     199                 :            : 
     200                 :          0 :                         usb_root_hub_lost_power(hcd->self.root_hub);
     201                 :            : 
     202                 :          0 :                         spin_lock_irq (&ohci->lock);
     203                 :            :                 }
     204                 :          0 :                 return status;
     205                 :            :         }
     206         [ #  # ]:          0 :         if (status != -EINPROGRESS)
     207                 :            :                 return status;
     208         [ #  # ]:          0 :         if (autostopped)
     209                 :          0 :                 goto skip_resume;
     210                 :          0 :         spin_unlock_irq (&ohci->lock);
     211                 :            : 
     212                 :            :         /* Some controllers (lucent erratum) need extra-long delays */
     213                 :          0 :         msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
     214                 :            : 
     215                 :          0 :         temp = ohci_readl (ohci, &ohci->regs->control);
     216                 :          0 :         temp &= OHCI_CTRL_HCFS;
     217         [ #  # ]:          0 :         if (temp != OHCI_USB_RESUME) {
     218                 :          0 :                 ohci_err (ohci, "controller won't resume\n");
     219                 :          0 :                 spin_lock_irq(&ohci->lock);
     220                 :          0 :                 return -EBUSY;
     221                 :            :         }
     222                 :            : 
     223                 :            :         /* disable old schedule state, reinit from scratch */
     224                 :          0 :         ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
     225                 :          0 :         ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
     226                 :          0 :         ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
     227                 :          0 :         ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
     228                 :          0 :         ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
     229                 :          0 :         ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
     230                 :            : 
     231                 :            :         /* Sometimes PCI D3 suspend trashes frame timings ... */
     232                 :          0 :         periodic_reinit (ohci);
     233                 :            : 
     234                 :            :         /*
     235                 :            :          * The following code is executed with ohci->lock held and
     236                 :            :          * irqs disabled if and only if autostopped is true.  This
     237                 :            :          * will cause sparse to warn about a "context imbalance".
     238                 :            :          */
     239                 :          0 : skip_resume:
     240                 :            :         /* interrupts might have been disabled */
     241                 :          0 :         ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
     242         [ #  # ]:          0 :         if (ohci->ed_rm_list)
     243                 :          0 :                 ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
     244                 :            : 
     245                 :            :         /* Then re-enable operations */
     246                 :          0 :         ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
     247                 :          0 :         (void) ohci_readl (ohci, &ohci->regs->control);
     248         [ #  # ]:          0 :         if (!autostopped)
     249                 :          0 :                 msleep (3);
     250                 :            : 
     251                 :          0 :         temp = ohci->hc_control;
     252                 :          0 :         temp &= OHCI_CTRL_RWC;
     253                 :          0 :         temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
     254                 :          0 :         ohci->hc_control = temp;
     255                 :          0 :         ohci_writel (ohci, temp, &ohci->regs->control);
     256                 :          0 :         (void) ohci_readl (ohci, &ohci->regs->control);
     257                 :            : 
     258                 :            :         /* TRSMRCY */
     259         [ #  # ]:          0 :         if (!autostopped) {
     260                 :          0 :                 msleep (10);
     261                 :          0 :                 spin_lock_irq (&ohci->lock);
     262                 :            :         }
     263                 :            :         /* now ohci->lock is always held and irqs are always disabled */
     264                 :            : 
     265                 :            :         /* keep it alive for more than ~5x suspend + resume costs */
     266         [ #  # ]:          0 :         ohci->next_statechange = jiffies + STATECHANGE_DELAY;
     267                 :            : 
     268                 :            :         /* maybe turn schedules back on */
     269                 :          0 :         enables = 0;
     270                 :          0 :         temp = 0;
     271         [ #  # ]:          0 :         if (!ohci->ed_rm_list) {
     272         [ #  # ]:          0 :                 if (ohci->ed_controltail) {
     273                 :          0 :                         ohci_writel (ohci,
     274                 :            :                                         find_head (ohci->ed_controltail)->dma,
     275                 :            :                                         &ohci->regs->ed_controlhead);
     276                 :          0 :                         enables |= OHCI_CTRL_CLE;
     277                 :          0 :                         temp |= OHCI_CLF;
     278                 :            :                 }
     279         [ #  # ]:          0 :                 if (ohci->ed_bulktail) {
     280                 :          0 :                         ohci_writel (ohci, find_head (ohci->ed_bulktail)->dma,
     281                 :            :                                 &ohci->regs->ed_bulkhead);
     282                 :          0 :                         enables |= OHCI_CTRL_BLE;
     283                 :          0 :                         temp |= OHCI_BLF;
     284                 :            :                 }
     285                 :            :         }
     286   [ #  #  #  # ]:          0 :         if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
     287                 :          0 :                 enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
     288         [ #  # ]:          0 :         if (enables) {
     289                 :          0 :                 ohci_dbg (ohci, "restarting schedules ... %08x\n", enables);
     290                 :          0 :                 ohci->hc_control |= enables;
     291                 :          0 :                 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
     292         [ #  # ]:          0 :                 if (temp)
     293                 :          0 :                         ohci_writel (ohci, temp, &ohci->regs->cmdstatus);
     294                 :          0 :                 (void) ohci_readl (ohci, &ohci->regs->control);
     295                 :            :         }
     296                 :            : 
     297                 :          0 :         ohci->rh_state = OHCI_RH_RUNNING;
     298                 :          0 :         return 0;
     299                 :            : }
     300                 :            : 
     301                 :          0 : static int ohci_bus_suspend (struct usb_hcd *hcd)
     302                 :            : {
     303                 :          0 :         struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
     304                 :          0 :         int                     rc;
     305                 :            : 
     306                 :          0 :         spin_lock_irq (&ohci->lock);
     307                 :            : 
     308         [ #  # ]:          0 :         if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
     309                 :            :                 rc = -ESHUTDOWN;
     310                 :            :         else
     311                 :          0 :                 rc = ohci_rh_suspend (ohci, 0);
     312                 :          0 :         spin_unlock_irq (&ohci->lock);
     313                 :            : 
     314         [ #  # ]:          0 :         if (rc == 0) {
     315                 :          0 :                 del_timer_sync(&ohci->io_watchdog);
     316                 :          0 :                 ohci->prev_frame_no = IO_WATCHDOG_OFF;
     317                 :            :         }
     318                 :          0 :         return rc;
     319                 :            : }
     320                 :            : 
     321                 :          0 : static int ohci_bus_resume (struct usb_hcd *hcd)
     322                 :            : {
     323         [ #  # ]:          0 :         struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
     324                 :          0 :         int                     rc;
     325                 :            : 
     326         [ #  # ]:          0 :         if (time_before (jiffies, ohci->next_statechange))
     327                 :          0 :                 msleep(5);
     328                 :            : 
     329                 :          0 :         spin_lock_irq (&ohci->lock);
     330                 :            : 
     331         [ #  # ]:          0 :         if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
     332                 :            :                 rc = -ESHUTDOWN;
     333                 :            :         else
     334                 :          0 :                 rc = ohci_rh_resume (ohci);
     335                 :          0 :         spin_unlock_irq (&ohci->lock);
     336                 :            : 
     337                 :            :         /* poll until we know a device is connected or we autostop */
     338         [ #  # ]:          0 :         if (rc == 0)
     339                 :          0 :                 usb_hcd_poll_rh_status(hcd);
     340                 :          0 :         return rc;
     341                 :            : }
     342                 :            : 
     343                 :            : /* Carry out polling-, autostop-, and autoresume-related state changes */
     344                 :          0 : static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
     345                 :            :                 int any_connected, int rhsc_status)
     346                 :            : {
     347                 :          0 :         int     poll_rh = 1;
     348                 :          0 :         int     rhsc_enable;
     349                 :            : 
     350                 :            :         /* Some broken controllers never turn off RHSC in the interrupt
     351                 :            :          * status register.  For their sake we won't re-enable RHSC
     352                 :            :          * interrupts if the interrupt bit is already active.
     353                 :            :          */
     354                 :          0 :         rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) &
     355                 :            :                         OHCI_INTR_RHSC;
     356                 :            : 
     357      [ #  #  # ]:          0 :         switch (ohci->hc_control & OHCI_CTRL_HCFS) {
     358                 :          0 :         case OHCI_USB_OPER:
     359                 :            :                 /* If no status changes are pending, enable RHSC interrupts. */
     360         [ #  # ]:          0 :                 if (!rhsc_enable && !rhsc_status && !changed) {
     361                 :          0 :                         rhsc_enable = OHCI_INTR_RHSC;
     362                 :          0 :                         ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable);
     363                 :            :                 }
     364                 :            : 
     365                 :            :                 /* Keep on polling until we know a device is connected
     366                 :            :                  * and RHSC is enabled, or until we autostop.
     367                 :            :                  */
     368         [ #  # ]:          0 :                 if (!ohci->autostop) {
     369   [ #  #  #  # ]:          0 :                         if (any_connected ||
     370                 :            :                                         !device_may_wakeup(&ohci_to_hcd(ohci)
     371         [ #  # ]:          0 :                                                 ->self.root_hub->dev)) {
     372         [ #  # ]:          0 :                                 if (rhsc_enable)
     373                 :          0 :                                         poll_rh = 0;
     374                 :            :                         } else {
     375                 :          0 :                                 ohci->autostop = 1;
     376                 :          0 :                                 ohci->next_statechange = jiffies + HZ;
     377                 :            :                         }
     378                 :            : 
     379                 :            :                 /* if no devices have been attached for one second, autostop */
     380                 :            :                 } else {
     381         [ #  # ]:          0 :                         if (changed || any_connected) {
     382                 :          0 :                                 ohci->autostop = 0;
     383                 :          0 :                                 ohci->next_statechange = jiffies +
     384                 :            :                                                 STATECHANGE_DELAY;
     385         [ #  # ]:          0 :                         } else if (time_after_eq(jiffies,
     386                 :            :                                                 ohci->next_statechange)
     387         [ #  # ]:          0 :                                         && !ohci->ed_rm_list
     388         [ #  # ]:          0 :                                         && !(ohci->hc_control &
     389                 :            :                                                 OHCI_SCHED_ENABLES)) {
     390                 :          0 :                                 ohci_rh_suspend(ohci, 1);
     391         [ #  # ]:          0 :                                 if (rhsc_enable)
     392                 :          0 :                                         poll_rh = 0;
     393                 :            :                         }
     394                 :            :                 }
     395                 :            :                 break;
     396                 :            : 
     397                 :          0 :         case OHCI_USB_SUSPEND:
     398                 :            :         case OHCI_USB_RESUME:
     399                 :            :                 /* if there is a port change, autostart or ask to be resumed */
     400         [ #  # ]:          0 :                 if (changed) {
     401         [ #  # ]:          0 :                         if (ohci->autostop)
     402                 :          0 :                                 ohci_rh_resume(ohci);
     403                 :            :                         else
     404                 :          0 :                                 usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
     405                 :            : 
     406                 :            :                 /* If remote wakeup is disabled, stop polling */
     407         [ #  # ]:          0 :                 } else if (!ohci->autostop &&
     408         [ #  # ]:          0 :                                 !ohci_to_hcd(ohci)->self.root_hub->
     409                 :            :                                         do_remote_wakeup) {
     410                 :            :                         poll_rh = 0;
     411                 :            : 
     412                 :            :                 } else {
     413                 :            :                         /* If no status changes are pending,
     414                 :            :                          * enable RHSC interrupts
     415                 :            :                          */
     416         [ #  # ]:          0 :                         if (!rhsc_enable && !rhsc_status) {
     417                 :          0 :                                 rhsc_enable = OHCI_INTR_RHSC;
     418                 :          0 :                                 ohci_writel(ohci, rhsc_enable,
     419                 :            :                                                 &ohci->regs->intrenable);
     420                 :            :                         }
     421                 :            :                         /* Keep polling until RHSC is enabled */
     422         [ #  # ]:          0 :                         if (rhsc_enable)
     423                 :            :                                 poll_rh = 0;
     424                 :            :                 }
     425                 :            :                 break;
     426                 :            :         }
     427                 :          0 :         return poll_rh;
     428                 :            : }
     429                 :            : 
     430                 :            : #else   /* CONFIG_PM */
     431                 :            : 
     432                 :            : static inline int ohci_rh_resume(struct ohci_hcd *ohci)
     433                 :            : {
     434                 :            :         return 0;
     435                 :            : }
     436                 :            : 
     437                 :            : /* Carry out polling-related state changes.
     438                 :            :  * autostop isn't used when CONFIG_PM is turned off.
     439                 :            :  */
     440                 :            : static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
     441                 :            :                 int any_connected, int rhsc_status)
     442                 :            : {
     443                 :            :         /* If RHSC is enabled, don't poll */
     444                 :            :         if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
     445                 :            :                 return 0;
     446                 :            : 
     447                 :            :         /* If status changes are pending, continue polling.
     448                 :            :          * Conversely, if no status changes are pending but the RHSC
     449                 :            :          * status bit was set, then RHSC may be broken so continue polling.
     450                 :            :          */
     451                 :            :         if (changed || rhsc_status)
     452                 :            :                 return 1;
     453                 :            : 
     454                 :            :         /* It's safe to re-enable RHSC interrupts */
     455                 :            :         ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
     456                 :            :         return 0;
     457                 :            : }
     458                 :            : 
     459                 :            : #endif  /* CONFIG_PM */
     460                 :            : 
     461                 :            : /*-------------------------------------------------------------------------*/
     462                 :            : 
     463                 :            : /* build "status change" packet (one or two bytes) from HC registers */
     464                 :            : 
     465                 :          0 : int ohci_hub_status_data(struct usb_hcd *hcd, char *buf)
     466                 :            : {
     467                 :          0 :         struct ohci_hcd *ohci = hcd_to_ohci (hcd);
     468                 :          0 :         int             i, changed = 0, length = 1;
     469                 :          0 :         int             any_connected = 0;
     470                 :          0 :         int             rhsc_status;
     471                 :          0 :         unsigned long   flags;
     472                 :            : 
     473                 :          0 :         spin_lock_irqsave (&ohci->lock, flags);
     474         [ #  # ]:          0 :         if (!HCD_HW_ACCESSIBLE(hcd))
     475                 :          0 :                 goto done;
     476                 :            : 
     477                 :            :         /* undocumented erratum seen on at least rev D */
     478         [ #  # ]:          0 :         if ((ohci->flags & OHCI_QUIRK_AMD756)
     479         [ #  # ]:          0 :                         && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
     480                 :          0 :                 ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
     481                 :            :                           ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
     482                 :            :                 /* retry later; "should not happen" */
     483                 :          0 :                 goto done;
     484                 :            :         }
     485                 :            : 
     486                 :            :         /* init status */
     487         [ #  # ]:          0 :         if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
     488                 :          0 :                 buf [0] = changed = 1;
     489                 :            :         else
     490                 :          0 :                 buf [0] = 0;
     491         [ #  # ]:          0 :         if (ohci->num_ports > 7) {
     492                 :          0 :                 buf [1] = 0;
     493                 :          0 :                 length++;
     494                 :            :         }
     495                 :            : 
     496                 :            :         /* Clear the RHSC status flag before reading the port statuses */
     497                 :          0 :         ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus);
     498                 :          0 :         rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
     499                 :            :                         OHCI_INTR_RHSC;
     500                 :            : 
     501                 :            :         /* look at each port */
     502         [ #  # ]:          0 :         for (i = 0; i < ohci->num_ports; i++) {
     503                 :          0 :                 u32     status = roothub_portstatus (ohci, i);
     504                 :            : 
     505                 :            :                 /* can't autostop if ports are connected */
     506                 :          0 :                 any_connected |= (status & RH_PS_CCS);
     507                 :            : 
     508         [ #  # ]:          0 :                 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
     509                 :            :                                 | RH_PS_OCIC | RH_PS_PRSC)) {
     510                 :          0 :                         changed = 1;
     511         [ #  # ]:          0 :                         if (i < 7)
     512                 :          0 :                             buf [0] |= 1 << (i + 1);
     513                 :            :                         else
     514                 :          0 :                             buf [1] |= 1 << (i - 7);
     515                 :            :                 }
     516                 :            :         }
     517                 :            : 
     518         [ #  # ]:          0 :         if (ohci_root_hub_state_changes(ohci, changed,
     519                 :            :                         any_connected, rhsc_status))
     520                 :          0 :                 set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
     521                 :            :         else
     522                 :          0 :                 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
     523                 :            : 
     524                 :            : 
     525                 :          0 : done:
     526                 :          0 :         spin_unlock_irqrestore (&ohci->lock, flags);
     527                 :            : 
     528         [ #  # ]:          0 :         return changed ? length : 0;
     529                 :            : }
     530                 :            : EXPORT_SYMBOL_GPL(ohci_hub_status_data);
     531                 :            : 
     532                 :            : /*-------------------------------------------------------------------------*/
     533                 :            : 
     534                 :            : static void
     535                 :          0 : ohci_hub_descriptor (
     536                 :            :         struct ohci_hcd                 *ohci,
     537                 :            :         struct usb_hub_descriptor       *desc
     538                 :            : ) {
     539                 :          0 :         u32             rh = roothub_a (ohci);
     540                 :          0 :         u16             temp;
     541                 :            : 
     542                 :          0 :         desc->bDescriptorType = USB_DT_HUB;
     543                 :          0 :         desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
     544                 :          0 :         desc->bHubContrCurrent = 0;
     545                 :            : 
     546                 :          0 :         desc->bNbrPorts = ohci->num_ports;
     547                 :          0 :         temp = 1 + (ohci->num_ports / 8);
     548                 :          0 :         desc->bDescLength = 7 + 2 * temp;
     549                 :            : 
     550                 :          0 :         temp = HUB_CHAR_COMMON_LPSM | HUB_CHAR_COMMON_OCPM;
     551         [ #  # ]:          0 :         if (rh & RH_A_NPS)          /* no power switching? */
     552                 :          0 :                 temp |= HUB_CHAR_NO_LPSM;
     553         [ #  # ]:          0 :         if (rh & RH_A_PSM)          /* per-port power switching? */
     554                 :          0 :                 temp |= HUB_CHAR_INDV_PORT_LPSM;
     555         [ #  # ]:          0 :         if (rh & RH_A_NOCP)         /* no overcurrent reporting? */
     556                 :          0 :                 temp |= HUB_CHAR_NO_OCPM;
     557         [ #  # ]:          0 :         else if (rh & RH_A_OCPM)    /* per-port overcurrent reporting? */
     558                 :          0 :                 temp |= HUB_CHAR_INDV_PORT_OCPM;
     559                 :          0 :         desc->wHubCharacteristics = cpu_to_le16(temp);
     560                 :            : 
     561                 :            :         /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
     562                 :          0 :         rh = roothub_b (ohci);
     563                 :          0 :         memset(desc->u.hs.DeviceRemovable, 0xff,
     564                 :            :                         sizeof(desc->u.hs.DeviceRemovable));
     565                 :          0 :         desc->u.hs.DeviceRemovable[0] = rh & RH_B_DR;
     566         [ #  # ]:          0 :         if (ohci->num_ports > 7) {
     567                 :          0 :                 desc->u.hs.DeviceRemovable[1] = (rh & RH_B_DR) >> 8;
     568                 :          0 :                 desc->u.hs.DeviceRemovable[2] = 0xff;
     569                 :            :         } else
     570                 :          0 :                 desc->u.hs.DeviceRemovable[1] = 0xff;
     571                 :          0 : }
     572                 :            : 
     573                 :            : /*-------------------------------------------------------------------------*/
     574                 :            : 
     575                 :            : #ifdef  CONFIG_USB_OTG
     576                 :            : 
     577                 :            : static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
     578                 :            : {
     579                 :            :         struct ohci_hcd *ohci = hcd_to_ohci (hcd);
     580                 :            :         u32                     status;
     581                 :            : 
     582                 :            :         if (!port)
     583                 :            :                 return -EINVAL;
     584                 :            :         port--;
     585                 :            : 
     586                 :            :         /* start port reset before HNP protocol times out */
     587                 :            :         status = ohci_readl(ohci, &ohci->regs->roothub.portstatus [port]);
     588                 :            :         if (!(status & RH_PS_CCS))
     589                 :            :                 return -ENODEV;
     590                 :            : 
     591                 :            :         /* hub_wq will finish the reset later */
     592                 :            :         ohci_writel(ohci, RH_PS_PRS, &ohci->regs->roothub.portstatus [port]);
     593                 :            :         return 0;
     594                 :            : }
     595                 :            : 
     596                 :            : #else
     597                 :            : 
     598                 :            : #define ohci_start_port_reset           NULL
     599                 :            : 
     600                 :            : #endif
     601                 :            : 
     602                 :            : /*-------------------------------------------------------------------------*/
     603                 :            : 
     604                 :            : 
     605                 :            : /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
     606                 :            :  * not necessarily continuous ... to guard against resume signaling.
     607                 :            :  */
     608                 :            : #define PORT_RESET_MSEC         50
     609                 :            : 
     610                 :            : /* this timer value might be vendor-specific ... */
     611                 :            : #define PORT_RESET_HW_MSEC      10
     612                 :            : 
     613                 :            : /* wrap-aware logic morphed from <linux/jiffies.h> */
     614                 :            : #define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
     615                 :            : 
     616                 :            : /* called from some task, normally hub_wq */
     617                 :            : static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
     618                 :            : {
     619                 :            :         __hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
     620                 :            :         u32     temp = 0;
     621                 :            :         u16     now = ohci_readl(ohci, &ohci->regs->fmnumber);
     622                 :            :         u16     reset_done = now + PORT_RESET_MSEC;
     623                 :            :         int     limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);
     624                 :            : 
     625                 :            :         /* build a "continuous enough" reset signal, with up to
     626                 :            :          * 3msec gap between pulses.  scheduler HZ==100 must work;
     627                 :            :          * this might need to be deadline-scheduled.
     628                 :            :          */
     629                 :            :         do {
     630                 :            :                 int limit_2;
     631                 :            : 
     632                 :            :                 /* spin until any current reset finishes */
     633                 :            :                 limit_2 = PORT_RESET_HW_MSEC * 2;
     634                 :            :                 while (--limit_2 >= 0) {
     635                 :            :                         temp = ohci_readl (ohci, portstat);
     636                 :            :                         /* handle e.g. CardBus eject */
     637                 :            :                         if (temp == ~(u32)0)
     638                 :            :                                 return -ESHUTDOWN;
     639                 :            :                         if (!(temp & RH_PS_PRS))
     640                 :            :                                 break;
     641                 :            :                         udelay (500);
     642                 :            :                 }
     643                 :            : 
     644                 :            :                 /* timeout (a hardware error) has been observed when
     645                 :            :                  * EHCI sets CF while this driver is resetting a port;
     646                 :            :                  * presumably other disconnect paths might do it too.
     647                 :            :                  */
     648                 :            :                 if (limit_2 < 0) {
     649                 :            :                         ohci_dbg(ohci,
     650                 :            :                                 "port[%d] reset timeout, stat %08x\n",
     651                 :            :                                 port, temp);
     652                 :            :                         break;
     653                 :            :                 }
     654                 :            : 
     655                 :            :                 if (!(temp & RH_PS_CCS))
     656                 :            :                         break;
     657                 :            :                 if (temp & RH_PS_PRSC)
     658                 :            :                         ohci_writel (ohci, RH_PS_PRSC, portstat);
     659                 :            : 
     660                 :            :                 /* start the next reset, sleep till it's probably done */
     661                 :            :                 ohci_writel (ohci, RH_PS_PRS, portstat);
     662                 :            :                 msleep(PORT_RESET_HW_MSEC);
     663                 :            :                 now = ohci_readl(ohci, &ohci->regs->fmnumber);
     664                 :            :         } while (tick_before(now, reset_done) && --limit_1 >= 0);
     665                 :            : 
     666                 :            :         /* caller synchronizes using PRSC ... and handles PRS
     667                 :            :          * still being set when this returns.
     668                 :            :          */
     669                 :            : 
     670                 :            :         return 0;
     671                 :            : }
     672                 :            : 
     673                 :          0 : int ohci_hub_control(
     674                 :            :         struct usb_hcd  *hcd,
     675                 :            :         u16             typeReq,
     676                 :            :         u16             wValue,
     677                 :            :         u16             wIndex,
     678                 :            :         char            *buf,
     679                 :            :         u16             wLength
     680                 :            : ) {
     681         [ #  # ]:          0 :         struct ohci_hcd *ohci = hcd_to_ohci (hcd);
     682                 :          0 :         int             ports = ohci->num_ports;
     683                 :          0 :         u32             temp;
     684                 :          0 :         int             retval = 0;
     685                 :            : 
     686         [ #  # ]:          0 :         if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
     687                 :            :                 return -ESHUTDOWN;
     688                 :            : 
     689   [ #  #  #  #  :          0 :         switch (typeReq) {
             #  #  #  # ]
     690                 :          0 :         case ClearHubFeature:
     691      [ #  #  # ]:          0 :                 switch (wValue) {
     692                 :          0 :                 case C_HUB_OVER_CURRENT:
     693                 :          0 :                         ohci_writel (ohci, RH_HS_OCIC,
     694                 :            :                                         &ohci->regs->roothub.status);
     695                 :            :                 case C_HUB_LOCAL_POWER:
     696                 :            :                         break;
     697                 :          0 :                 default:
     698                 :          0 :                         goto error;
     699                 :            :                 }
     700                 :            :                 break;
     701                 :          0 :         case ClearPortFeature:
     702   [ #  #  #  # ]:          0 :                 if (!wIndex || wIndex > ports)
     703                 :          0 :                         goto error;
     704                 :          0 :                 wIndex--;
     705                 :            : 
     706   [ #  #  #  #  :          0 :                 switch (wValue) {
             #  #  #  #  
                      # ]
     707                 :            :                 case USB_PORT_FEAT_ENABLE:
     708                 :            :                         temp = RH_PS_CCS;
     709                 :            :                         break;
     710                 :          0 :                 case USB_PORT_FEAT_C_ENABLE:
     711                 :          0 :                         temp = RH_PS_PESC;
     712                 :          0 :                         break;
     713                 :          0 :                 case USB_PORT_FEAT_SUSPEND:
     714                 :          0 :                         temp = RH_PS_POCI;
     715                 :          0 :                         break;
     716                 :          0 :                 case USB_PORT_FEAT_C_SUSPEND:
     717                 :          0 :                         temp = RH_PS_PSSC;
     718                 :          0 :                         break;
     719                 :          0 :                 case USB_PORT_FEAT_POWER:
     720                 :          0 :                         temp = RH_PS_LSDA;
     721                 :          0 :                         break;
     722                 :          0 :                 case USB_PORT_FEAT_C_CONNECTION:
     723                 :          0 :                         temp = RH_PS_CSC;
     724                 :          0 :                         break;
     725                 :          0 :                 case USB_PORT_FEAT_C_OVER_CURRENT:
     726                 :          0 :                         temp = RH_PS_OCIC;
     727                 :          0 :                         break;
     728                 :          0 :                 case USB_PORT_FEAT_C_RESET:
     729                 :          0 :                         temp = RH_PS_PRSC;
     730                 :          0 :                         break;
     731                 :          0 :                 default:
     732                 :          0 :                         goto error;
     733                 :            :                 }
     734                 :          0 :                 ohci_writel (ohci, temp,
     735                 :            :                                 &ohci->regs->roothub.portstatus [wIndex]);
     736                 :            :                 // ohci_readl (ohci, &ohci->regs->roothub.portstatus [wIndex]);
     737                 :            :                 break;
     738                 :          0 :         case GetHubDescriptor:
     739                 :          0 :                 ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
     740                 :          0 :                 break;
     741                 :          0 :         case GetHubStatus:
     742                 :          0 :                 temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
     743                 :          0 :                 put_unaligned_le32(temp, buf);
     744                 :            :                 break;
     745                 :          0 :         case GetPortStatus:
     746   [ #  #  #  # ]:          0 :                 if (!wIndex || wIndex > ports)
     747                 :          0 :                         goto error;
     748                 :          0 :                 wIndex--;
     749                 :          0 :                 temp = roothub_portstatus (ohci, wIndex);
     750                 :          0 :                 put_unaligned_le32(temp, buf);
     751                 :            : 
     752                 :          0 :                 if (*(u16*)(buf+2))     /* only if wPortChange is interesting */
     753                 :            :                         dbg_port(ohci, "GetStatus", wIndex, temp);
     754                 :            :                 break;
     755                 :          0 :         case SetHubFeature:
     756         [ #  # ]:          0 :                 switch (wValue) {
     757                 :            :                 case C_HUB_OVER_CURRENT:
     758                 :            :                         // FIXME:  this can be cleared, yes?
     759                 :            :                 case C_HUB_LOCAL_POWER:
     760                 :            :                         break;
     761                 :          0 :                 default:
     762                 :          0 :                         goto error;
     763                 :            :                 }
     764                 :            :                 break;
     765                 :          0 :         case SetPortFeature:
     766   [ #  #  #  # ]:          0 :                 if (!wIndex || wIndex > ports)
     767                 :          0 :                         goto error;
     768                 :          0 :                 wIndex--;
     769   [ #  #  #  # ]:          0 :                 switch (wValue) {
     770                 :          0 :                 case USB_PORT_FEAT_SUSPEND:
     771                 :            : #ifdef  CONFIG_USB_OTG
     772                 :            :                         if (hcd->self.otg_port == (wIndex + 1)
     773                 :            :                                         && hcd->self.b_hnp_enable)
     774                 :            :                                 ohci->start_hnp(ohci);
     775                 :            :                         else
     776                 :            : #endif
     777                 :          0 :                         ohci_writel (ohci, RH_PS_PSS,
     778                 :            :                                 &ohci->regs->roothub.portstatus [wIndex]);
     779                 :            :                         break;
     780                 :          0 :                 case USB_PORT_FEAT_POWER:
     781                 :          0 :                         ohci_writel (ohci, RH_PS_PPS,
     782                 :            :                                 &ohci->regs->roothub.portstatus [wIndex]);
     783                 :            :                         break;
     784                 :          0 :                 case USB_PORT_FEAT_RESET:
     785                 :          0 :                         retval = root_port_reset (ohci, wIndex);
     786                 :          0 :                         break;
     787                 :          0 :                 default:
     788                 :          0 :                         goto error;
     789                 :            :                 }
     790                 :            :                 break;
     791                 :            : 
     792                 :            :         default:
     793                 :            : error:
     794                 :            :                 /* "protocol stall" on error */
     795                 :            :                 retval = -EPIPE;
     796                 :            :         }
     797                 :            :         return retval;
     798                 :            : }
     799                 :            : EXPORT_SYMBOL_GPL(ohci_hub_control);

Generated by: LCOV version 1.14