@@ -626,6 +626,38 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref,
626626 return err ;
627627}
628628
629+ static void xenvif_disconnect_queue (struct xenvif_queue * queue )
630+ {
631+ if (queue -> tx_irq ) {
632+ unbind_from_irqhandler (queue -> tx_irq , queue );
633+ if (queue -> tx_irq == queue -> rx_irq )
634+ queue -> rx_irq = 0 ;
635+ queue -> tx_irq = 0 ;
636+ }
637+
638+ if (queue -> rx_irq ) {
639+ unbind_from_irqhandler (queue -> rx_irq , queue );
640+ queue -> rx_irq = 0 ;
641+ }
642+
643+ if (queue -> task ) {
644+ kthread_stop (queue -> task );
645+ queue -> task = NULL ;
646+ }
647+
648+ if (queue -> dealloc_task ) {
649+ kthread_stop (queue -> dealloc_task );
650+ queue -> dealloc_task = NULL ;
651+ }
652+
653+ if (queue -> napi .poll ) {
654+ netif_napi_del (& queue -> napi );
655+ queue -> napi .poll = NULL ;
656+ }
657+
658+ xenvif_unmap_frontend_data_rings (queue );
659+ }
660+
629661int xenvif_connect_data (struct xenvif_queue * queue ,
630662 unsigned long tx_ring_ref ,
631663 unsigned long rx_ring_ref ,
@@ -651,13 +683,27 @@ int xenvif_connect_data(struct xenvif_queue *queue,
651683 netif_napi_add (queue -> vif -> dev , & queue -> napi , xenvif_poll ,
652684 XENVIF_NAPI_WEIGHT );
653685
686+ queue -> stalled = true;
687+
688+ task = kthread_run (xenvif_kthread_guest_rx , queue ,
689+ "%s-guest-rx" , queue -> name );
690+ if (IS_ERR (task ))
691+ goto kthread_err ;
692+ queue -> task = task ;
693+
694+ task = kthread_run (xenvif_dealloc_kthread , queue ,
695+ "%s-dealloc" , queue -> name );
696+ if (IS_ERR (task ))
697+ goto kthread_err ;
698+ queue -> dealloc_task = task ;
699+
654700 if (tx_evtchn == rx_evtchn ) {
655701 /* feature-split-event-channels == 0 */
656702 err = bind_interdomain_evtchn_to_irqhandler (
657703 queue -> vif -> domid , tx_evtchn , xenvif_interrupt , 0 ,
658704 queue -> name , queue );
659705 if (err < 0 )
660- goto err_unmap ;
706+ goto err ;
661707 queue -> tx_irq = queue -> rx_irq = err ;
662708 disable_irq (queue -> tx_irq );
663709 } else {
@@ -668,7 +714,7 @@ int xenvif_connect_data(struct xenvif_queue *queue,
668714 queue -> vif -> domid , tx_evtchn , xenvif_tx_interrupt , 0 ,
669715 queue -> tx_irq_name , queue );
670716 if (err < 0 )
671- goto err_unmap ;
717+ goto err ;
672718 queue -> tx_irq = err ;
673719 disable_irq (queue -> tx_irq );
674720
@@ -678,47 +724,18 @@ int xenvif_connect_data(struct xenvif_queue *queue,
678724 queue -> vif -> domid , rx_evtchn , xenvif_rx_interrupt , 0 ,
679725 queue -> rx_irq_name , queue );
680726 if (err < 0 )
681- goto err_tx_unbind ;
727+ goto err ;
682728 queue -> rx_irq = err ;
683729 disable_irq (queue -> rx_irq );
684730 }
685731
686- queue -> stalled = true;
687-
688- task = kthread_create (xenvif_kthread_guest_rx ,
689- (void * )queue , "%s-guest-rx" , queue -> name );
690- if (IS_ERR (task )) {
691- pr_warn ("Could not allocate kthread for %s\n" , queue -> name );
692- err = PTR_ERR (task );
693- goto err_rx_unbind ;
694- }
695- queue -> task = task ;
696- get_task_struct (task );
697-
698- task = kthread_create (xenvif_dealloc_kthread ,
699- (void * )queue , "%s-dealloc" , queue -> name );
700- if (IS_ERR (task )) {
701- pr_warn ("Could not allocate kthread for %s\n" , queue -> name );
702- err = PTR_ERR (task );
703- goto err_rx_unbind ;
704- }
705- queue -> dealloc_task = task ;
706-
707- wake_up_process (queue -> task );
708- wake_up_process (queue -> dealloc_task );
709-
710732 return 0 ;
711733
712- err_rx_unbind :
713- unbind_from_irqhandler (queue -> rx_irq , queue );
714- queue -> rx_irq = 0 ;
715- err_tx_unbind :
716- unbind_from_irqhandler (queue -> tx_irq , queue );
717- queue -> tx_irq = 0 ;
718- err_unmap :
719- xenvif_unmap_frontend_data_rings (queue );
720- netif_napi_del (& queue -> napi );
734+ kthread_err :
735+ pr_warn ("Could not allocate kthread for %s\n" , queue -> name );
736+ err = PTR_ERR (task );
721737err :
738+ xenvif_disconnect_queue (queue );
722739 return err ;
723740}
724741
@@ -746,30 +763,7 @@ void xenvif_disconnect_data(struct xenvif *vif)
746763 for (queue_index = 0 ; queue_index < num_queues ; ++ queue_index ) {
747764 queue = & vif -> queues [queue_index ];
748765
749- netif_napi_del (& queue -> napi );
750-
751- if (queue -> task ) {
752- kthread_stop (queue -> task );
753- put_task_struct (queue -> task );
754- queue -> task = NULL ;
755- }
756-
757- if (queue -> dealloc_task ) {
758- kthread_stop (queue -> dealloc_task );
759- queue -> dealloc_task = NULL ;
760- }
761-
762- if (queue -> tx_irq ) {
763- if (queue -> tx_irq == queue -> rx_irq )
764- unbind_from_irqhandler (queue -> tx_irq , queue );
765- else {
766- unbind_from_irqhandler (queue -> tx_irq , queue );
767- unbind_from_irqhandler (queue -> rx_irq , queue );
768- }
769- queue -> tx_irq = 0 ;
770- }
771-
772- xenvif_unmap_frontend_data_rings (queue );
766+ xenvif_disconnect_queue (queue );
773767 }
774768
775769 xenvif_mcast_addr_list_free (vif );
0 commit comments