@@ -446,13 +446,6 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
446446 return - ENOMEM ;
447447
448448 fc_host -> dev_loss_tmo = fc_dev_loss_tmo ;
449- fc_host -> devloss_work_q = alloc_workqueue ("fc_dl_%d" , 0 , 0 ,
450- shost -> host_no );
451- if (!fc_host -> devloss_work_q ) {
452- destroy_workqueue (fc_host -> work_q );
453- fc_host -> work_q = NULL ;
454- return - ENOMEM ;
455- }
456449
457450 fc_bsg_hostadd (shost , fc_host );
458451 /* ignore any bsg add error - we just can't do sgio */
@@ -2814,17 +2807,18 @@ fc_flush_work(struct Scsi_Host *shost)
28142807/**
28152808 * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
28162809 * @shost: Pointer to Scsi_Host bound to fc_host.
2810+ * @rport: rport associated with the devloss work
28172811 * @work: Work to queue for execution.
28182812 * @delay: jiffies to delay the work queuing
28192813 *
28202814 * Return value:
28212815 * 1 on success / 0 already queued / < 0 for error
28222816 */
28232817static int
2824- fc_queue_devloss_work (struct Scsi_Host * shost , struct delayed_work * work ,
2825- unsigned long delay )
2818+ fc_queue_devloss_work (struct Scsi_Host * shost , struct fc_rport * rport ,
2819+ struct delayed_work * work , unsigned long delay )
28262820{
2827- if (unlikely (!fc_host_devloss_work_q ( shost ) )) {
2821+ if (unlikely (!rport -> devloss_work_q )) {
28282822 printk (KERN_ERR
28292823 "ERROR: FC host '%s' attempted to queue work, "
28302824 "when no workqueue created.\n" , shost -> hostt -> name );
@@ -2833,25 +2827,26 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
28332827 return - EINVAL ;
28342828 }
28352829
2836- return queue_delayed_work (fc_host_devloss_work_q ( shost ) , work , delay );
2830+ return queue_delayed_work (rport -> devloss_work_q , work , delay );
28372831}
28382832
28392833/**
28402834 * fc_flush_devloss - Flush a fc_host's devloss workqueue.
28412835 * @shost: Pointer to Scsi_Host bound to fc_host.
2836+ * @rport: rport associated with the devloss work
28422837 */
28432838static void
2844- fc_flush_devloss (struct Scsi_Host * shost )
2839+ fc_flush_devloss (struct Scsi_Host * shost , struct fc_rport * rport )
28452840{
2846- if (! fc_host_devloss_work_q ( shost )) {
2841+ if (unlikely (! rport -> devloss_work_q )) {
28472842 printk (KERN_ERR
28482843 "ERROR: FC host '%s' attempted to flush work, "
28492844 "when no workqueue created.\n" , shost -> hostt -> name );
28502845 dump_stack ();
28512846 return ;
28522847 }
28532848
2854- flush_workqueue (fc_host_devloss_work_q ( shost ) );
2849+ flush_workqueue (rport -> devloss_work_q );
28552850}
28562851
28572852
@@ -2913,13 +2908,6 @@ fc_remove_host(struct Scsi_Host *shost)
29132908 fc_host -> work_q = NULL ;
29142909 destroy_workqueue (work_q );
29152910 }
2916-
2917- /* flush all devloss work items, then kill it */
2918- if (fc_host -> devloss_work_q ) {
2919- work_q = fc_host -> devloss_work_q ;
2920- fc_host -> devloss_work_q = NULL ;
2921- destroy_workqueue (work_q );
2922- }
29232911}
29242912EXPORT_SYMBOL (fc_remove_host );
29252913
@@ -2967,6 +2955,7 @@ fc_rport_final_delete(struct work_struct *work)
29672955 struct device * dev = & rport -> dev ;
29682956 struct Scsi_Host * shost = rport_to_shost (rport );
29692957 struct fc_internal * i = to_fc_internal (shost -> transportt );
2958+ struct workqueue_struct * work_q ;
29702959 unsigned long flags ;
29712960 int do_callback = 0 ;
29722961
@@ -2988,9 +2977,9 @@ fc_rport_final_delete(struct work_struct *work)
29882977 if (rport -> flags & FC_RPORT_DEVLOSS_PENDING ) {
29892978 spin_unlock_irqrestore (shost -> host_lock , flags );
29902979 if (!cancel_delayed_work (& rport -> fail_io_work ))
2991- fc_flush_devloss (shost );
2980+ fc_flush_devloss (shost , rport );
29922981 if (!cancel_delayed_work (& rport -> dev_loss_work ))
2993- fc_flush_devloss (shost );
2982+ fc_flush_devloss (shost , rport );
29942983 cancel_work_sync (& rport -> scan_work );
29952984 spin_lock_irqsave (shost -> host_lock , flags );
29962985 rport -> flags &= ~FC_RPORT_DEVLOSS_PENDING ;
@@ -3021,6 +3010,12 @@ fc_rport_final_delete(struct work_struct *work)
30213010
30223011 fc_bsg_remove (rport -> rqst_q );
30233012
3013+ if (rport -> devloss_work_q ) {
3014+ work_q = rport -> devloss_work_q ;
3015+ rport -> devloss_work_q = NULL ;
3016+ destroy_workqueue (work_q );
3017+ }
3018+
30243019 transport_remove_device (dev );
30253020 device_del (dev );
30263021 transport_destroy_device (dev );
@@ -3093,6 +3088,22 @@ fc_remote_port_create(struct Scsi_Host *shost, int channel,
30933088
30943089 spin_unlock_irqrestore (shost -> host_lock , flags );
30953090
3091+ rport -> devloss_work_q = alloc_workqueue ("fc_dl_%d_%d" , 0 , 0 ,
3092+ shost -> host_no , rport -> number );
3093+ if (!rport -> devloss_work_q ) {
3094+ printk (KERN_ERR "FC Remote Port alloc_workqueue failed\n" );
3095+ /*
3096+ * Note that we have not yet called device_initialize() / get_device()
3097+ * Cannot reclaim incremented rport->number because we released host_lock
3098+ */
3099+ spin_lock_irqsave (shost -> host_lock , flags );
3100+ list_del (& rport -> peers );
3101+ scsi_host_put (shost ); /* for fc_host->rport list */
3102+ spin_unlock_irqrestore (shost -> host_lock , flags );
3103+ kfree (rport );
3104+ return NULL ;
3105+ }
3106+
30963107 dev = & rport -> dev ;
30973108 device_initialize (dev ); /* takes self reference */
30983109 dev -> parent = get_device (& shost -> shost_gendev ); /* parent reference */
@@ -3255,9 +3266,9 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
32553266 * be checked and will NOOP the function.
32563267 */
32573268 if (!cancel_delayed_work (& rport -> fail_io_work ))
3258- fc_flush_devloss (shost );
3269+ fc_flush_devloss (shost , rport );
32593270 if (!cancel_delayed_work (& rport -> dev_loss_work ))
3260- fc_flush_devloss (shost );
3271+ fc_flush_devloss (shost , rport );
32613272
32623273 spin_lock_irqsave (shost -> host_lock , flags );
32633274
@@ -3451,11 +3462,12 @@ fc_remote_port_delete(struct fc_rport *rport)
34513462 /* see if we need to kill io faster than waiting for device loss */
34523463 if ((rport -> fast_io_fail_tmo != -1 ) &&
34533464 (rport -> fast_io_fail_tmo < timeout ))
3454- fc_queue_devloss_work (shost , & rport -> fail_io_work ,
3455- rport -> fast_io_fail_tmo * HZ );
3465+ fc_queue_devloss_work (shost , rport , & rport -> fail_io_work ,
3466+ rport -> fast_io_fail_tmo * HZ );
34563467
34573468 /* cap the length the devices can be blocked until they are deleted */
3458- fc_queue_devloss_work (shost , & rport -> dev_loss_work , timeout * HZ );
3469+ fc_queue_devloss_work (shost , rport , & rport -> dev_loss_work ,
3470+ timeout * HZ );
34593471}
34603472EXPORT_SYMBOL (fc_remote_port_delete );
34613473
@@ -3509,14 +3521,14 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
35093521 * state as the LLDD would not have had an rport
35103522 * reference to pass us.
35113523 *
3512- * Take no action on the del_timer failure as the state
3524+ * Take no action on the timer_delete() failure as the state
35133525 * machine state change will validate the
35143526 * transaction.
35153527 */
35163528 if (!cancel_delayed_work (& rport -> fail_io_work ))
3517- fc_flush_devloss (shost );
3529+ fc_flush_devloss (shost , rport );
35183530 if (!cancel_delayed_work (& rport -> dev_loss_work ))
3519- fc_flush_devloss (shost );
3531+ fc_flush_devloss (shost , rport );
35203532
35213533 spin_lock_irqsave (shost -> host_lock , flags );
35223534 rport -> flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
0 commit comments