]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: zfcp: Move scan_target to scsi host workqueue | |
3 | References: bnc#484767,LTC#52236 | |
4 | ||
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 | |
12 | midlayer runs on. | |
13 | ||
14 | Acked-by: John Jolly <jjolly@suse.de> | |
15 | --- | |
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(-) | |
22 | ||
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); | |
27 | ||
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); | |
33 | ||
34 | down(&zfcp_data.config_sema); | |
35 | zfcp_unit_put(unit); | |
36 | @@ -288,6 +286,7 @@ struct zfcp_unit *zfcp_unit_enqueue(stru | |
37 | ||
38 | atomic_set(&unit->refcount, 0); | |
39 | init_waitqueue_head(&unit->remove_wq); | |
40 | + INIT_WORK(&unit->scsi_work, zfcp_scsi_scan); | |
41 | ||
42 | unit->port = port; | |
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 | |
51 | ||
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 */ | |
56 | atomic_t erp_counter; | |
57 | struct zfcp_latencies latencies; | |
58 | + struct work_struct scsi_work; | |
59 | }; | |
60 | ||
61 | /* FSF request */ | |
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 | |
65 | } | |
66 | } | |
67 | ||
68 | -struct zfcp_erp_add_work { | |
69 | - struct zfcp_unit *unit; | |
70 | - struct work_struct work; | |
71 | -}; | |
72 | - | |
73 | -static void zfcp_erp_scsi_scan(struct work_struct *work) | |
74 | -{ | |
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; | |
79 | - | |
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); | |
86 | - kfree(p); | |
87 | -} | |
88 | - | |
89 | -static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | |
90 | -{ | |
91 | - struct zfcp_erp_add_work *p; | |
92 | - | |
93 | - p = kzalloc(sizeof(*p), GFP_KERNEL); | |
94 | - if (!p) { | |
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); | |
99 | - return; | |
100 | - } | |
101 | - | |
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); | |
105 | - p->unit = unit; | |
106 | - if (!queue_work(zfcp_data.work_queue, &p->work)) | |
107 | - zfcp_unit_put(unit); | |
108 | -} | |
109 | - | |
110 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |
111 | { | |
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, | |
116 | &unit->status); | |
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); | |
124 | } | |
125 | zfcp_unit_put(unit); | |
126 | break; | |
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 | |
130 | } | |
131 | ||
132 | ||
133 | +void zfcp_scsi_scan(struct work_struct *work) | |
134 | +{ | |
135 | + struct zfcp_unit *unit = container_of(work, struct zfcp_unit, | |
136 | + scsi_work); | |
137 | + struct fc_rport *rport = unit->port->rport; | |
138 | + | |
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); | |
143 | + | |
144 | + zfcp_unit_put(unit); | |
145 | +} | |
146 | + | |
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 *); | |
157 | ||
158 | /* zfcp_sysfs.c */ | |
159 | extern struct attribute_group zfcp_sysfs_unit_attrs; |