blob: d9cd25b56cfae5223460ecdcabbdd269c442cce7 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Swen Schillig41fa2ada2007-09-07 09:15:31 +02002/*
Christof Schmitt553448f2008-06-10 18:20:58 +02003 * zfcp device driver
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Christof Schmitt553448f2008-06-10 18:20:58 +02005 * Error Recovery Procedures (ERP).
Swen Schillig41fa2ada2007-09-07 09:15:31 +02006 *
Steffen Maier6f2ce1c2016-12-09 17:16:33 +01007 * Copyright IBM Corp. 2002, 2016
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
Christof Schmittecf39d42008-12-25 13:39:53 +010010#define KMSG_COMPONENT "zfcp"
11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12
Christof Schmitt347c6a92009-08-18 15:43:25 +020013#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "zfcp_ext.h"
Christof Schmittb6bd2fb2010-02-17 11:18:50 +010015#include "zfcp_reqlist.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
Christof Schmitt287ac012008-07-02 10:56:40 +020017#define ZFCP_MAX_ERPS 3
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Christof Schmitt287ac012008-07-02 10:56:40 +020019enum zfcp_erp_act_flags {
20 ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000,
21 ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000,
22 ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
23 ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
24 ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
Christof Schmittfdbd1c52010-09-08 14:39:54 +020025 ZFCP_STATUS_ERP_NO_REF = 0x00800000,
Christof Schmitt287ac012008-07-02 10:56:40 +020026};
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Christof Schmitt287ac012008-07-02 10:56:40 +020028enum zfcp_erp_steps {
29 ZFCP_ERP_STEP_UNINITIALIZED = 0x0000,
30 ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
31 ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
32 ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
Christof Schmitt287ac012008-07-02 10:56:40 +020033 ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
Christof Schmittb62a8d92010-09-08 14:39:55 +020034 ZFCP_ERP_STEP_LUN_CLOSING = 0x1000,
35 ZFCP_ERP_STEP_LUN_OPENING = 0x2000,
Christof Schmitt287ac012008-07-02 10:56:40 +020036};
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Steffen Maier512857a72018-05-17 19:14:45 +020038/**
39 * enum zfcp_erp_act_type - Type of ERP action object.
40 * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery.
41 * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery.
42 * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery.
43 * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery.
44 * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with
45 * either of the other enum values.
46 * Used to indicate that an ERP action could not be
47 * set up despite a detected need for some recovery.
48 */
Christof Schmitt287ac012008-07-02 10:56:40 +020049enum zfcp_erp_act_type {
Christof Schmittb62a8d92010-09-08 14:39:55 +020050 ZFCP_ERP_ACTION_REOPEN_LUN = 1,
Christof Schmitt287ac012008-07-02 10:56:40 +020051 ZFCP_ERP_ACTION_REOPEN_PORT = 2,
52 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
53 ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4,
Steffen Maier512857a72018-05-17 19:14:45 +020054 ZFCP_ERP_ACTION_NONE = 0xc0,
Christof Schmitt287ac012008-07-02 10:56:40 +020055};
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Christof Schmitt287ac012008-07-02 10:56:40 +020057enum zfcp_erp_act_state {
58 ZFCP_ERP_ACTION_RUNNING = 1,
59 ZFCP_ERP_ACTION_READY = 2,
60};
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Christof Schmitt287ac012008-07-02 10:56:40 +020062enum zfcp_erp_act_result {
63 ZFCP_ERP_SUCCEEDED = 0,
64 ZFCP_ERP_FAILED = 1,
65 ZFCP_ERP_CONTINUES = 2,
66 ZFCP_ERP_EXIT = 3,
67 ZFCP_ERP_DISMISSED = 4,
68 ZFCP_ERP_NOMEM = 5,
69};
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Christof Schmitt287ac012008-07-02 10:56:40 +020071static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
Andreas Herrmann2abbe862006-09-18 22:29:56 +020072{
Swen Schilligedaed852010-09-08 14:40:01 +020073 zfcp_erp_clear_adapter_status(adapter,
74 ZFCP_STATUS_COMMON_UNBLOCKED | mask);
Andreas Herrmann2abbe862006-09-18 22:29:56 +020075}
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Christof Schmitt287ac012008-07-02 10:56:40 +020077static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
Christof Schmitt287ac012008-07-02 10:56:40 +020079 struct zfcp_erp_action *curr_act;
80
81 list_for_each_entry(curr_act, &act->adapter->erp_running_head, list)
82 if (act == curr_act)
83 return ZFCP_ERP_ACTION_RUNNING;
84 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085}
86
Christof Schmitt287ac012008-07-02 10:56:40 +020087static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088{
Christof Schmitt287ac012008-07-02 10:56:40 +020089 struct zfcp_adapter *adapter = act->adapter;
90
91 list_move(&act->list, &act->adapter->erp_ready_head);
Swen Schilligae0904f2010-12-02 15:16:12 +010092 zfcp_dbf_rec_run("erardy1", act);
Christof Schmitt347c6a92009-08-18 15:43:25 +020093 wake_up(&adapter->erp_ready_wq);
Swen Schilligae0904f2010-12-02 15:16:12 +010094 zfcp_dbf_rec_run("erardy2", act);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095}
96
Christof Schmitt287ac012008-07-02 10:56:40 +020097static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
Christof Schmitt287ac012008-07-02 10:56:40 +020099 act->status |= ZFCP_STATUS_ERP_DISMISSED;
100 if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING)
101 zfcp_erp_action_ready(act);
102}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Christof Schmittb62a8d92010-09-08 14:39:55 +0200104static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
Christof Schmitt287ac012008-07-02 10:56:40 +0200105{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200106 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
107
108 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
109 zfcp_erp_action_dismiss(&zfcp_sdev->erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +0200110}
111
112static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
113{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200114 struct scsi_device *sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +0200115
116 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
117 zfcp_erp_action_dismiss(&port->erp_action);
Martin Peschke924dd582013-08-22 17:45:37 +0200118 else {
119 spin_lock(port->adapter->scsi_host->host_lock);
120 __shost_for_each_device(sdev, port->adapter->scsi_host)
Christof Schmittb62a8d92010-09-08 14:39:55 +0200121 if (sdev_to_zfcp(sdev)->port == port)
122 zfcp_erp_action_dismiss_lun(sdev);
Martin Peschke924dd582013-08-22 17:45:37 +0200123 spin_unlock(port->adapter->scsi_host->host_lock);
124 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200125}
126
127static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
128{
129 struct zfcp_port *port;
130
131 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
132 zfcp_erp_action_dismiss(&adapter->erp_action);
Swen Schilligecf0c772009-11-24 16:53:58 +0100133 else {
134 read_lock(&adapter->port_list_lock);
135 list_for_each_entry(port, &adapter->port_list, list)
Christof Schmitt287ac012008-07-02 10:56:40 +0200136 zfcp_erp_action_dismiss_port(port);
Swen Schilligecf0c772009-11-24 16:53:58 +0100137 read_unlock(&adapter->port_list_lock);
138 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200139}
140
141static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
142 struct zfcp_port *port,
Christof Schmittb62a8d92010-09-08 14:39:55 +0200143 struct scsi_device *sdev)
Christof Schmitt287ac012008-07-02 10:56:40 +0200144{
145 int need = want;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200146 int l_status, p_status, a_status;
147 struct zfcp_scsi_dev *zfcp_sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +0200148
149 switch (want) {
Christof Schmittb62a8d92010-09-08 14:39:55 +0200150 case ZFCP_ERP_ACTION_REOPEN_LUN:
151 zfcp_sdev = sdev_to_zfcp(sdev);
152 l_status = atomic_read(&zfcp_sdev->status);
153 if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE)
Christof Schmitt287ac012008-07-02 10:56:40 +0200154 return 0;
155 p_status = atomic_read(&port->status);
156 if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
157 p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
158 return 0;
159 if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED))
160 need = ZFCP_ERP_ACTION_REOPEN_PORT;
161 /* fall through */
Christof Schmitt287ac012008-07-02 10:56:40 +0200162 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
163 p_status = atomic_read(&port->status);
Christof Schmitt097ef3b2010-07-08 09:53:06 +0200164 if (!(p_status & ZFCP_STATUS_COMMON_OPEN))
165 need = ZFCP_ERP_ACTION_REOPEN_PORT;
166 /* fall through */
167 case ZFCP_ERP_ACTION_REOPEN_PORT:
168 p_status = atomic_read(&port->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200169 if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE)
170 return 0;
171 a_status = atomic_read(&adapter->status);
172 if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
173 a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
174 return 0;
Swen Schilligd3e10882010-11-17 14:23:42 +0100175 if (p_status & ZFCP_STATUS_COMMON_NOESC)
176 return need;
Christof Schmitt287ac012008-07-02 10:56:40 +0200177 if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
178 need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
179 /* fall through */
180 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
181 a_status = atomic_read(&adapter->status);
182 if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
183 return 0;
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200184 if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
185 !(a_status & ZFCP_STATUS_COMMON_OPEN))
186 return 0; /* shutdown requested for closed adapter */
Christof Schmitt287ac012008-07-02 10:56:40 +0200187 }
188
189 return need;
190}
191
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200192static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
Christof Schmitt287ac012008-07-02 10:56:40 +0200193 struct zfcp_adapter *adapter,
194 struct zfcp_port *port,
Christof Schmittb62a8d92010-09-08 14:39:55 +0200195 struct scsi_device *sdev)
Christof Schmitt287ac012008-07-02 10:56:40 +0200196{
197 struct zfcp_erp_action *erp_action;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200198 struct zfcp_scsi_dev *zfcp_sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +0200199
200 switch (need) {
Christof Schmittb62a8d92010-09-08 14:39:55 +0200201 case ZFCP_ERP_ACTION_REOPEN_LUN:
202 zfcp_sdev = sdev_to_zfcp(sdev);
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200203 if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
Christof Schmittb62a8d92010-09-08 14:39:55 +0200204 if (scsi_device_get(sdev))
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200205 return NULL;
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200206 atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE,
Christof Schmittb62a8d92010-09-08 14:39:55 +0200207 &zfcp_sdev->status);
208 erp_action = &zfcp_sdev->erp_action;
Steffen Maierab31fd02017-10-13 15:40:07 +0200209 WARN_ON_ONCE(erp_action->port != port);
210 WARN_ON_ONCE(erp_action->sdev != sdev);
Christof Schmittb62a8d92010-09-08 14:39:55 +0200211 if (!(atomic_read(&zfcp_sdev->status) &
212 ZFCP_STATUS_COMMON_RUNNING))
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200213 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
Christof Schmitt287ac012008-07-02 10:56:40 +0200214 break;
215
216 case ZFCP_ERP_ACTION_REOPEN_PORT:
217 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
Christof Schmitt615f59e2010-02-17 11:18:56 +0100218 if (!get_device(&port->dev))
Swen Schillig6b1833342009-11-24 16:54:05 +0100219 return NULL;
Christof Schmitt287ac012008-07-02 10:56:40 +0200220 zfcp_erp_action_dismiss_port(port);
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200221 atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200222 erp_action = &port->erp_action;
Steffen Maierab31fd02017-10-13 15:40:07 +0200223 WARN_ON_ONCE(erp_action->port != port);
224 WARN_ON_ONCE(erp_action->sdev != NULL);
Christof Schmitt287ac012008-07-02 10:56:40 +0200225 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200226 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
Christof Schmitt287ac012008-07-02 10:56:40 +0200227 break;
228
229 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Swen Schilligf3450c72009-11-24 16:53:59 +0100230 kref_get(&adapter->ref);
Christof Schmitt287ac012008-07-02 10:56:40 +0200231 zfcp_erp_action_dismiss_adapter(adapter);
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200232 atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200233 erp_action = &adapter->erp_action;
Steffen Maierab31fd02017-10-13 15:40:07 +0200234 WARN_ON_ONCE(erp_action->port != NULL);
235 WARN_ON_ONCE(erp_action->sdev != NULL);
Christof Schmitt287ac012008-07-02 10:56:40 +0200236 if (!(atomic_read(&adapter->status) &
237 ZFCP_STATUS_COMMON_RUNNING))
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200238 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
Christof Schmitt287ac012008-07-02 10:56:40 +0200239 break;
240
241 default:
242 return NULL;
243 }
244
Steffen Maierab31fd02017-10-13 15:40:07 +0200245 WARN_ON_ONCE(erp_action->adapter != adapter);
246 memset(&erp_action->list, 0, sizeof(erp_action->list));
247 memset(&erp_action->timer, 0, sizeof(erp_action->timer));
248 erp_action->step = ZFCP_ERP_STEP_UNINITIALIZED;
249 erp_action->fsf_req_id = 0;
Christof Schmitt287ac012008-07-02 10:56:40 +0200250 erp_action->action = need;
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200251 erp_action->status = act_status;
Christof Schmitt287ac012008-07-02 10:56:40 +0200252
253 return erp_action;
254}
255
256static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
257 struct zfcp_port *port,
Christof Schmittb62a8d92010-09-08 14:39:55 +0200258 struct scsi_device *sdev,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100259 char *id, u32 act_status)
Christof Schmitt287ac012008-07-02 10:56:40 +0200260{
261 int retval = 1, need;
Swen Schilligae0904f2010-12-02 15:16:12 +0100262 struct zfcp_erp_action *act;
Christof Schmitt287ac012008-07-02 10:56:40 +0200263
Christof Schmitt347c6a92009-08-18 15:43:25 +0200264 if (!adapter->erp_thread)
Christof Schmitt287ac012008-07-02 10:56:40 +0200265 return -EIO;
266
Christof Schmittb62a8d92010-09-08 14:39:55 +0200267 need = zfcp_erp_required_act(want, adapter, port, sdev);
Christof Schmitt287ac012008-07-02 10:56:40 +0200268 if (!need)
269 goto out;
270
Christof Schmittb62a8d92010-09-08 14:39:55 +0200271 act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
Steffen Maier512857a72018-05-17 19:14:45 +0200272 if (!act) {
273 need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */
Christof Schmitt287ac012008-07-02 10:56:40 +0200274 goto out;
Steffen Maier512857a72018-05-17 19:14:45 +0200275 }
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200276 atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200277 ++adapter->erp_total_count;
278 list_add_tail(&act->list, &adapter->erp_ready_head);
Christof Schmitt347c6a92009-08-18 15:43:25 +0200279 wake_up(&adapter->erp_ready_wq);
Christof Schmitt287ac012008-07-02 10:56:40 +0200280 retval = 0;
281 out:
Swen Schilligae0904f2010-12-02 15:16:12 +0100282 zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need);
Christof Schmitt287ac012008-07-02 10:56:40 +0200283 return retval;
284}
285
286static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100287 int clear_mask, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200288{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 zfcp_erp_adapter_block(adapter, clear_mask);
Christof Schmitta2fa0ae2009-03-02 13:09:08 +0100290 zfcp_scsi_schedule_rports_block(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Christof Schmitt287ac012008-07-02 10:56:40 +0200292 /* ensure propagation of failed status to new devices */
293 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
Swen Schilligedaed852010-09-08 14:40:01 +0200294 zfcp_erp_set_adapter_status(adapter,
295 ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmitt287ac012008-07-02 10:56:40 +0200296 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200298 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100299 adapter, NULL, NULL, id, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200303 * zfcp_erp_adapter_reopen - Reopen adapter.
304 * @adapter: Adapter to reopen.
305 * @clear: Status flags to clear.
306 * @id: Id for debug trace event.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100308void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
Christof Schmitt287ac012008-07-02 10:56:40 +0200310 unsigned long flags;
311
Swen Schilligecf0c772009-11-24 16:53:58 +0100312 zfcp_erp_adapter_block(adapter, clear);
313 zfcp_scsi_schedule_rports_block(adapter);
314
315 write_lock_irqsave(&adapter->erp_lock, flags);
316 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
Swen Schilligedaed852010-09-08 14:40:01 +0200317 zfcp_erp_set_adapter_status(adapter,
318 ZFCP_STATUS_COMMON_ERP_FAILED);
Swen Schilligecf0c772009-11-24 16:53:58 +0100319 else
320 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100321 NULL, NULL, id, 0);
Swen Schilligecf0c772009-11-24 16:53:58 +0100322 write_unlock_irqrestore(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200323}
324
325/**
326 * zfcp_erp_adapter_shutdown - Shutdown adapter.
327 * @adapter: Adapter to shut down.
328 * @clear: Status flags to clear.
329 * @id: Id for debug trace event.
Christof Schmitt287ac012008-07-02 10:56:40 +0200330 */
331void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100332 char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200333{
334 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
Swen Schilligea4a3a62010-12-02 15:16:16 +0100335 zfcp_erp_adapter_reopen(adapter, clear | flags, id);
Christof Schmitt287ac012008-07-02 10:56:40 +0200336}
337
338/**
339 * zfcp_erp_port_shutdown - Shutdown port
340 * @port: Port to shut down.
341 * @clear: Status flags to clear.
342 * @id: Id for debug trace event.
Christof Schmitt287ac012008-07-02 10:56:40 +0200343 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100344void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200345{
346 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
Swen Schilligea4a3a62010-12-02 15:16:16 +0100347 zfcp_erp_port_reopen(port, clear | flags, id);
Christof Schmitt287ac012008-07-02 10:56:40 +0200348}
349
Christof Schmitt287ac012008-07-02 10:56:40 +0200350static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
351{
Swen Schilligedaed852010-09-08 14:40:01 +0200352 zfcp_erp_clear_port_status(port,
353 ZFCP_STATUS_COMMON_UNBLOCKED | clear);
Christof Schmitt287ac012008-07-02 10:56:40 +0200354}
355
Swen Schilligea4a3a62010-12-02 15:16:16 +0100356static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear,
357 char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200358{
359 zfcp_erp_port_block(port, clear);
Christof Schmitta2fa0ae2009-03-02 13:09:08 +0100360 zfcp_scsi_schedule_rport_block(port);
Christof Schmitt287ac012008-07-02 10:56:40 +0200361
362 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
363 return;
364
365 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100366 port->adapter, port, NULL, id, 0);
Christof Schmitt287ac012008-07-02 10:56:40 +0200367}
368
369/**
370 * zfcp_erp_port_forced_reopen - Forced close of port and open again
371 * @port: Port to force close and to reopen.
Swen Schilligea4a3a62010-12-02 15:16:16 +0100372 * @clear: Status flags to clear.
Christof Schmitt287ac012008-07-02 10:56:40 +0200373 * @id: Id for debug trace event.
Christof Schmitt287ac012008-07-02 10:56:40 +0200374 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100375void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200376{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 unsigned long flags;
378 struct zfcp_adapter *adapter = port->adapter;
379
Swen Schilligecf0c772009-11-24 16:53:58 +0100380 write_lock_irqsave(&adapter->erp_lock, flags);
Swen Schilligea4a3a62010-12-02 15:16:16 +0100381 _zfcp_erp_port_forced_reopen(port, clear, id);
Swen Schilligecf0c772009-11-24 16:53:58 +0100382 write_unlock_irqrestore(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200383}
384
Swen Schilligea4a3a62010-12-02 15:16:16 +0100385static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200386{
387 zfcp_erp_port_block(port, clear);
Christof Schmitta2fa0ae2009-03-02 13:09:08 +0100388 zfcp_scsi_schedule_rport_block(port);
Christof Schmitt287ac012008-07-02 10:56:40 +0200389
390 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
391 /* ensure propagation of failed status to new devices */
Swen Schilligedaed852010-09-08 14:40:01 +0200392 zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmitt287ac012008-07-02 10:56:40 +0200393 return -EIO;
394 }
395
396 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100397 port->adapter, port, NULL, id, 0);
Christof Schmitt287ac012008-07-02 10:56:40 +0200398}
399
400/**
401 * zfcp_erp_port_reopen - trigger remote port recovery
402 * @port: port to recover
403 * @clear_mask: flags in port status to be cleared
Swen Schilligea4a3a62010-12-02 15:16:16 +0100404 * @id: Id for debug trace event.
Christof Schmitt287ac012008-07-02 10:56:40 +0200405 *
406 * Returns 0 if recovery has been triggered, < 0 if not.
407 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100408int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200409{
Christof Schmitt287ac012008-07-02 10:56:40 +0200410 int retval;
Swen Schilligecf0c772009-11-24 16:53:58 +0100411 unsigned long flags;
Christof Schmitt287ac012008-07-02 10:56:40 +0200412 struct zfcp_adapter *adapter = port->adapter;
413
Swen Schilligecf0c772009-11-24 16:53:58 +0100414 write_lock_irqsave(&adapter->erp_lock, flags);
Swen Schilligea4a3a62010-12-02 15:16:16 +0100415 retval = _zfcp_erp_port_reopen(port, clear, id);
Swen Schilligecf0c772009-11-24 16:53:58 +0100416 write_unlock_irqrestore(&adapter->erp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 return retval;
419}
420
Christof Schmittb62a8d92010-09-08 14:39:55 +0200421static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
Swen Schilligedaed852010-09-08 14:40:01 +0200423 zfcp_erp_clear_lun_status(sdev,
424 ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask);
Christof Schmitt287ac012008-07-02 10:56:40 +0200425}
426
Christof Schmittb62a8d92010-09-08 14:39:55 +0200427static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100428 u32 act_status)
Christof Schmitt287ac012008-07-02 10:56:40 +0200429{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200430 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
431 struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Christof Schmittb62a8d92010-09-08 14:39:55 +0200433 zfcp_erp_lun_block(sdev, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Christof Schmittb62a8d92010-09-08 14:39:55 +0200435 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
Christof Schmitt287ac012008-07-02 10:56:40 +0200436 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Christof Schmittb62a8d92010-09-08 14:39:55 +0200438 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100439 zfcp_sdev->port, sdev, id, act_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440}
441
442/**
Christof Schmittb62a8d92010-09-08 14:39:55 +0200443 * zfcp_erp_lun_reopen - initiate reopen of a LUN
444 * @sdev: SCSI device / LUN to be reopened
445 * @clear_mask: specifies flags in LUN status to be cleared
Swen Schilligea4a3a62010-12-02 15:16:16 +0100446 * @id: Id for debug trace event.
447 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 * Return: 0 on success, < 0 on error
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100450void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 unsigned long flags;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200453 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
454 struct zfcp_port *port = zfcp_sdev->port;
Christof Schmitt287ac012008-07-02 10:56:40 +0200455 struct zfcp_adapter *adapter = port->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Swen Schilligecf0c772009-11-24 16:53:58 +0100457 write_lock_irqsave(&adapter->erp_lock, flags);
Swen Schilligea4a3a62010-12-02 15:16:16 +0100458 _zfcp_erp_lun_reopen(sdev, clear, id, 0);
Swen Schilligecf0c772009-11-24 16:53:58 +0100459 write_unlock_irqrestore(&adapter->erp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460}
461
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200462/**
Christof Schmittb62a8d92010-09-08 14:39:55 +0200463 * zfcp_erp_lun_shutdown - Shutdown LUN
464 * @sdev: SCSI device / LUN to shut down.
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200465 * @clear: Status flags to clear.
466 * @id: Id for debug trace event.
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200467 */
Swen Schilligea4a3a62010-12-02 15:16:16 +0100468void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id)
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200469{
470 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
Swen Schilligea4a3a62010-12-02 15:16:16 +0100471 zfcp_erp_lun_reopen(sdev, clear | flags, id);
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200472}
473
474/**
Christof Schmittb62a8d92010-09-08 14:39:55 +0200475 * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
476 * @sdev: SCSI device / LUN to shut down.
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200477 * @id: Id for debug trace event.
478 *
Christof Schmittb62a8d92010-09-08 14:39:55 +0200479 * Do not acquire a reference for the LUN when creating the ERP
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200480 * action. It is safe, because this function waits for the ERP to
Christof Schmittb62a8d92010-09-08 14:39:55 +0200481 * complete first. This allows to shutdown the LUN, even when the SCSI
482 * device is in the state SDEV_DEL when scsi_device_get will fail.
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200483 */
Christof Schmittb62a8d92010-09-08 14:39:55 +0200484void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200485{
486 unsigned long flags;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200487 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
488 struct zfcp_port *port = zfcp_sdev->port;
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200489 struct zfcp_adapter *adapter = port->adapter;
490 int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
491
492 write_lock_irqsave(&adapter->erp_lock, flags);
Swen Schilligea4a3a62010-12-02 15:16:16 +0100493 _zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF);
Christof Schmittfdbd1c52010-09-08 14:39:54 +0200494 write_unlock_irqrestore(&adapter->erp_lock, flags);
495
496 zfcp_erp_wait(adapter);
497}
498
Christof Schmitt287ac012008-07-02 10:56:40 +0200499static int status_change_set(unsigned long mask, atomic_t *status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Christof Schmitt287ac012008-07-02 10:56:40 +0200501 return (atomic_read(status) ^ mask) & mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200504static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
Christof Schmitt287ac012008-07-02 10:56:40 +0200506 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
Swen Schilligae0904f2010-12-02 15:16:12 +0100507 zfcp_dbf_rec_run("eraubl1", &adapter->erp_action);
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200508 atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509}
510
Christof Schmitt287ac012008-07-02 10:56:40 +0200511static void zfcp_erp_port_unblock(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
Christof Schmitt287ac012008-07-02 10:56:40 +0200513 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
Swen Schilligae0904f2010-12-02 15:16:12 +0100514 zfcp_dbf_rec_run("erpubl1", &port->erp_action);
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200515 atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516}
517
Christof Schmittb62a8d92010-09-08 14:39:55 +0200518static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200520 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
521
522 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
Swen Schilligae0904f2010-12-02 15:16:12 +0100523 zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action);
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200524 atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525}
526
Christof Schmitt287ac012008-07-02 10:56:40 +0200527static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528{
Christof Schmitt287ac012008-07-02 10:56:40 +0200529 list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
Swen Schilligae0904f2010-12-02 15:16:12 +0100530 zfcp_dbf_rec_run("erator1", erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531}
532
Christof Schmitt287ac012008-07-02 10:56:40 +0200533static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534{
Christof Schmitt287ac012008-07-02 10:56:40 +0200535 struct zfcp_adapter *adapter = act->adapter;
Christof Schmitte60a6d62010-02-17 11:18:49 +0100536 struct zfcp_fsf_req *req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Christof Schmitte60a6d62010-02-17 11:18:49 +0100538 if (!act->fsf_req_id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200539 return;
540
Christof Schmittb6bd2fb2010-02-17 11:18:50 +0100541 spin_lock(&adapter->req_list->lock);
542 req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id);
Christof Schmitte60a6d62010-02-17 11:18:49 +0100543 if (req && req->erp_action == act) {
Christof Schmitt287ac012008-07-02 10:56:40 +0200544 if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
545 ZFCP_STATUS_ERP_TIMEDOUT)) {
Christof Schmitte60a6d62010-02-17 11:18:49 +0100546 req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
Swen Schilligae0904f2010-12-02 15:16:12 +0100547 zfcp_dbf_rec_run("erscf_1", act);
Christof Schmitte60a6d62010-02-17 11:18:49 +0100548 req->erp_action = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200550 if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
Swen Schilligae0904f2010-12-02 15:16:12 +0100551 zfcp_dbf_rec_run("erscf_2", act);
Christof Schmitte60a6d62010-02-17 11:18:49 +0100552 if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
553 act->fsf_req_id = 0;
Christof Schmitt287ac012008-07-02 10:56:40 +0200554 } else
Christof Schmitte60a6d62010-02-17 11:18:49 +0100555 act->fsf_req_id = 0;
Christof Schmittb6bd2fb2010-02-17 11:18:50 +0100556 spin_unlock(&adapter->req_list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557}
558
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200559/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200560 * zfcp_erp_notify - Trigger ERP action.
561 * @erp_action: ERP action to continue.
562 * @set_mask: ERP action status flags to set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 */
Christof Schmitt287ac012008-07-02 10:56:40 +0200564void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 struct zfcp_adapter *adapter = erp_action->adapter;
567 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 write_lock_irqsave(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200570 if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
571 erp_action->status |= set_mask;
572 zfcp_erp_action_ready(erp_action);
573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 write_unlock_irqrestore(&adapter->erp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575}
576
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200577/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200578 * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
579 * @data: ERP action (from timer data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 */
Kees Cook75492a52017-10-16 16:44:34 -0700581void zfcp_erp_timeout_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
Kees Cook75492a52017-10-16 16:44:34 -0700583 struct zfcp_fsf_req *fsf_req = from_timer(fsf_req, t, timer);
584 struct zfcp_erp_action *act = fsf_req->erp_action;
Steffen Maier5c13db92017-10-17 18:40:51 +0200585
Christof Schmitt287ac012008-07-02 10:56:40 +0200586 zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587}
588
Kees Cook75492a52017-10-16 16:44:34 -0700589static void zfcp_erp_memwait_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
Kees Cook75492a52017-10-16 16:44:34 -0700591 struct zfcp_erp_action *act = from_timer(act, t, timer);
592
593 zfcp_erp_notify(act, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594}
595
Christof Schmitt287ac012008-07-02 10:56:40 +0200596static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597{
Steffen Maier5c13db92017-10-17 18:40:51 +0200598 timer_setup(&erp_action->timer, zfcp_erp_memwait_handler, 0);
Christof Schmitt287ac012008-07-02 10:56:40 +0200599 erp_action->timer.expires = jiffies + HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 add_timer(&erp_action->timer);
Christof Schmitt287ac012008-07-02 10:56:40 +0200601}
602
603static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100604 int clear, char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200605{
606 struct zfcp_port *port;
607
Swen Schilligecf0c772009-11-24 16:53:58 +0100608 read_lock(&adapter->port_list_lock);
609 list_for_each_entry(port, &adapter->port_list, list)
Swen Schilligea4a3a62010-12-02 15:16:16 +0100610 _zfcp_erp_port_reopen(port, clear, id);
Swen Schilligecf0c772009-11-24 16:53:58 +0100611 read_unlock(&adapter->port_list_lock);
Christof Schmitt287ac012008-07-02 10:56:40 +0200612}
613
Christof Schmittb62a8d92010-09-08 14:39:55 +0200614static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100615 char *id)
Christof Schmitt287ac012008-07-02 10:56:40 +0200616{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200617 struct scsi_device *sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +0200618
Martin Peschke924dd582013-08-22 17:45:37 +0200619 spin_lock(port->adapter->scsi_host->host_lock);
620 __shost_for_each_device(sdev, port->adapter->scsi_host)
Christof Schmittb62a8d92010-09-08 14:39:55 +0200621 if (sdev_to_zfcp(sdev)->port == port)
Swen Schilligea4a3a62010-12-02 15:16:16 +0100622 _zfcp_erp_lun_reopen(sdev, clear, id, 0);
Martin Peschke924dd582013-08-22 17:45:37 +0200623 spin_unlock(port->adapter->scsi_host->host_lock);
Christof Schmitt287ac012008-07-02 10:56:40 +0200624}
625
Christof Schmitt85600f72009-07-13 15:06:09 +0200626static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
Christof Schmitt287ac012008-07-02 10:56:40 +0200627{
Christof Schmitt287ac012008-07-02 10:56:40 +0200628 switch (act->action) {
Christof Schmitt287ac012008-07-02 10:56:40 +0200629 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100630 _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1");
Christof Schmitt287ac012008-07-02 10:56:40 +0200631 break;
Christof Schmitt287ac012008-07-02 10:56:40 +0200632 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100633 _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2");
Christof Schmitt287ac012008-07-02 10:56:40 +0200634 break;
Christof Schmitt287ac012008-07-02 10:56:40 +0200635 case ZFCP_ERP_ACTION_REOPEN_PORT:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100636 _zfcp_erp_port_reopen(act->port, 0, "ersff_3");
Christof Schmitt287ac012008-07-02 10:56:40 +0200637 break;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200638 case ZFCP_ERP_ACTION_REOPEN_LUN:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100639 _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0);
Christof Schmitt85600f72009-07-13 15:06:09 +0200640 break;
641 }
642}
643
644static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
645{
646 switch (act->action) {
647 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100648 _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1");
Christof Schmitt85600f72009-07-13 15:06:09 +0200649 break;
650 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100651 _zfcp_erp_port_reopen(act->port, 0, "ersfs_2");
Christof Schmitt85600f72009-07-13 15:06:09 +0200652 break;
653 case ZFCP_ERP_ACTION_REOPEN_PORT:
Swen Schilligea4a3a62010-12-02 15:16:16 +0100654 _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3");
Christof Schmitt287ac012008-07-02 10:56:40 +0200655 break;
656 }
657}
658
659static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
660{
661 unsigned long flags;
662
Swen Schilligecf0c772009-11-24 16:53:58 +0100663 read_lock_irqsave(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200664 if (list_empty(&adapter->erp_ready_head) &&
665 list_empty(&adapter->erp_running_head)) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200666 atomic_andnot(ZFCP_STATUS_ADAPTER_ERP_PENDING,
Christof Schmitt287ac012008-07-02 10:56:40 +0200667 &adapter->status);
668 wake_up(&adapter->erp_done_wqh);
669 }
Swen Schilligecf0c772009-11-24 16:53:58 +0100670 read_unlock_irqrestore(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200671}
672
Christof Schmitt287ac012008-07-02 10:56:40 +0200673static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter)
674{
675 struct zfcp_port *port;
676 port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0,
677 adapter->peer_d_id);
678 if (IS_ERR(port)) /* error or port already attached */
679 return;
Swen Schilligea4a3a62010-12-02 15:16:16 +0100680 _zfcp_erp_port_reopen(port, 0, "ereptp1");
Christof Schmitt287ac012008-07-02 10:56:40 +0200681}
682
683static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
684{
685 int retries;
686 int sleep = 1;
687 struct zfcp_adapter *adapter = erp_action->adapter;
688
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200689 atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200690
691 for (retries = 7; retries; retries--) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200692 atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
Christof Schmitt287ac012008-07-02 10:56:40 +0200693 &adapter->status);
694 write_lock_irq(&adapter->erp_lock);
695 zfcp_erp_action_to_running(erp_action);
696 write_unlock_irq(&adapter->erp_lock);
697 if (zfcp_fsf_exchange_config_data(erp_action)) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200698 atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
Christof Schmitt287ac012008-07-02 10:56:40 +0200699 &adapter->status);
700 return ZFCP_ERP_FAILED;
701 }
702
Christof Schmitt347c6a92009-08-18 15:43:25 +0200703 wait_event(adapter->erp_ready_wq,
704 !list_empty(&adapter->erp_ready_head));
Christof Schmitt287ac012008-07-02 10:56:40 +0200705 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
706 break;
707
708 if (!(atomic_read(&adapter->status) &
709 ZFCP_STATUS_ADAPTER_HOST_CON_INIT))
710 break;
711
712 ssleep(sleep);
713 sleep *= 2;
714 }
715
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200716 atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
Christof Schmitt287ac012008-07-02 10:56:40 +0200717 &adapter->status);
718
719 if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
720 return ZFCP_ERP_FAILED;
721
722 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
723 zfcp_erp_enqueue_ptp_port(adapter);
724
725 return ZFCP_ERP_SUCCEEDED;
726}
727
728static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
729{
730 int ret;
731 struct zfcp_adapter *adapter = act->adapter;
732
Christof Schmitt287ac012008-07-02 10:56:40 +0200733 write_lock_irq(&adapter->erp_lock);
734 zfcp_erp_action_to_running(act);
735 write_unlock_irq(&adapter->erp_lock);
736
737 ret = zfcp_fsf_exchange_port_data(act);
738 if (ret == -EOPNOTSUPP)
739 return ZFCP_ERP_SUCCEEDED;
740 if (ret)
741 return ZFCP_ERP_FAILED;
742
Swen Schilligae0904f2010-12-02 15:16:12 +0100743 zfcp_dbf_rec_run("erasox1", act);
Christof Schmitt347c6a92009-08-18 15:43:25 +0200744 wait_event(adapter->erp_ready_wq,
745 !list_empty(&adapter->erp_ready_head));
Swen Schilligae0904f2010-12-02 15:16:12 +0100746 zfcp_dbf_rec_run("erasox2", act);
Christof Schmitt287ac012008-07-02 10:56:40 +0200747 if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
748 return ZFCP_ERP_FAILED;
749
750 return ZFCP_ERP_SUCCEEDED;
751}
752
753static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
754{
755 if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED)
756 return ZFCP_ERP_FAILED;
757
758 if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
759 return ZFCP_ERP_FAILED;
760
Christof Schmittc7b279a2011-02-22 19:54:40 +0100761 if (mempool_resize(act->adapter->pool.sr_data,
David Rientjes11d83362015-04-14 15:48:21 -0700762 act->adapter->stat_read_buf_num))
Christof Schmitt8d88cf32010-06-21 10:11:33 +0200763 return ZFCP_ERP_FAILED;
764
765 if (mempool_resize(act->adapter->pool.status_read_req,
David Rientjes11d83362015-04-14 15:48:21 -0700766 act->adapter->stat_read_buf_num))
Christof Schmitt8d88cf32010-06-21 10:11:33 +0200767 return ZFCP_ERP_FAILED;
768
Christof Schmitt64deb6e2010-04-30 18:09:36 +0200769 atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
Christof Schmitt287ac012008-07-02 10:56:40 +0200770 if (zfcp_status_read_refill(act->adapter))
771 return ZFCP_ERP_FAILED;
772
773 return ZFCP_ERP_SUCCEEDED;
774}
775
Swen Schilligcf13c082009-03-02 13:09:03 +0100776static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
Christof Schmitt287ac012008-07-02 10:56:40 +0200777{
Christof Schmitt287ac012008-07-02 10:56:40 +0200778 struct zfcp_adapter *adapter = act->adapter;
779
Christof Schmitt287ac012008-07-02 10:56:40 +0200780 /* close queues to ensure that buffers are not accessed by adapter */
Swen Schillig564e1c82009-08-18 15:43:19 +0200781 zfcp_qdio_close(adapter->qdio);
Christof Schmitt287ac012008-07-02 10:56:40 +0200782 zfcp_fsf_req_dismiss_all(adapter);
783 adapter->fsf_req_seq_no = 0;
Christof Schmitt55c770f2009-08-18 15:43:12 +0200784 zfcp_fc_wka_ports_force_offline(adapter->gs);
Christof Schmittb62a8d92010-09-08 14:39:55 +0200785 /* all ports and LUNs are closed */
Swen Schilligedaed852010-09-08 14:40:01 +0200786 zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
Swen Schilligcf13c082009-03-02 13:09:03 +0100787
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200788 atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
Swen Schilligcf13c082009-03-02 13:09:03 +0100789 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
790}
791
792static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act)
793{
794 struct zfcp_adapter *adapter = act->adapter;
795
Christof Schmitt3d63d3b2010-12-02 15:16:17 +0100796 if (zfcp_qdio_open(adapter->qdio)) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200797 atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
Swen Schilligcf13c082009-03-02 13:09:03 +0100798 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
799 &adapter->status);
800 return ZFCP_ERP_FAILED;
801 }
802
803 if (zfcp_erp_adapter_strategy_open_fsf(act)) {
804 zfcp_erp_adapter_strategy_close(act);
805 return ZFCP_ERP_FAILED;
806 }
807
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200808 atomic_or(ZFCP_STATUS_COMMON_OPEN, &adapter->status);
Swen Schilligcf13c082009-03-02 13:09:03 +0100809
810 return ZFCP_ERP_SUCCEEDED;
Christof Schmitt287ac012008-07-02 10:56:40 +0200811}
812
813static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
814{
Swen Schilligcf13c082009-03-02 13:09:03 +0100815 struct zfcp_adapter *adapter = act->adapter;
Christof Schmitt287ac012008-07-02 10:56:40 +0200816
Swen Schilligcf13c082009-03-02 13:09:03 +0100817 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN) {
818 zfcp_erp_adapter_strategy_close(act);
819 if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
820 return ZFCP_ERP_EXIT;
821 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200822
Swen Schilligcf13c082009-03-02 13:09:03 +0100823 if (zfcp_erp_adapter_strategy_open(act)) {
Christof Schmitt287ac012008-07-02 10:56:40 +0200824 ssleep(8);
Swen Schilligcf13c082009-03-02 13:09:03 +0100825 return ZFCP_ERP_FAILED;
826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Swen Schilligcf13c082009-03-02 13:09:03 +0100828 return ZFCP_ERP_SUCCEEDED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829}
830
Christof Schmitt287ac012008-07-02 10:56:40 +0200831static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832{
Christof Schmitt287ac012008-07-02 10:56:40 +0200833 int retval;
834
835 retval = zfcp_fsf_close_physical_port(act);
836 if (retval == -ENOMEM)
837 return ZFCP_ERP_NOMEM;
838 act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
839 if (retval)
840 return ZFCP_ERP_FAILED;
841
842 return ZFCP_ERP_CONTINUES;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Christof Schmitt287ac012008-07-02 10:56:40 +0200845static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
846{
847 struct zfcp_port *port = erp_action->port;
848 int status = atomic_read(&port->status);
849
850 switch (erp_action->step) {
851 case ZFCP_ERP_STEP_UNINITIALIZED:
Christof Schmitt287ac012008-07-02 10:56:40 +0200852 if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
853 (status & ZFCP_STATUS_COMMON_OPEN))
854 return zfcp_erp_port_forced_strategy_close(erp_action);
855 else
856 return ZFCP_ERP_FAILED;
857
858 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
Christof Schmittddb3e0c2009-07-13 15:06:08 +0200859 if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
Christof Schmitt287ac012008-07-02 10:56:40 +0200860 return ZFCP_ERP_SUCCEEDED;
861 }
862 return ZFCP_ERP_FAILED;
863}
864
865static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
866{
867 int retval;
868
869 retval = zfcp_fsf_close_port(erp_action);
870 if (retval == -ENOMEM)
871 return ZFCP_ERP_NOMEM;
872 erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
873 if (retval)
874 return ZFCP_ERP_FAILED;
875 return ZFCP_ERP_CONTINUES;
876}
877
878static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
879{
880 int retval;
881
882 retval = zfcp_fsf_open_port(erp_action);
883 if (retval == -ENOMEM)
884 return ZFCP_ERP_NOMEM;
885 erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
886 if (retval)
887 return ZFCP_ERP_FAILED;
888 return ZFCP_ERP_CONTINUES;
889}
890
Christof Schmitt287ac012008-07-02 10:56:40 +0200891static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
892{
893 struct zfcp_adapter *adapter = act->adapter;
894 struct zfcp_port *port = act->port;
895
896 if (port->wwpn != adapter->peer_wwpn) {
Swen Schilligedaed852010-09-08 14:40:01 +0200897 zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmitt287ac012008-07-02 10:56:40 +0200898 return ZFCP_ERP_FAILED;
899 }
900 port->d_id = adapter->peer_d_id;
Christof Schmitt287ac012008-07-02 10:56:40 +0200901 return zfcp_erp_port_strategy_open_port(act);
902}
903
904static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
905{
906 struct zfcp_adapter *adapter = act->adapter;
907 struct zfcp_port *port = act->port;
Christof Schmitt287ac012008-07-02 10:56:40 +0200908 int p_status = atomic_read(&port->status);
909
910 switch (act->step) {
911 case ZFCP_ERP_STEP_UNINITIALIZED:
912 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
913 case ZFCP_ERP_STEP_PORT_CLOSING:
914 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
915 return zfcp_erp_open_ptp_port(act);
Christof Schmittb98478d2008-12-19 16:56:59 +0100916 if (!port->d_id) {
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200917 zfcp_fc_trigger_did_lookup(port);
Christof Schmitt799b76d2009-08-18 15:43:20 +0200918 return ZFCP_ERP_EXIT;
Christof Schmitt287ac012008-07-02 10:56:40 +0200919 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200920 return zfcp_erp_port_strategy_open_port(act);
921
922 case ZFCP_ERP_STEP_PORT_OPENING:
923 /* D_ID might have changed during open */
Swen Schillig5ab944f2008-10-01 12:42:17 +0200924 if (p_status & ZFCP_STATUS_COMMON_OPEN) {
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200925 if (!port->d_id) {
926 zfcp_fc_trigger_did_lookup(port);
927 return ZFCP_ERP_EXIT;
Swen Schillig5ab944f2008-10-01 12:42:17 +0200928 }
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200929 return ZFCP_ERP_SUCCEEDED;
Swen Schillig5ab944f2008-10-01 12:42:17 +0200930 }
Swen Schilligea460a82009-05-15 13:18:20 +0200931 if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
932 port->d_id = 0;
Christof Schmittf7bd7c32010-07-08 09:53:10 +0200933 return ZFCP_ERP_FAILED;
Swen Schilligea460a82009-05-15 13:18:20 +0200934 }
935 /* fall through otherwise */
Christof Schmitt287ac012008-07-02 10:56:40 +0200936 }
937 return ZFCP_ERP_FAILED;
938}
939
Christof Schmitt287ac012008-07-02 10:56:40 +0200940static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
941{
942 struct zfcp_port *port = erp_action->port;
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200943 int p_status = atomic_read(&port->status);
Christof Schmitt287ac012008-07-02 10:56:40 +0200944
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200945 if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
946 !(p_status & ZFCP_STATUS_COMMON_OPEN))
Swen Schillig5ab944f2008-10-01 12:42:17 +0200947 goto close_init_done;
948
Christof Schmitt287ac012008-07-02 10:56:40 +0200949 switch (erp_action->step) {
950 case ZFCP_ERP_STEP_UNINITIALIZED:
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200951 if (p_status & ZFCP_STATUS_COMMON_OPEN)
Christof Schmitt287ac012008-07-02 10:56:40 +0200952 return zfcp_erp_port_strategy_close(erp_action);
953 break;
954
955 case ZFCP_ERP_STEP_PORT_CLOSING:
Christof Schmitt934aeb5872009-10-14 11:00:43 +0200956 if (p_status & ZFCP_STATUS_COMMON_OPEN)
Christof Schmitt287ac012008-07-02 10:56:40 +0200957 return ZFCP_ERP_FAILED;
958 break;
959 }
Swen Schillig5ab944f2008-10-01 12:42:17 +0200960
961close_init_done:
Christof Schmitt287ac012008-07-02 10:56:40 +0200962 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
963 return ZFCP_ERP_EXIT;
Christof Schmitt287ac012008-07-02 10:56:40 +0200964
Swen Schillig5ab944f2008-10-01 12:42:17 +0200965 return zfcp_erp_port_strategy_open_common(erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966}
967
Christof Schmittb62a8d92010-09-08 14:39:55 +0200968static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200970 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
971
Peter Zijlstra805de8f42015-04-24 01:12:32 +0200972 atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED,
Christof Schmittb62a8d92010-09-08 14:39:55 +0200973 &zfcp_sdev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974}
975
Christof Schmittb62a8d92010-09-08 14:39:55 +0200976static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
Christof Schmitt287ac012008-07-02 10:56:40 +0200977{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200978 int retval = zfcp_fsf_close_lun(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +0200979 if (retval == -ENOMEM)
980 return ZFCP_ERP_NOMEM;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200981 erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
Christof Schmitt287ac012008-07-02 10:56:40 +0200982 if (retval)
983 return ZFCP_ERP_FAILED;
984 return ZFCP_ERP_CONTINUES;
985}
986
Christof Schmittb62a8d92010-09-08 14:39:55 +0200987static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
Christof Schmitt287ac012008-07-02 10:56:40 +0200988{
Christof Schmittb62a8d92010-09-08 14:39:55 +0200989 int retval = zfcp_fsf_open_lun(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +0200990 if (retval == -ENOMEM)
991 return ZFCP_ERP_NOMEM;
Christof Schmittb62a8d92010-09-08 14:39:55 +0200992 erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
Christof Schmitt287ac012008-07-02 10:56:40 +0200993 if (retval)
994 return ZFCP_ERP_FAILED;
995 return ZFCP_ERP_CONTINUES;
996}
997
Christof Schmittb62a8d92010-09-08 14:39:55 +0200998static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
Christof Schmitt287ac012008-07-02 10:56:40 +0200999{
Christof Schmittb62a8d92010-09-08 14:39:55 +02001000 struct scsi_device *sdev = erp_action->sdev;
1001 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
Christof Schmitt287ac012008-07-02 10:56:40 +02001002
1003 switch (erp_action->step) {
1004 case ZFCP_ERP_STEP_UNINITIALIZED:
Christof Schmittb62a8d92010-09-08 14:39:55 +02001005 zfcp_erp_lun_strategy_clearstati(sdev);
1006 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
1007 return zfcp_erp_lun_strategy_close(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +02001008 /* already closed, fall through */
Christof Schmittb62a8d92010-09-08 14:39:55 +02001009 case ZFCP_ERP_STEP_LUN_CLOSING:
1010 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
Christof Schmitt287ac012008-07-02 10:56:40 +02001011 return ZFCP_ERP_FAILED;
1012 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
1013 return ZFCP_ERP_EXIT;
Christof Schmittb62a8d92010-09-08 14:39:55 +02001014 return zfcp_erp_lun_strategy_open(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +02001015
Christof Schmittb62a8d92010-09-08 14:39:55 +02001016 case ZFCP_ERP_STEP_LUN_OPENING:
1017 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
Christof Schmitt287ac012008-07-02 10:56:40 +02001018 return ZFCP_ERP_SUCCEEDED;
1019 }
1020 return ZFCP_ERP_FAILED;
1021}
1022
Christof Schmittb62a8d92010-09-08 14:39:55 +02001023static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
Christof Schmitt287ac012008-07-02 10:56:40 +02001024{
Christof Schmittb62a8d92010-09-08 14:39:55 +02001025 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1026
Christof Schmitt287ac012008-07-02 10:56:40 +02001027 switch (result) {
1028 case ZFCP_ERP_SUCCEEDED :
Christof Schmittb62a8d92010-09-08 14:39:55 +02001029 atomic_set(&zfcp_sdev->erp_counter, 0);
1030 zfcp_erp_lun_unblock(sdev);
Christof Schmitt287ac012008-07-02 10:56:40 +02001031 break;
1032 case ZFCP_ERP_FAILED :
Christof Schmittb62a8d92010-09-08 14:39:55 +02001033 atomic_inc(&zfcp_sdev->erp_counter);
1034 if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) {
1035 dev_err(&zfcp_sdev->port->adapter->ccw_device->dev,
1036 "ERP failed for LUN 0x%016Lx on "
Christof Schmittff3b24f2008-10-01 12:42:15 +02001037 "port 0x%016Lx\n",
Christof Schmittb62a8d92010-09-08 14:39:55 +02001038 (unsigned long long)zfcp_scsi_dev_lun(sdev),
1039 (unsigned long long)zfcp_sdev->port->wwpn);
Swen Schilligedaed852010-09-08 14:40:01 +02001040 zfcp_erp_set_lun_status(sdev,
1041 ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001042 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001043 break;
1044 }
1045
Christof Schmittb62a8d92010-09-08 14:39:55 +02001046 if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1047 zfcp_erp_lun_block(sdev, 0);
Christof Schmitt287ac012008-07-02 10:56:40 +02001048 result = ZFCP_ERP_EXIT;
1049 }
1050 return result;
1051}
1052
1053static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
1054{
1055 switch (result) {
1056 case ZFCP_ERP_SUCCEEDED :
1057 atomic_set(&port->erp_counter, 0);
1058 zfcp_erp_port_unblock(port);
1059 break;
1060
1061 case ZFCP_ERP_FAILED :
1062 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
1063 zfcp_erp_port_block(port, 0);
1064 result = ZFCP_ERP_EXIT;
1065 }
1066 atomic_inc(&port->erp_counter);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001067 if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
1068 dev_err(&port->adapter->ccw_device->dev,
1069 "ERP failed for remote port 0x%016Lx\n",
Swen Schillig7ba58c92008-10-01 12:42:18 +02001070 (unsigned long long)port->wwpn);
Swen Schilligedaed852010-09-08 14:40:01 +02001071 zfcp_erp_set_port_status(port,
1072 ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001073 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001074 break;
1075 }
1076
1077 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1078 zfcp_erp_port_block(port, 0);
1079 result = ZFCP_ERP_EXIT;
1080 }
1081 return result;
1082}
1083
1084static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
1085 int result)
1086{
1087 switch (result) {
1088 case ZFCP_ERP_SUCCEEDED :
1089 atomic_set(&adapter->erp_counter, 0);
1090 zfcp_erp_adapter_unblock(adapter);
1091 break;
1092
1093 case ZFCP_ERP_FAILED :
1094 atomic_inc(&adapter->erp_counter);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001095 if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
1096 dev_err(&adapter->ccw_device->dev,
1097 "ERP cannot recover an error "
1098 "on the FCP device\n");
Swen Schilligedaed852010-09-08 14:40:01 +02001099 zfcp_erp_set_adapter_status(adapter,
1100 ZFCP_STATUS_COMMON_ERP_FAILED);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001101 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001102 break;
1103 }
1104
1105 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1106 zfcp_erp_adapter_block(adapter, 0);
1107 result = ZFCP_ERP_EXIT;
1108 }
1109 return result;
1110}
1111
1112static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
1113 int result)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
1115 struct zfcp_adapter *adapter = erp_action->adapter;
1116 struct zfcp_port *port = erp_action->port;
Christof Schmittb62a8d92010-09-08 14:39:55 +02001117 struct scsi_device *sdev = erp_action->sdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 switch (erp_action->action) {
1120
Christof Schmittb62a8d92010-09-08 14:39:55 +02001121 case ZFCP_ERP_ACTION_REOPEN_LUN:
1122 result = zfcp_erp_strategy_check_lun(sdev, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 break;
1124
1125 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1126 case ZFCP_ERP_ACTION_REOPEN_PORT:
1127 result = zfcp_erp_strategy_check_port(port, result);
1128 break;
1129
1130 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1131 result = zfcp_erp_strategy_check_adapter(adapter, result);
1132 break;
1133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return result;
1135}
1136
Christof Schmitt287ac012008-07-02 10:56:40 +02001137static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138{
Christof Schmitt287ac012008-07-02 10:56:40 +02001139 int status = atomic_read(target_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Christof Schmitt287ac012008-07-02 10:56:40 +02001141 if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
1142 (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1143 return 1; /* take it online */
1144
1145 if (!(status & ZFCP_STATUS_COMMON_RUNNING) &&
1146 !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1147 return 1; /* take it offline */
1148
1149 return 0;
1150}
1151
1152static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
1153{
1154 int action = act->action;
1155 struct zfcp_adapter *adapter = act->adapter;
1156 struct zfcp_port *port = act->port;
Christof Schmittb62a8d92010-09-08 14:39:55 +02001157 struct scsi_device *sdev = act->sdev;
1158 struct zfcp_scsi_dev *zfcp_sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +02001159 u32 erp_status = act->status;
1160
1161 switch (action) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Christof Schmitt287ac012008-07-02 10:56:40 +02001163 if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
1164 _zfcp_erp_adapter_reopen(adapter,
1165 ZFCP_STATUS_COMMON_ERP_FAILED,
Swen Schilligea4a3a62010-12-02 15:16:16 +01001166 "ersscg1");
Christof Schmitt287ac012008-07-02 10:56:40 +02001167 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 }
1169 break;
1170
1171 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1172 case ZFCP_ERP_ACTION_REOPEN_PORT:
Christof Schmitt287ac012008-07-02 10:56:40 +02001173 if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
1174 _zfcp_erp_port_reopen(port,
1175 ZFCP_STATUS_COMMON_ERP_FAILED,
Swen Schilligea4a3a62010-12-02 15:16:16 +01001176 "ersscg2");
Christof Schmitt287ac012008-07-02 10:56:40 +02001177 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179 break;
1180
Christof Schmittb62a8d92010-09-08 14:39:55 +02001181 case ZFCP_ERP_ACTION_REOPEN_LUN:
1182 zfcp_sdev = sdev_to_zfcp(sdev);
1183 if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
1184 _zfcp_erp_lun_reopen(sdev,
1185 ZFCP_STATUS_COMMON_ERP_FAILED,
Swen Schilligea4a3a62010-12-02 15:16:16 +01001186 "ersscg3", 0);
Christof Schmitt287ac012008-07-02 10:56:40 +02001187 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189 break;
1190 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001191 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192}
1193
Christof Schmitt287ac012008-07-02 10:56:40 +02001194static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
Christof Schmitt287ac012008-07-02 10:56:40 +02001196 struct zfcp_adapter *adapter = erp_action->adapter;
Christof Schmittb62a8d92010-09-08 14:39:55 +02001197 struct zfcp_scsi_dev *zfcp_sdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Christof Schmitt287ac012008-07-02 10:56:40 +02001199 adapter->erp_total_count--;
1200 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1201 adapter->erp_low_mem_count--;
1202 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 }
1204
Christof Schmitt287ac012008-07-02 10:56:40 +02001205 list_del(&erp_action->list);
Swen Schilligae0904f2010-12-02 15:16:12 +01001206 zfcp_dbf_rec_run("eractd1", erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Christof Schmitt287ac012008-07-02 10:56:40 +02001208 switch (erp_action->action) {
Christof Schmittb62a8d92010-09-08 14:39:55 +02001209 case ZFCP_ERP_ACTION_REOPEN_LUN:
1210 zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001211 atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
Christof Schmittb62a8d92010-09-08 14:39:55 +02001212 &zfcp_sdev->status);
Christof Schmitt287ac012008-07-02 10:56:40 +02001213 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Christof Schmitt287ac012008-07-02 10:56:40 +02001215 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1216 case ZFCP_ERP_ACTION_REOPEN_PORT:
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001217 atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
Christof Schmitt287ac012008-07-02 10:56:40 +02001218 &erp_action->port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001220
1221 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001222 atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
Christof Schmitt287ac012008-07-02 10:56:40 +02001223 &erp_action->adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 break;
1225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
Steffen Maier6f2ce1c2016-12-09 17:16:33 +01001228/**
1229 * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery
1230 * @port: zfcp_port whose fc_rport we should try to unblock
1231 */
1232static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
1233{
1234 unsigned long flags;
1235 struct zfcp_adapter *adapter = port->adapter;
1236 int port_status;
1237 struct Scsi_Host *shost = adapter->scsi_host;
1238 struct scsi_device *sdev;
1239
1240 write_lock_irqsave(&adapter->erp_lock, flags);
1241 port_status = atomic_read(&port->status);
1242 if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
1243 (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
1244 ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) {
1245 /* new ERP of severity >= port triggered elsewhere meanwhile or
1246 * local link down (adapter erp_failed but not clear unblock)
1247 */
1248 zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
1249 write_unlock_irqrestore(&adapter->erp_lock, flags);
1250 return;
1251 }
1252 spin_lock(shost->host_lock);
1253 __shost_for_each_device(sdev, shost) {
1254 struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
1255 int lun_status;
1256
1257 if (zsdev->port != port)
1258 continue;
1259 /* LUN under port of interest */
1260 lun_status = atomic_read(&zsdev->status);
1261 if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
1262 continue; /* unblock rport despite failed LUNs */
1263 /* LUN recovery not given up yet [maybe follow-up pending] */
1264 if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
1265 (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) {
1266 /* LUN blocked:
1267 * not yet unblocked [LUN recovery pending]
1268 * or meanwhile blocked [new LUN recovery triggered]
1269 */
1270 zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
1271 spin_unlock(shost->host_lock);
1272 write_unlock_irqrestore(&adapter->erp_lock, flags);
1273 return;
1274 }
1275 }
1276 /* now port has no child or all children have completed recovery,
1277 * and no ERP of severity >= port was meanwhile triggered elsewhere
1278 */
1279 zfcp_scsi_schedule_rport_register(port);
1280 spin_unlock(shost->host_lock);
1281 write_unlock_irqrestore(&adapter->erp_lock, flags);
1282}
1283
Christof Schmitt287ac012008-07-02 10:56:40 +02001284static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02001285{
Christof Schmitt287ac012008-07-02 10:56:40 +02001286 struct zfcp_adapter *adapter = act->adapter;
1287 struct zfcp_port *port = act->port;
Christof Schmittb62a8d92010-09-08 14:39:55 +02001288 struct scsi_device *sdev = act->sdev;
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02001289
Christof Schmitt287ac012008-07-02 10:56:40 +02001290 switch (act->action) {
Christof Schmittb62a8d92010-09-08 14:39:55 +02001291 case ZFCP_ERP_ACTION_REOPEN_LUN:
Christof Schmittfdbd1c52010-09-08 14:39:54 +02001292 if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
Christof Schmittb62a8d92010-09-08 14:39:55 +02001293 scsi_device_put(sdev);
Steffen Maier6f2ce1c2016-12-09 17:16:33 +01001294 zfcp_erp_try_rport_unblock(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 case ZFCP_ERP_ACTION_REOPEN_PORT:
Steffen Maier4eeaa4f2016-08-10 18:30:46 +02001298 /* This switch case might also happen after a forced reopen
1299 * was successfully done and thus overwritten with a new
1300 * non-forced reopen at `ersfs_2'. In this case, we must not
1301 * do the clean-up of the non-forced version.
1302 */
1303 if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
1304 if (result == ZFCP_ERP_SUCCEEDED)
Steffen Maier6f2ce1c2016-12-09 17:16:33 +01001305 zfcp_erp_try_rport_unblock(port);
Christof Schmitt57676202010-07-08 09:53:05 +02001306 /* fall through */
1307 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
Christof Schmitt615f59e2010-02-17 11:18:56 +01001308 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Christof Schmitta2fa0ae2009-03-02 13:09:08 +01001312 if (result == ZFCP_ERP_SUCCEEDED) {
Christof Schmittbd43a42b72008-12-25 13:38:50 +01001313 register_service_level(&adapter->service_level);
Steffen Maier43f60cb2012-09-04 15:23:35 +02001314 zfcp_fc_conditional_port_scan(adapter);
Christof Schmitt038d9442011-02-22 19:54:48 +01001315 queue_work(adapter->work_queue, &adapter->ns_up_work);
Christof Schmitta2fa0ae2009-03-02 13:09:08 +01001316 } else
1317 unregister_service_level(&adapter->service_level);
Christof Schmitt038d9442011-02-22 19:54:48 +01001318
Swen Schilligf3450c72009-11-24 16:53:59 +01001319 kref_put(&adapter->ref, zfcp_adapter_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 }
1322}
1323
Christof Schmitt287ac012008-07-02 10:56:40 +02001324static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
1325{
1326 switch (erp_action->action) {
1327 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1328 return zfcp_erp_adapter_strategy(erp_action);
1329 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1330 return zfcp_erp_port_forced_strategy(erp_action);
1331 case ZFCP_ERP_ACTION_REOPEN_PORT:
1332 return zfcp_erp_port_strategy(erp_action);
Christof Schmittb62a8d92010-09-08 14:39:55 +02001333 case ZFCP_ERP_ACTION_REOPEN_LUN:
1334 return zfcp_erp_lun_strategy(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +02001335 }
1336 return ZFCP_ERP_FAILED;
1337}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Christof Schmitt287ac012008-07-02 10:56:40 +02001339static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1340{
1341 int retval;
Christof Schmitt287ac012008-07-02 10:56:40 +02001342 unsigned long flags;
Swen Schilligecf0c772009-11-24 16:53:58 +01001343 struct zfcp_adapter *adapter = erp_action->adapter;
Christof Schmitt287ac012008-07-02 10:56:40 +02001344
Swen Schilligf3450c72009-11-24 16:53:59 +01001345 kref_get(&adapter->ref);
Christof Schmitt287ac012008-07-02 10:56:40 +02001346
Swen Schilligf3450c72009-11-24 16:53:59 +01001347 write_lock_irqsave(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +02001348 zfcp_erp_strategy_check_fsfreq(erp_action);
1349
1350 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
1351 zfcp_erp_action_dequeue(erp_action);
1352 retval = ZFCP_ERP_DISMISSED;
1353 goto unlock;
1354 }
1355
Christof Schmitt9c785d92010-07-08 09:53:09 +02001356 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
1357 retval = ZFCP_ERP_FAILED;
1358 goto check_target;
1359 }
1360
Christof Schmitt287ac012008-07-02 10:56:40 +02001361 zfcp_erp_action_to_running(erp_action);
1362
1363 /* no lock to allow for blocking operations */
Swen Schilligecf0c772009-11-24 16:53:58 +01001364 write_unlock_irqrestore(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +02001365 retval = zfcp_erp_strategy_do_action(erp_action);
Swen Schilligecf0c772009-11-24 16:53:58 +01001366 write_lock_irqsave(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +02001367
1368 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
1369 retval = ZFCP_ERP_CONTINUES;
1370
1371 switch (retval) {
1372 case ZFCP_ERP_NOMEM:
1373 if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
1374 ++adapter->erp_low_mem_count;
1375 erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
1376 }
1377 if (adapter->erp_total_count == adapter->erp_low_mem_count)
Swen Schilligea4a3a62010-12-02 15:16:16 +01001378 _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1");
Christof Schmitt287ac012008-07-02 10:56:40 +02001379 else {
1380 zfcp_erp_strategy_memwait(erp_action);
1381 retval = ZFCP_ERP_CONTINUES;
1382 }
1383 goto unlock;
1384
1385 case ZFCP_ERP_CONTINUES:
1386 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1387 --adapter->erp_low_mem_count;
1388 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1389 }
1390 goto unlock;
1391 }
1392
Christof Schmitt9c785d92010-07-08 09:53:09 +02001393check_target:
Christof Schmitt287ac012008-07-02 10:56:40 +02001394 retval = zfcp_erp_strategy_check_target(erp_action, retval);
1395 zfcp_erp_action_dequeue(erp_action);
1396 retval = zfcp_erp_strategy_statechange(erp_action, retval);
1397 if (retval == ZFCP_ERP_EXIT)
1398 goto unlock;
Christof Schmitt85600f72009-07-13 15:06:09 +02001399 if (retval == ZFCP_ERP_SUCCEEDED)
1400 zfcp_erp_strategy_followup_success(erp_action);
1401 if (retval == ZFCP_ERP_FAILED)
1402 zfcp_erp_strategy_followup_failed(erp_action);
Christof Schmitt287ac012008-07-02 10:56:40 +02001403
1404 unlock:
Swen Schilligecf0c772009-11-24 16:53:58 +01001405 write_unlock_irqrestore(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +02001406
1407 if (retval != ZFCP_ERP_CONTINUES)
1408 zfcp_erp_action_cleanup(erp_action, retval);
1409
Swen Schilligf3450c72009-11-24 16:53:59 +01001410 kref_put(&adapter->ref, zfcp_adapter_release);
Christof Schmitt287ac012008-07-02 10:56:40 +02001411 return retval;
1412}
1413
1414static int zfcp_erp_thread(void *data)
1415{
1416 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
1417 struct list_head *next;
1418 struct zfcp_erp_action *act;
1419 unsigned long flags;
1420
Christof Schmitt347c6a92009-08-18 15:43:25 +02001421 for (;;) {
Christof Schmitt347c6a92009-08-18 15:43:25 +02001422 wait_event_interruptible(adapter->erp_ready_wq,
1423 !list_empty(&adapter->erp_ready_head) ||
1424 kthread_should_stop());
Swen Schillig94ab4b32009-04-17 15:08:06 +02001425
Christof Schmitt347c6a92009-08-18 15:43:25 +02001426 if (kthread_should_stop())
1427 break;
1428
Christof Schmitt287ac012008-07-02 10:56:40 +02001429 write_lock_irqsave(&adapter->erp_lock, flags);
1430 next = adapter->erp_ready_head.next;
1431 write_unlock_irqrestore(&adapter->erp_lock, flags);
1432
1433 if (next != &adapter->erp_ready_head) {
1434 act = list_entry(next, struct zfcp_erp_action, list);
1435
1436 /* there is more to come after dismission, no notify */
1437 if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
1438 zfcp_erp_wakeup(adapter);
1439 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001440 }
1441
Christof Schmitt287ac012008-07-02 10:56:40 +02001442 return 0;
1443}
1444
1445/**
1446 * zfcp_erp_thread_setup - Start ERP thread for adapter
1447 * @adapter: Adapter to start the ERP thread for
1448 *
1449 * Returns 0 on success or error code from kernel_thread()
1450 */
1451int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
1452{
Christof Schmitt347c6a92009-08-18 15:43:25 +02001453 struct task_struct *thread;
Christof Schmitt287ac012008-07-02 10:56:40 +02001454
Christof Schmitt347c6a92009-08-18 15:43:25 +02001455 thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
1456 dev_name(&adapter->ccw_device->dev));
1457 if (IS_ERR(thread)) {
Christof Schmitt287ac012008-07-02 10:56:40 +02001458 dev_err(&adapter->ccw_device->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +02001459 "Creating an ERP thread for the FCP device failed.\n");
Christof Schmitt347c6a92009-08-18 15:43:25 +02001460 return PTR_ERR(thread);
Christof Schmitt287ac012008-07-02 10:56:40 +02001461 }
Christof Schmitt347c6a92009-08-18 15:43:25 +02001462
1463 adapter->erp_thread = thread;
Christof Schmitt287ac012008-07-02 10:56:40 +02001464 return 0;
1465}
1466
1467/**
1468 * zfcp_erp_thread_kill - Stop ERP thread.
1469 * @adapter: Adapter where the ERP thread should be stopped.
1470 *
1471 * The caller of this routine ensures that the specified adapter has
1472 * been shut down and that this operation has been completed. Thus,
1473 * there are no pending erp_actions which would need to be handled
1474 * here.
1475 */
1476void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
1477{
Christof Schmitt347c6a92009-08-18 15:43:25 +02001478 kthread_stop(adapter->erp_thread);
1479 adapter->erp_thread = NULL;
Christof Schmitt143bb6b2009-08-18 15:43:27 +02001480 WARN_ON(!list_empty(&adapter->erp_ready_head));
1481 WARN_ON(!list_empty(&adapter->erp_running_head));
Christof Schmitt287ac012008-07-02 10:56:40 +02001482}
1483
1484/**
Christof Schmitt287ac012008-07-02 10:56:40 +02001485 * zfcp_erp_wait - wait for completion of error recovery on an adapter
1486 * @adapter: adapter for which to wait for completion of its error recovery
1487 */
1488void zfcp_erp_wait(struct zfcp_adapter *adapter)
1489{
1490 wait_event(adapter->erp_done_wqh,
1491 !(atomic_read(&adapter->status) &
1492 ZFCP_STATUS_ADAPTER_ERP_PENDING));
1493}
1494
1495/**
Swen Schilligedaed852010-09-08 14:40:01 +02001496 * zfcp_erp_set_adapter_status - set adapter status bits
Christof Schmitt287ac012008-07-02 10:56:40 +02001497 * @adapter: adapter to change the status
Christof Schmitt287ac012008-07-02 10:56:40 +02001498 * @mask: status bits to change
Christof Schmitt287ac012008-07-02 10:56:40 +02001499 *
Christof Schmittb62a8d92010-09-08 14:39:55 +02001500 * Changes in common status bits are propagated to attached ports and LUNs.
Christof Schmitt287ac012008-07-02 10:56:40 +02001501 */
Swen Schilligedaed852010-09-08 14:40:01 +02001502void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 struct zfcp_port *port;
Swen Schilligedaed852010-09-08 14:40:01 +02001505 struct scsi_device *sdev;
Swen Schilligecf0c772009-11-24 16:53:58 +01001506 unsigned long flags;
Christof Schmitt287ac012008-07-02 10:56:40 +02001507 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001509 atomic_or(mask, &adapter->status);
Christof Schmitt287ac012008-07-02 10:56:40 +02001510
Swen Schilligedaed852010-09-08 14:40:01 +02001511 if (!common_mask)
1512 return;
1513
1514 read_lock_irqsave(&adapter->port_list_lock, flags);
1515 list_for_each_entry(port, &adapter->port_list, list)
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001516 atomic_or(common_mask, &port->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001517 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1518
Martin Peschke924dd582013-08-22 17:45:37 +02001519 spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
1520 __shost_for_each_device(sdev, adapter->scsi_host)
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001521 atomic_or(common_mask, &sdev_to_zfcp(sdev)->status);
Martin Peschke924dd582013-08-22 17:45:37 +02001522 spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
Swen Schilligedaed852010-09-08 14:40:01 +02001523}
1524
1525/**
1526 * zfcp_erp_clear_adapter_status - clear adapter status bits
1527 * @adapter: adapter to change the status
1528 * @mask: status bits to change
1529 *
1530 * Changes in common status bits are propagated to attached ports and LUNs.
1531 */
1532void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
1533{
1534 struct zfcp_port *port;
1535 struct scsi_device *sdev;
1536 unsigned long flags;
1537 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1538 u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
1539
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001540 atomic_andnot(mask, &adapter->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001541
1542 if (!common_mask)
1543 return;
1544
1545 if (clear_counter)
1546 atomic_set(&adapter->erp_counter, 0);
1547
1548 read_lock_irqsave(&adapter->port_list_lock, flags);
1549 list_for_each_entry(port, &adapter->port_list, list) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001550 atomic_andnot(common_mask, &port->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001551 if (clear_counter)
1552 atomic_set(&port->erp_counter, 0);
1553 }
1554 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1555
Martin Peschke924dd582013-08-22 17:45:37 +02001556 spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
1557 __shost_for_each_device(sdev, adapter->scsi_host) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001558 atomic_andnot(common_mask, &sdev_to_zfcp(sdev)->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001559 if (clear_counter)
1560 atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
Swen Schilligecf0c772009-11-24 16:53:58 +01001561 }
Martin Peschke924dd582013-08-22 17:45:37 +02001562 spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563}
1564
Christof Schmitt287ac012008-07-02 10:56:40 +02001565/**
Swen Schilligedaed852010-09-08 14:40:01 +02001566 * zfcp_erp_set_port_status - set port status bits
1567 * @port: port to change the status
Christof Schmitt287ac012008-07-02 10:56:40 +02001568 * @mask: status bits to change
Christof Schmitt287ac012008-07-02 10:56:40 +02001569 *
Christof Schmittb62a8d92010-09-08 14:39:55 +02001570 * Changes in common status bits are propagated to attached LUNs.
Christof Schmitt287ac012008-07-02 10:56:40 +02001571 */
Swen Schilligedaed852010-09-08 14:40:01 +02001572void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573{
Christof Schmittb62a8d92010-09-08 14:39:55 +02001574 struct scsi_device *sdev;
Christof Schmitt287ac012008-07-02 10:56:40 +02001575 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
Martin Peschke924dd582013-08-22 17:45:37 +02001576 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001578 atomic_or(mask, &port->status);
Christof Schmitt287ac012008-07-02 10:56:40 +02001579
Swen Schilligedaed852010-09-08 14:40:01 +02001580 if (!common_mask)
1581 return;
1582
Martin Peschke924dd582013-08-22 17:45:37 +02001583 spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
1584 __shost_for_each_device(sdev, port->adapter->scsi_host)
Swen Schilligedaed852010-09-08 14:40:01 +02001585 if (sdev_to_zfcp(sdev)->port == port)
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001586 atomic_or(common_mask,
Swen Schilligedaed852010-09-08 14:40:01 +02001587 &sdev_to_zfcp(sdev)->status);
Martin Peschke924dd582013-08-22 17:45:37 +02001588 spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589}
1590
Christof Schmitt287ac012008-07-02 10:56:40 +02001591/**
Swen Schilligedaed852010-09-08 14:40:01 +02001592 * zfcp_erp_clear_port_status - clear port status bits
1593 * @port: adapter to change the status
Christof Schmitt287ac012008-07-02 10:56:40 +02001594 * @mask: status bits to change
Swen Schilligedaed852010-09-08 14:40:01 +02001595 *
1596 * Changes in common status bits are propagated to attached LUNs.
Christof Schmitt287ac012008-07-02 10:56:40 +02001597 */
Swen Schilligedaed852010-09-08 14:40:01 +02001598void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
1599{
1600 struct scsi_device *sdev;
1601 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1602 u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
Martin Peschke924dd582013-08-22 17:45:37 +02001603 unsigned long flags;
Swen Schilligedaed852010-09-08 14:40:01 +02001604
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001605 atomic_andnot(mask, &port->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001606
1607 if (!common_mask)
1608 return;
1609
1610 if (clear_counter)
1611 atomic_set(&port->erp_counter, 0);
1612
Martin Peschke924dd582013-08-22 17:45:37 +02001613 spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
1614 __shost_for_each_device(sdev, port->adapter->scsi_host)
Swen Schilligedaed852010-09-08 14:40:01 +02001615 if (sdev_to_zfcp(sdev)->port == port) {
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001616 atomic_andnot(common_mask,
Swen Schilligedaed852010-09-08 14:40:01 +02001617 &sdev_to_zfcp(sdev)->status);
1618 if (clear_counter)
1619 atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
1620 }
Martin Peschke924dd582013-08-22 17:45:37 +02001621 spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
Swen Schilligedaed852010-09-08 14:40:01 +02001622}
1623
1624/**
1625 * zfcp_erp_set_lun_status - set lun status bits
1626 * @sdev: SCSI device / lun to set the status bits
1627 * @mask: status bits to change
1628 */
1629void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630{
Christof Schmittb62a8d92010-09-08 14:39:55 +02001631 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1632
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001633 atomic_or(mask, &zfcp_sdev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634}
1635
Christof Schmitt287ac012008-07-02 10:56:40 +02001636/**
Swen Schilligedaed852010-09-08 14:40:01 +02001637 * zfcp_erp_clear_lun_status - clear lun status bits
1638 * @sdev: SCSi device / lun to clear the status bits
1639 * @mask: status bits to change
Christof Schmitt287ac012008-07-02 10:56:40 +02001640 */
Swen Schilligedaed852010-09-08 14:40:01 +02001641void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001642{
Swen Schilligedaed852010-09-08 14:40:01 +02001643 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1644
Peter Zijlstra805de8f42015-04-24 01:12:32 +02001645 atomic_andnot(mask, &zfcp_sdev->status);
Swen Schilligedaed852010-09-08 14:40:01 +02001646
1647 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1648 atomic_set(&zfcp_sdev->erp_counter, 0);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001649}
1650