@@ -4996,8 +4996,7 @@ static void port_event(struct usb_hub *hub, int port1)
49964996 hub_port_connect_change (hub , port1 , portstatus , portchange );
49974997}
49984998
4999-
5000- static void hub_events (void )
4999+ static void hub_event (void )
50015000{
50025001 struct list_head * tmp ;
50035002 struct usb_device * hdev ;
@@ -5008,144 +5007,131 @@ static void hub_events(void)
50085007 u16 hubchange ;
50095008 int i , ret ;
50105009
5011- /*
5012- * We restart the list every time to avoid a deadlock with
5013- * deleting hubs downstream from this one. This should be
5014- * safe since we delete the hub from the event list.
5015- * Not the most efficient, but avoids deadlocks.
5016- */
5017- while (1 ) {
5010+ /* Grab the first entry at the beginning of the list */
5011+ spin_lock_irq (& hub_event_lock );
5012+ if (list_empty (& hub_event_list )) {
5013+ spin_unlock_irq (& hub_event_lock );
5014+ return ;
5015+ }
50185016
5019- /* Grab the first entry at the beginning of the list */
5020- spin_lock_irq (& hub_event_lock );
5021- if (list_empty (& hub_event_list )) {
5022- spin_unlock_irq (& hub_event_lock );
5023- break ;
5024- }
5017+ tmp = hub_event_list .next ;
5018+ list_del_init (tmp );
50255019
5026- tmp = hub_event_list .next ;
5027- list_del_init (tmp );
5020+ hub = list_entry (tmp , struct usb_hub , event_list );
5021+ kref_get (& hub -> kref );
5022+ spin_unlock_irq (& hub_event_lock );
50285023
5029- hub = list_entry (tmp , struct usb_hub , event_list );
5030- kref_get (& hub -> kref );
5031- spin_unlock_irq (& hub_event_lock );
5024+ hdev = hub -> hdev ;
5025+ hub_dev = hub -> intfdev ;
5026+ intf = to_usb_interface (hub_dev );
5027+ dev_dbg (hub_dev , "state %d ports %d chg %04x evt %04x\n" ,
5028+ hdev -> state , hdev -> maxchild ,
5029+ /* NOTE: expects max 15 ports... */
5030+ (u16 ) hub -> change_bits [0 ],
5031+ (u16 ) hub -> event_bits [0 ]);
5032+
5033+ /* Lock the device, then check to see if we were
5034+ * disconnected while waiting for the lock to succeed. */
5035+ usb_lock_device (hdev );
5036+ if (unlikely (hub -> disconnected ))
5037+ goto out_disconnected ;
5038+
5039+ /* If the hub has died, clean up after it */
5040+ if (hdev -> state == USB_STATE_NOTATTACHED ) {
5041+ hub -> error = - ENODEV ;
5042+ hub_quiesce (hub , HUB_DISCONNECT );
5043+ goto out ;
5044+ }
5045+
5046+ /* Autoresume */
5047+ ret = usb_autopm_get_interface (intf );
5048+ if (ret ) {
5049+ dev_dbg (hub_dev , "Can't autoresume: %d\n" , ret );
5050+ goto out ;
5051+ }
50325052
5033- hdev = hub -> hdev ;
5034- hub_dev = hub -> intfdev ;
5035- intf = to_usb_interface (hub_dev );
5036- dev_dbg (hub_dev , "state %d ports %d chg %04x evt %04x\n" ,
5037- hdev -> state , hdev -> maxchild ,
5038- /* NOTE: expects max 15 ports... */
5039- (u16 ) hub -> change_bits [0 ],
5040- (u16 ) hub -> event_bits [0 ]);
5041-
5042- /* Lock the device, then check to see if we were
5043- * disconnected while waiting for the lock to succeed. */
5044- usb_lock_device (hdev );
5045- if (unlikely (hub -> disconnected ))
5046- goto loop_disconnected ;
5047-
5048- /* If the hub has died, clean up after it */
5049- if (hdev -> state == USB_STATE_NOTATTACHED ) {
5050- hub -> error = - ENODEV ;
5051- hub_quiesce (hub , HUB_DISCONNECT );
5052- goto loop ;
5053- }
5053+ /* If this is an inactive hub, do nothing */
5054+ if (hub -> quiescing )
5055+ goto out_autopm ;
5056+
5057+ if (hub -> error ) {
5058+ dev_dbg (hub_dev , "resetting for error %d\n" , hub -> error );
50545059
5055- /* Autoresume */
5056- ret = usb_autopm_get_interface (intf );
5060+ ret = usb_reset_device (hdev );
50575061 if (ret ) {
5058- dev_dbg (hub_dev , "Can't autoresume : %d\n" , ret );
5059- goto loop ;
5062+ dev_dbg (hub_dev , "error resetting hub : %d\n" , ret );
5063+ goto out_autopm ;
50605064 }
50615065
5062- /* If this is an inactive hub, do nothing */
5063- if ( hub -> quiescing )
5064- goto loop_autopm ;
5066+ hub -> nerrors = 0 ;
5067+ hub -> error = 0 ;
5068+ }
50655069
5066- if ( hub -> error ) {
5067- dev_dbg ( hub_dev , "resetting for error %d\n" ,
5068- hub -> error ) ;
5070+ /* deal with port status changes */
5071+ for ( i = 1 ; i <= hdev -> maxchild ; i ++ ) {
5072+ struct usb_port * port_dev = hub -> ports [ i - 1 ] ;
50695073
5070- ret = usb_reset_device (hdev );
5071- if (ret ) {
5072- dev_dbg (hub_dev ,
5073- "error resetting hub: %d\n" , ret );
5074- goto loop_autopm ;
5075- }
5076-
5077- hub -> nerrors = 0 ;
5078- hub -> error = 0 ;
5074+ if (test_bit (i , hub -> event_bits )
5075+ || test_bit (i , hub -> change_bits )
5076+ || test_bit (i , hub -> wakeup_bits )) {
5077+ /*
5078+ * The get_noresume and barrier ensure that if
5079+ * the port was in the process of resuming, we
5080+ * flush that work and keep the port active for
5081+ * the duration of the port_event(). However,
5082+ * if the port is runtime pm suspended
5083+ * (powered-off), we leave it in that state, run
5084+ * an abbreviated port_event(), and move on.
5085+ */
5086+ pm_runtime_get_noresume (& port_dev -> dev );
5087+ pm_runtime_barrier (& port_dev -> dev );
5088+ usb_lock_port (port_dev );
5089+ port_event (hub , i );
5090+ usb_unlock_port (port_dev );
5091+ pm_runtime_put_sync (& port_dev -> dev );
50795092 }
5093+ }
50805094
5081- /* deal with port status changes */
5082- for (i = 1 ; i <= hdev -> maxchild ; i ++ ) {
5083- struct usb_port * port_dev = hub -> ports [i - 1 ];
5084-
5085- if (test_bit (i , hub -> event_bits )
5086- || test_bit (i , hub -> change_bits )
5087- || test_bit (i , hub -> wakeup_bits )) {
5088- /*
5089- * The get_noresume and barrier ensure that if
5090- * the port was in the process of resuming, we
5091- * flush that work and keep the port active for
5092- * the duration of the port_event(). However,
5093- * if the port is runtime pm suspended
5094- * (powered-off), we leave it in that state, run
5095- * an abbreviated port_event(), and move on.
5096- */
5097- pm_runtime_get_noresume (& port_dev -> dev );
5098- pm_runtime_barrier (& port_dev -> dev );
5099- usb_lock_port (port_dev );
5100- port_event (hub , i );
5101- usb_unlock_port (port_dev );
5102- pm_runtime_put_sync (& port_dev -> dev );
5103- }
5095+ /* deal with hub status changes */
5096+ if (test_and_clear_bit (0 , hub -> event_bits ) == 0 )
5097+ ; /* do nothing */
5098+ else if (hub_hub_status (hub , & hubstatus , & hubchange ) < 0 )
5099+ dev_err (hub_dev , "get_hub_status failed\n" );
5100+ else {
5101+ if (hubchange & HUB_CHANGE_LOCAL_POWER ) {
5102+ dev_dbg (hub_dev , "power change\n" );
5103+ clear_hub_feature (hdev , C_HUB_LOCAL_POWER );
5104+ if (hubstatus & HUB_STATUS_LOCAL_POWER )
5105+ /* FIXME: Is this always true? */
5106+ hub -> limited_power = 1 ;
5107+ else
5108+ hub -> limited_power = 0 ;
51045109 }
5110+ if (hubchange & HUB_CHANGE_OVERCURRENT ) {
5111+ u16 status = 0 ;
5112+ u16 unused ;
51055113
5106- /* deal with hub status changes */
5107- if (test_and_clear_bit (0 , hub -> event_bits ) == 0 )
5108- ; /* do nothing */
5109- else if (hub_hub_status (hub , & hubstatus , & hubchange ) < 0 )
5110- dev_err (hub_dev , "get_hub_status failed\n" );
5111- else {
5112- if (hubchange & HUB_CHANGE_LOCAL_POWER ) {
5113- dev_dbg (hub_dev , "power change\n" );
5114- clear_hub_feature (hdev , C_HUB_LOCAL_POWER );
5115- if (hubstatus & HUB_STATUS_LOCAL_POWER )
5116- /* FIXME: Is this always true? */
5117- hub -> limited_power = 1 ;
5118- else
5119- hub -> limited_power = 0 ;
5120- }
5121- if (hubchange & HUB_CHANGE_OVERCURRENT ) {
5122- u16 status = 0 ;
5123- u16 unused ;
5124-
5125- dev_dbg (hub_dev , "over-current change\n" );
5126- clear_hub_feature (hdev , C_HUB_OVER_CURRENT );
5127- msleep (500 ); /* Cool down */
5128- hub_power_on (hub , true);
5129- hub_hub_status (hub , & status , & unused );
5130- if (status & HUB_STATUS_OVERCURRENT )
5131- dev_err (hub_dev , "over-current "
5132- "condition\n" );
5133- }
5114+ dev_dbg (hub_dev , "over-current change\n" );
5115+ clear_hub_feature (hdev , C_HUB_OVER_CURRENT );
5116+ msleep (500 ); /* Cool down */
5117+ hub_power_on (hub , true);
5118+ hub_hub_status (hub , & status , & unused );
5119+ if (status & HUB_STATUS_OVERCURRENT )
5120+ dev_err (hub_dev , "over-current condition\n" );
51345121 }
5122+ }
51355123
5136- loop_autopm :
5137- /* Balance the usb_autopm_get_interface() above */
5138- usb_autopm_put_interface_no_suspend (intf );
5139- loop :
5140- /* Balance the usb_autopm_get_interface_no_resume() in
5141- * kick_khubd() and allow autosuspend.
5142- */
5143- usb_autopm_put_interface (intf );
5144- loop_disconnected :
5145- usb_unlock_device (hdev );
5146- kref_put (& hub -> kref , hub_release );
5147-
5148- } /* end while (1) */
5124+ out_autopm :
5125+ /* Balance the usb_autopm_get_interface() above */
5126+ usb_autopm_put_interface_no_suspend (intf );
5127+ out :
5128+ /* Balance the usb_autopm_get_interface_no_resume() in
5129+ * kick_khubd() and allow autosuspend.
5130+ */
5131+ usb_autopm_put_interface (intf );
5132+ out_disconnected :
5133+ usb_unlock_device (hdev );
5134+ kref_put (& hub -> kref , hub_release );
51495135}
51505136
51515137static int hub_thread (void * __unused )
@@ -5158,7 +5144,7 @@ static int hub_thread(void *__unused)
51585144 set_freezable ();
51595145
51605146 do {
5161- hub_events ();
5147+ hub_event ();
51625148 wait_event_freezable (khubd_wait ,
51635149 !list_empty (& hub_event_list ) ||
51645150 kthread_should_stop ());
0 commit comments