1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: zfcp: Move scan_target to scsi host workqueue
3 References: bnc#484767,LTC#52236
5 Symptom: Trying to attach a non-existing LUN blocks all state
6 changes in the zfcp driver.
7 Problem: If the storage server does not respond, the
8 scsi_scan_target call blocks until it reaches all
9 timeouts. This blocks all other tasks on the zfcp workqueue.
10 Solution: Run the scsi_scan_target work on the scsi host
11 workqueue, the same one where the scan from the SCSI
14 Acked-by: John Jolly <jjolly@suse.de>
16 drivers/s390/scsi/zfcp_aux.c | 5 +---
17 drivers/s390/scsi/zfcp_def.h | 2 -
18 drivers/s390/scsi/zfcp_erp.c | 49 +++---------------------------------------
19 drivers/s390/scsi/zfcp_ext.h | 1
20 drivers/s390/scsi/zfcp_scsi.c | 14 ++++++++++++
21 5 files changed, 22 insertions(+), 49 deletions(-)
23 --- a/drivers/s390/scsi/zfcp_aux.c 2009-03-16 16:41:33.000000000 +0100
24 +++ b/drivers/s390/scsi/zfcp_aux.c 2009-03-16 16:42:42.000000000 +0100
25 @@ -133,9 +133,7 @@ static void __init zfcp_init_device_conf
26 ccw_device_set_online(adapter->ccw_device);
28 zfcp_erp_wait(adapter);
29 - wait_event(adapter->erp_done_wqh,
30 - !(atomic_read(&unit->status) &
31 - ZFCP_STATUS_UNIT_SCSI_WORK_PENDING));
32 + flush_work(&unit->scsi_work);
34 down(&zfcp_data.config_sema);
36 @@ -288,6 +286,7 @@ struct zfcp_unit *zfcp_unit_enqueue(stru
38 atomic_set(&unit->refcount, 0);
39 init_waitqueue_head(&unit->remove_wq);
40 + INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
43 unit->fcp_lun = fcp_lun;
44 --- a/drivers/s390/scsi/zfcp_def.h 2009-03-16 16:41:33.000000000 +0100
45 +++ b/drivers/s390/scsi/zfcp_def.h 2009-03-16 16:43:18.000000000 +0100
46 @@ -273,7 +273,6 @@ enum zfcp_wka_status {
47 #define ZFCP_STATUS_UNIT_SHARED 0x00000004
48 #define ZFCP_STATUS_UNIT_READONLY 0x00000008
49 #define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
50 -#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
52 /* FSF request status (this does not have a common part) */
53 #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
54 @@ -558,6 +557,7 @@ struct zfcp_unit {
55 struct zfcp_erp_action erp_action; /* pending error recovery */
57 struct zfcp_latencies latencies;
58 + struct work_struct scsi_work;
62 --- a/drivers/s390/scsi/zfcp_erp.c 2009-03-16 16:41:33.000000000 +0100
63 +++ b/drivers/s390/scsi/zfcp_erp.c 2009-03-16 16:44:04.000000000 +0100
64 @@ -1184,48 +1184,6 @@ static void zfcp_erp_action_dequeue(stru
68 -struct zfcp_erp_add_work {
69 - struct zfcp_unit *unit;
70 - struct work_struct work;
73 -static void zfcp_erp_scsi_scan(struct work_struct *work)
75 - struct zfcp_erp_add_work *p =
76 - container_of(work, struct zfcp_erp_add_work, work);
77 - struct zfcp_unit *unit = p->unit;
78 - struct fc_rport *rport = unit->port->rport;
80 - if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
81 - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
82 - scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
83 - atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
84 - zfcp_unit_put(unit);
85 - wake_up(&unit->port->adapter->erp_done_wqh);
89 -static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
91 - struct zfcp_erp_add_work *p;
93 - p = kzalloc(sizeof(*p), GFP_KERNEL);
95 - dev_err(&unit->port->adapter->ccw_device->dev,
96 - "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
97 - (unsigned long long)unit->fcp_lun,
98 - (unsigned long long)unit->port->wwpn);
102 - zfcp_unit_get(unit);
103 - atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
104 - INIT_WORK(&p->work, zfcp_erp_scsi_scan);
106 - if (!queue_work(zfcp_data.work_queue, &p->work))
107 - zfcp_unit_put(unit);
110 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
112 struct zfcp_adapter *adapter = act->adapter;
113 @@ -1238,9 +1196,10 @@ static void zfcp_erp_action_cleanup(stru
114 if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
115 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
117 - if (!(atomic_read(&unit->status) &
118 - ZFCP_STATUS_UNIT_SCSI_WORK_PENDING))
119 - zfcp_erp_schedule_work(unit);
120 + zfcp_unit_get(unit);
121 + if (scsi_queue_work(unit->port->adapter->scsi_host,
122 + &unit->scsi_work) <= 0)
123 + zfcp_unit_put(unit);
127 --- a/drivers/s390/scsi/zfcp_scsi.c 2009-03-16 16:41:33.000000000 +0100
128 +++ b/drivers/s390/scsi/zfcp_scsi.c 2009-03-16 16:42:42.000000000 +0100
129 @@ -588,6 +588,20 @@ void zfcp_scsi_rport_work(struct work_st
133 +void zfcp_scsi_scan(struct work_struct *work)
135 + struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
137 + struct fc_rport *rport = unit->port->rport;
139 + if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
140 + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
141 + scsilun_to_int((struct scsi_lun *)
142 + &unit->fcp_lun), 0);
144 + zfcp_unit_put(unit);
147 struct fc_function_template zfcp_transport_functions = {
148 .show_starget_port_id = 1,
149 .show_starget_port_name = 1,
150 --- a/drivers/s390/scsi/zfcp_ext.h 2009-03-16 16:41:33.000000000 +0100
151 +++ b/drivers/s390/scsi/zfcp_ext.h 2009-03-16 16:42:42.000000000 +0100
152 @@ -159,6 +159,7 @@ extern void zfcp_scsi_rport_work(struct
153 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
154 extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
155 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
156 +extern void zfcp_scsi_scan(struct work_struct *);
159 extern struct attribute_group zfcp_sysfs_unit_attrs;