]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/s390-10-05-zfcp_remote_port_handling.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / s390-10-05-zfcp_remote_port_handling.patch
CommitLineData
2cb7cef9
BS
1From: Gerald Schaefer <geraldsc@de.ibm.com>
2Subject: zfcp: Block remote ports (rports) early
3References: bnc#482818,LTC#51961
4
5Symptom: On path failover, the SCSI error recovery can set
6 SCSI devices offline.
7Problem: For path failover to work correctly, the FC rports
8 in the Linux kernel have to be in the state BLOCKED.
9 This prevents SCSI timeouts from triggering the SCSI
10 error recovery.
11Solution: On any problem (local link, remote port or any type
12 of error recovery) set the FC rports to BLOCKED early.
13
14Acked-by: John Jolly <jjolly@suse.de>
15---
16 drivers/s390/scsi/zfcp_aux.c | 2
17 drivers/s390/scsi/zfcp_dbf.c | 1
18 drivers/s390/scsi/zfcp_def.h | 2
19 drivers/s390/scsi/zfcp_erp.c | 48 ++---------------
20 drivers/s390/scsi/zfcp_ext.h | 4 +
21 drivers/s390/scsi/zfcp_fc.c | 20 ++++++-
22 drivers/s390/scsi/zfcp_fsf.c | 1
23 drivers/s390/scsi/zfcp_scsi.c | 117 +++++++++++++++++++++++++++++++++++++++++-
24 8 files changed, 149 insertions(+), 46 deletions(-)
25
26--- a/drivers/s390/scsi/zfcp_aux.c
27+++ b/drivers/s390/scsi/zfcp_aux.c
28@@ -612,10 +612,12 @@ struct zfcp_port *zfcp_port_enqueue(stru
29 INIT_LIST_HEAD(&port->unit_list_head);
30 INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
31 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
32+ INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
33
34 port->adapter = adapter;
35 port->d_id = d_id;
36 port->wwpn = wwpn;
37+ port->rport_task = RPORT_NONE;
38
39 /* mark port unusable as long as sysfs registration is not complete */
40 atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
41--- a/drivers/s390/scsi/zfcp_dbf.c
42+++ b/drivers/s390/scsi/zfcp_dbf.c
43@@ -644,6 +644,7 @@ static const char *zfcp_rec_dbf_ids[] =
44 [149] = "port scan",
45 [150] = "ptp attach",
46 [151] = "port validation failed",
47+ [152] = "term rport io",
48 };
49
50 static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
51--- a/drivers/s390/scsi/zfcp_def.h
52+++ b/drivers/s390/scsi/zfcp_def.h
53@@ -540,6 +540,8 @@ struct zfcp_port {
54 u32 supported_classes;
55 struct work_struct gid_pn_work;
56 struct work_struct test_link_work;
57+ struct work_struct rport_work;
58+ enum { RPORT_NONE, RPORT_ADD, RPORT_DEL } rport_task;
59 };
60
61 struct zfcp_unit {
62--- a/drivers/s390/scsi/zfcp_erp.c
63+++ b/drivers/s390/scsi/zfcp_erp.c
64@@ -239,6 +239,7 @@ static int _zfcp_erp_adapter_reopen(stru
65 int clear_mask, u8 id, void *ref)
66 {
67 zfcp_erp_adapter_block(adapter, clear_mask);
68+ zfcp_scsi_schedule_rports_block(adapter);
69
70 /* ensure propagation of failed status to new devices */
71 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
72@@ -319,6 +320,7 @@ static void _zfcp_erp_port_forced_reopen
73 int clear, u8 id, void *ref)
74 {
75 zfcp_erp_port_block(port, clear);
76+ zfcp_scsi_schedule_rport_block(port);
77
78 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
79 return;
80@@ -350,6 +352,7 @@ static int _zfcp_erp_port_reopen(struct
81 void *ref)
82 {
83 zfcp_erp_port_block(port, clear);
84+ zfcp_scsi_schedule_rport_block(port);
85
86 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
87 /* ensure propagation of failed status to new devices */
88@@ -1218,37 +1221,6 @@ static void zfcp_erp_schedule_work(struc
89 queue_work(zfcp_data.work_queue, &p->work);
90 }
91
92-static void zfcp_erp_rport_register(struct zfcp_port *port)
93-{
94- struct fc_rport_identifiers ids;
95- ids.node_name = port->wwnn;
96- ids.port_name = port->wwpn;
97- ids.port_id = port->d_id;
98- ids.roles = FC_RPORT_ROLE_FCP_TARGET;
99- port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
100- if (!port->rport) {
101- dev_err(&port->adapter->ccw_device->dev,
102- "Registering port 0x%016Lx failed\n",
103- (unsigned long long)port->wwpn);
104- return;
105- }
106-
107- scsi_target_unblock(&port->rport->dev);
108- port->rport->maxframe_size = port->maxframe_size;
109- port->rport->supported_classes = port->supported_classes;
110-}
111-
112-static void zfcp_erp_rports_del(struct zfcp_adapter *adapter)
113-{
114- struct zfcp_port *port;
115- list_for_each_entry(port, &adapter->port_list_head, list) {
116- if (!port->rport)
117- continue;
118- fc_remote_port_delete(port->rport);
119- port->rport = NULL;
120- }
121-}
122-
123 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
124 {
125 struct zfcp_adapter *adapter = act->adapter;
126@@ -1257,8 +1229,8 @@ static void zfcp_erp_action_cleanup(stru
127
128 switch (act->action) {
129 case ZFCP_ERP_ACTION_REOPEN_UNIT:
130- if ((result == ZFCP_ERP_SUCCEEDED) &&
131- !unit->device && port->rport) {
132+ flush_work(&port->rport_work);
133+ if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
134 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
135 &unit->status);
136 if (!(atomic_read(&unit->status) &
137@@ -1274,18 +1246,12 @@ static void zfcp_erp_action_cleanup(stru
138 zfcp_port_put(port);
139 return;
140 }
141- if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport)
142- zfcp_erp_rport_register(port);
143- if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
144- fc_remote_port_delete(port->rport);
145- port->rport = NULL;
146- }
147+ if (result == ZFCP_ERP_SUCCEEDED)
148+ zfcp_scsi_schedule_rport_register(port);
149 zfcp_port_put(port);
150 break;
151
152 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
153- if (result != ZFCP_ERP_SUCCEEDED)
154- zfcp_erp_rports_del(adapter);
155 zfcp_adapter_put(adapter);
156 break;
157 }
158--- a/drivers/s390/scsi/zfcp_ext.h
159+++ b/drivers/s390/scsi/zfcp_ext.h
160@@ -154,6 +154,10 @@ extern int zfcp_adapter_scsi_register(st
161 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
162 extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
163 extern struct fc_function_template zfcp_transport_functions;
164+extern void zfcp_scsi_rport_work(struct work_struct *);
165+extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
166+extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
167+extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
168
169 /* zfcp_sysfs.c */
170 extern struct attribute_group zfcp_sysfs_unit_attrs;
171--- a/drivers/s390/scsi/zfcp_fc.c
172+++ b/drivers/s390/scsi/zfcp_fc.c
173@@ -370,9 +370,14 @@ static void zfcp_fc_adisc_handler(unsign
174 port->wwnn = ls_adisc->wwnn;
175
176 if ((port->wwpn != ls_adisc->wwpn) ||
177- !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN))
178+ !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) {
179 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 64,
180 NULL);
181+ goto out;
182+ }
183+
184+ /* port is good, unblock rport without going through erp */
185+ zfcp_scsi_schedule_rport_register(port);
186
187 out:
188 zfcp_port_put(port);
189@@ -417,14 +422,23 @@ void zfcp_fc_link_test_work(struct work_
190 container_of(work, struct zfcp_port, test_link_work);
191 int retval;
192
193+ if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) {
194+ zfcp_port_put(port);
195+ return; /* port erp is running and will update rport status */
196+ }
197+
198+ zfcp_port_get(port);
199+ port->rport_task = RPORT_DEL;
200+ zfcp_scsi_rport_work(&port->rport_work);
201+
202 retval = zfcp_fc_adisc(port);
203 if (retval == 0)
204 return;
205
206 /* send of ADISC was not possible */
207+ zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
208+
209 zfcp_port_put(port);
210- if (retval != -EBUSY)
211- zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
212 }
213
214 /**
215--- a/drivers/s390/scsi/zfcp_fsf.c
216+++ b/drivers/s390/scsi/zfcp_fsf.c
217@@ -180,6 +180,7 @@ static void zfcp_fsf_link_down_info_eval
218 return;
219
220 atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
221+ zfcp_scsi_schedule_rports_block(adapter);
222
223 if (!link_down)
224 goto out;
225--- a/drivers/s390/scsi/zfcp_scsi.c
226+++ b/drivers/s390/scsi/zfcp_scsi.c
227@@ -57,8 +57,8 @@ static int zfcp_scsi_queuecommand(struct
228 {
229 struct zfcp_unit *unit;
230 struct zfcp_adapter *adapter;
231- int status;
232- int ret;
233+ int status, scsi_result, ret;
234+ struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
235
236 /* reset the status for this request */
237 scpnt->result = 0;
238@@ -80,6 +80,14 @@ static int zfcp_scsi_queuecommand(struct
239 return 0;
240 }
241
242+ scsi_result = fc_remote_port_chkready(rport);
243+ if (unlikely(scsi_result)) {
244+ scpnt->result = scsi_result;
245+ zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
246+ scpnt->scsi_done(scpnt);
247+ return 0;
248+ }
249+
250 status = atomic_read(&unit->status);
251 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
252 !(status & ZFCP_STATUS_COMMON_RUNNING))) {
253@@ -478,6 +486,109 @@ static void zfcp_set_rport_dev_loss_tmo(
254 rport->dev_loss_tmo = timeout;
255 }
256
257+/**
258+ * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
259+ * @rport: The rport that is about to be deleted.
260+ */
261+static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
262+{
263+ struct zfcp_port *port = rport->dd_data;
264+
265+ write_lock_irq(&zfcp_data.config_lock);
266+ port->rport = NULL;
267+ write_unlock_irq(&zfcp_data.config_lock);
268+}
269+
270+/**
271+ * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
272+ * @rport: The FC rport where to teminate I/O
273+ *
274+ * Abort all pending SCSI commands for a port by closing the
275+ * port. Using a reopen for avoids a conflict with a shutdown
276+ * overwriting a reopen.
277+ */
278+static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
279+{
280+ struct zfcp_port *port = rport->dd_data;
281+
282+ zfcp_erp_port_reopen(port, 0, 152, NULL);
283+}
284+
285+static void zfcp_scsi_rport_register(struct zfcp_port *port)
286+{
287+ struct fc_rport_identifiers ids;
288+ struct fc_rport *rport;
289+
290+ ids.node_name = port->wwnn;
291+ ids.port_name = port->wwpn;
292+ ids.port_id = port->d_id;
293+ ids.roles = FC_RPORT_ROLE_FCP_TARGET;
294+
295+ rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
296+ if (!rport) {
297+ dev_err(&port->adapter->ccw_device->dev,
298+ "Registering port 0x%016Lx failed\n",
299+ (unsigned long long)port->wwpn);
300+ return;
301+ }
302+
303+ rport->dd_data = port;
304+ rport->maxframe_size = port->maxframe_size;
305+ rport->supported_classes = port->supported_classes;
306+ port->rport = rport;
307+}
308+
309+static void zfcp_scsi_rport_block(struct zfcp_port *port)
310+{
311+ if (port->rport)
312+ fc_remote_port_delete(port->rport);
313+}
314+
315+void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
316+{
317+ zfcp_port_get(port);
318+ port->rport_task = RPORT_ADD;
319+
320+ if (!queue_work(zfcp_data.work_queue, &port->rport_work))
321+ zfcp_port_put(port);
322+}
323+
324+void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
325+{
326+ zfcp_port_get(port);
327+ port->rport_task = RPORT_DEL;
328+
329+ if (!queue_work(zfcp_data.work_queue, &port->rport_work))
330+ zfcp_port_put(port);
331+}
332+
333+void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
334+{
335+ struct zfcp_port *port;
336+
337+ list_for_each_entry(port, &adapter->port_list_head, list)
338+ zfcp_scsi_schedule_rport_block(port);
339+}
340+
341+void zfcp_scsi_rport_work(struct work_struct *work)
342+{
343+ struct zfcp_port *port = container_of(work, struct zfcp_port,
344+ rport_work);
345+
346+ while (port->rport_task) {
347+ if (port->rport_task == RPORT_ADD) {
348+ port->rport_task = RPORT_NONE;
349+ zfcp_scsi_rport_register(port);
350+ } else {
351+ port->rport_task = RPORT_NONE;
352+ zfcp_scsi_rport_block(port);
353+ }
354+ }
355+
356+ zfcp_port_put(port);
357+}
358+
359+
360 struct fc_function_template zfcp_transport_functions = {
361 .show_starget_port_id = 1,
362 .show_starget_port_name = 1,
363@@ -496,6 +607,8 @@ struct fc_function_template zfcp_transpo
364 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
365 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
366 .get_host_port_state = zfcp_get_host_port_state,
367+ .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
368+ .terminate_rport_io = zfcp_scsi_terminate_rport_io,
369 .show_host_port_state = 1,
370 /* no functions registered for following dynamic attributes but
371 directly set by LLDD */