diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 409 |
1 files changed, 273 insertions, 136 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 03ea6748e7ee..35ca0e72df46 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -55,6 +55,8 @@ | |||
55 | #include <scsi/libfc.h> | 55 | #include <scsi/libfc.h> |
56 | #include <scsi/fc_encode.h> | 56 | #include <scsi/fc_encode.h> |
57 | 57 | ||
58 | #include "fc_libfc.h" | ||
59 | |||
58 | struct workqueue_struct *rport_event_queue; | 60 | struct workqueue_struct *rport_event_queue; |
59 | 61 | ||
60 | static void fc_rport_enter_plogi(struct fc_rport_priv *); | 62 | static void fc_rport_enter_plogi(struct fc_rport_priv *); |
@@ -86,12 +88,13 @@ static const char *fc_rport_state_names[] = { | |||
86 | [RPORT_ST_LOGO] = "LOGO", | 88 | [RPORT_ST_LOGO] = "LOGO", |
87 | [RPORT_ST_ADISC] = "ADISC", | 89 | [RPORT_ST_ADISC] = "ADISC", |
88 | [RPORT_ST_DELETE] = "Delete", | 90 | [RPORT_ST_DELETE] = "Delete", |
91 | [RPORT_ST_RESTART] = "Restart", | ||
89 | }; | 92 | }; |
90 | 93 | ||
91 | /** | 94 | /** |
92 | * fc_rport_lookup() - lookup a remote port by port_id | 95 | * fc_rport_lookup() - Lookup a remote port by port_id |
93 | * @lport: Fibre Channel host port instance | 96 | * @lport: The local port to lookup the remote port on |
94 | * @port_id: remote port port_id to match | 97 | * @port_id: The remote port ID to look up |
95 | */ | 98 | */ |
96 | static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, | 99 | static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, |
97 | u32 port_id) | 100 | u32 port_id) |
@@ -99,16 +102,17 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, | |||
99 | struct fc_rport_priv *rdata; | 102 | struct fc_rport_priv *rdata; |
100 | 103 | ||
101 | list_for_each_entry(rdata, &lport->disc.rports, peers) | 104 | list_for_each_entry(rdata, &lport->disc.rports, peers) |
102 | if (rdata->ids.port_id == port_id && | 105 | if (rdata->ids.port_id == port_id) |
103 | rdata->rp_state != RPORT_ST_DELETE) | ||
104 | return rdata; | 106 | return rdata; |
105 | return NULL; | 107 | return NULL; |
106 | } | 108 | } |
107 | 109 | ||
108 | /** | 110 | /** |
109 | * fc_rport_create() - Create a new remote port | 111 | * fc_rport_create() - Create a new remote port |
110 | * @lport: The local port that the new remote port is for | 112 | * @lport: The local port this remote port will be associated with |
111 | * @port_id: The port ID for the new remote port | 113 | * @ids: The identifiers for the new remote port |
114 | * | ||
115 | * The remote port will start in the INIT state. | ||
112 | * | 116 | * |
113 | * Locking note: must be called with the disc_mutex held. | 117 | * Locking note: must be called with the disc_mutex held. |
114 | */ | 118 | */ |
@@ -147,8 +151,8 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, | |||
147 | } | 151 | } |
148 | 152 | ||
149 | /** | 153 | /** |
150 | * fc_rport_destroy() - free a remote port after last reference is released. | 154 | * fc_rport_destroy() - Free a remote port after last reference is released |
151 | * @kref: pointer to kref inside struct fc_rport_priv | 155 | * @kref: The remote port's kref |
152 | */ | 156 | */ |
153 | static void fc_rport_destroy(struct kref *kref) | 157 | static void fc_rport_destroy(struct kref *kref) |
154 | { | 158 | { |
@@ -159,8 +163,8 @@ static void fc_rport_destroy(struct kref *kref) | |||
159 | } | 163 | } |
160 | 164 | ||
161 | /** | 165 | /** |
162 | * fc_rport_state() - return a string for the state the rport is in | 166 | * fc_rport_state() - Return a string identifying the remote port's state |
163 | * @rdata: remote port private data | 167 | * @rdata: The remote port |
164 | */ | 168 | */ |
165 | static const char *fc_rport_state(struct fc_rport_priv *rdata) | 169 | static const char *fc_rport_state(struct fc_rport_priv *rdata) |
166 | { | 170 | { |
@@ -173,9 +177,9 @@ static const char *fc_rport_state(struct fc_rport_priv *rdata) | |||
173 | } | 177 | } |
174 | 178 | ||
175 | /** | 179 | /** |
176 | * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. | 180 | * fc_set_rport_loss_tmo() - Set the remote port loss timeout |
177 | * @rport: Pointer to Fibre Channel remote port structure | 181 | * @rport: The remote port that gets a new timeout value |
178 | * @timeout: timeout in seconds | 182 | * @timeout: The new timeout value (in seconds) |
179 | */ | 183 | */ |
180 | void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | 184 | void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) |
181 | { | 185 | { |
@@ -187,9 +191,11 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
187 | EXPORT_SYMBOL(fc_set_rport_loss_tmo); | 191 | EXPORT_SYMBOL(fc_set_rport_loss_tmo); |
188 | 192 | ||
189 | /** | 193 | /** |
190 | * fc_plogi_get_maxframe() - Get max payload from the common service parameters | 194 | * fc_plogi_get_maxframe() - Get the maximum payload from the common service |
191 | * @flp: FLOGI payload structure | 195 | * parameters in a FLOGI frame |
192 | * @maxval: upper limit, may be less than what is in the service parameters | 196 | * @flp: The FLOGI payload |
197 | * @maxval: The maximum frame size upper limit; this may be less than what | ||
198 | * is in the service parameters | ||
193 | */ | 199 | */ |
194 | static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, | 200 | static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, |
195 | unsigned int maxval) | 201 | unsigned int maxval) |
@@ -210,9 +216,9 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, | |||
210 | } | 216 | } |
211 | 217 | ||
212 | /** | 218 | /** |
213 | * fc_rport_state_enter() - Change the rport's state | 219 | * fc_rport_state_enter() - Change the state of a remote port |
214 | * @rdata: The rport whose state should change | 220 | * @rdata: The remote port whose state should change |
215 | * @new: The new state of the rport | 221 | * @new: The new state |
216 | * | 222 | * |
217 | * Locking Note: Called with the rport lock held | 223 | * Locking Note: Called with the rport lock held |
218 | */ | 224 | */ |
@@ -224,17 +230,22 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata, | |||
224 | rdata->rp_state = new; | 230 | rdata->rp_state = new; |
225 | } | 231 | } |
226 | 232 | ||
233 | /** | ||
234 | * fc_rport_work() - Handler for remote port events in the rport_event_queue | ||
235 | * @work: Handle to the remote port being dequeued | ||
236 | */ | ||
227 | static void fc_rport_work(struct work_struct *work) | 237 | static void fc_rport_work(struct work_struct *work) |
228 | { | 238 | { |
229 | u32 port_id; | 239 | u32 port_id; |
230 | struct fc_rport_priv *rdata = | 240 | struct fc_rport_priv *rdata = |
231 | container_of(work, struct fc_rport_priv, event_work); | 241 | container_of(work, struct fc_rport_priv, event_work); |
232 | struct fc_rport_libfc_priv *rp; | 242 | struct fc_rport_libfc_priv *rpriv; |
233 | enum fc_rport_event event; | 243 | enum fc_rport_event event; |
234 | struct fc_lport *lport = rdata->local_port; | 244 | struct fc_lport *lport = rdata->local_port; |
235 | struct fc_rport_operations *rport_ops; | 245 | struct fc_rport_operations *rport_ops; |
236 | struct fc_rport_identifiers ids; | 246 | struct fc_rport_identifiers ids; |
237 | struct fc_rport *rport; | 247 | struct fc_rport *rport; |
248 | int restart = 0; | ||
238 | 249 | ||
239 | mutex_lock(&rdata->rp_mutex); | 250 | mutex_lock(&rdata->rp_mutex); |
240 | event = rdata->event; | 251 | event = rdata->event; |
@@ -265,12 +276,12 @@ static void fc_rport_work(struct work_struct *work) | |||
265 | rport->maxframe_size = rdata->maxframe_size; | 276 | rport->maxframe_size = rdata->maxframe_size; |
266 | rport->supported_classes = rdata->supported_classes; | 277 | rport->supported_classes = rdata->supported_classes; |
267 | 278 | ||
268 | rp = rport->dd_data; | 279 | rpriv = rport->dd_data; |
269 | rp->local_port = lport; | 280 | rpriv->local_port = lport; |
270 | rp->rp_state = rdata->rp_state; | 281 | rpriv->rp_state = rdata->rp_state; |
271 | rp->flags = rdata->flags; | 282 | rpriv->flags = rdata->flags; |
272 | rp->e_d_tov = rdata->e_d_tov; | 283 | rpriv->e_d_tov = rdata->e_d_tov; |
273 | rp->r_a_tov = rdata->r_a_tov; | 284 | rpriv->r_a_tov = rdata->r_a_tov; |
274 | mutex_unlock(&rdata->rp_mutex); | 285 | mutex_unlock(&rdata->rp_mutex); |
275 | 286 | ||
276 | if (rport_ops && rport_ops->event_callback) { | 287 | if (rport_ops && rport_ops->event_callback) { |
@@ -287,8 +298,19 @@ static void fc_rport_work(struct work_struct *work) | |||
287 | mutex_unlock(&rdata->rp_mutex); | 298 | mutex_unlock(&rdata->rp_mutex); |
288 | 299 | ||
289 | if (port_id != FC_FID_DIR_SERV) { | 300 | if (port_id != FC_FID_DIR_SERV) { |
301 | /* | ||
302 | * We must drop rp_mutex before taking disc_mutex. | ||
303 | * Re-evaluate state to allow for restart. | ||
304 | * A transition to RESTART state must only happen | ||
305 | * while disc_mutex is held and rdata is on the list. | ||
306 | */ | ||
290 | mutex_lock(&lport->disc.disc_mutex); | 307 | mutex_lock(&lport->disc.disc_mutex); |
291 | list_del(&rdata->peers); | 308 | mutex_lock(&rdata->rp_mutex); |
309 | if (rdata->rp_state == RPORT_ST_RESTART) | ||
310 | restart = 1; | ||
311 | else | ||
312 | list_del(&rdata->peers); | ||
313 | mutex_unlock(&rdata->rp_mutex); | ||
292 | mutex_unlock(&lport->disc.disc_mutex); | 314 | mutex_unlock(&lport->disc.disc_mutex); |
293 | } | 315 | } |
294 | 316 | ||
@@ -305,14 +327,20 @@ static void fc_rport_work(struct work_struct *work) | |||
305 | lport->tt.exch_mgr_reset(lport, port_id, 0); | 327 | lport->tt.exch_mgr_reset(lport, port_id, 0); |
306 | 328 | ||
307 | if (rport) { | 329 | if (rport) { |
308 | rp = rport->dd_data; | 330 | rpriv = rport->dd_data; |
309 | rp->rp_state = RPORT_ST_DELETE; | 331 | rpriv->rp_state = RPORT_ST_DELETE; |
310 | mutex_lock(&rdata->rp_mutex); | 332 | mutex_lock(&rdata->rp_mutex); |
311 | rdata->rport = NULL; | 333 | rdata->rport = NULL; |
312 | mutex_unlock(&rdata->rp_mutex); | 334 | mutex_unlock(&rdata->rp_mutex); |
313 | fc_remote_port_delete(rport); | 335 | fc_remote_port_delete(rport); |
314 | } | 336 | } |
315 | kref_put(&rdata->kref, lport->tt.rport_destroy); | 337 | if (restart) { |
338 | mutex_lock(&rdata->rp_mutex); | ||
339 | FC_RPORT_DBG(rdata, "work restart\n"); | ||
340 | fc_rport_enter_plogi(rdata); | ||
341 | mutex_unlock(&rdata->rp_mutex); | ||
342 | } else | ||
343 | kref_put(&rdata->kref, lport->tt.rport_destroy); | ||
316 | break; | 344 | break; |
317 | 345 | ||
318 | default: | 346 | default: |
@@ -323,7 +351,7 @@ static void fc_rport_work(struct work_struct *work) | |||
323 | 351 | ||
324 | /** | 352 | /** |
325 | * fc_rport_login() - Start the remote port login state machine | 353 | * fc_rport_login() - Start the remote port login state machine |
326 | * @rdata: private remote port | 354 | * @rdata: The remote port to be logged in to |
327 | * | 355 | * |
328 | * Locking Note: Called without the rport lock held. This | 356 | * Locking Note: Called without the rport lock held. This |
329 | * function will hold the rport lock, call an _enter_* | 357 | * function will hold the rport lock, call an _enter_* |
@@ -342,6 +370,12 @@ int fc_rport_login(struct fc_rport_priv *rdata) | |||
342 | FC_RPORT_DBG(rdata, "ADISC port\n"); | 370 | FC_RPORT_DBG(rdata, "ADISC port\n"); |
343 | fc_rport_enter_adisc(rdata); | 371 | fc_rport_enter_adisc(rdata); |
344 | break; | 372 | break; |
373 | case RPORT_ST_RESTART: | ||
374 | break; | ||
375 | case RPORT_ST_DELETE: | ||
376 | FC_RPORT_DBG(rdata, "Restart deleted port\n"); | ||
377 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); | ||
378 | break; | ||
345 | default: | 379 | default: |
346 | FC_RPORT_DBG(rdata, "Login to port\n"); | 380 | FC_RPORT_DBG(rdata, "Login to port\n"); |
347 | fc_rport_enter_plogi(rdata); | 381 | fc_rport_enter_plogi(rdata); |
@@ -353,9 +387,9 @@ int fc_rport_login(struct fc_rport_priv *rdata) | |||
353 | } | 387 | } |
354 | 388 | ||
355 | /** | 389 | /** |
356 | * fc_rport_enter_delete() - schedule a remote port to be deleted. | 390 | * fc_rport_enter_delete() - Schedule a remote port to be deleted |
357 | * @rdata: private remote port | 391 | * @rdata: The remote port to be deleted |
358 | * @event: event to report as the reason for deletion | 392 | * @event: The event to report as the reason for deletion |
359 | * | 393 | * |
360 | * Locking Note: Called with the rport lock held. | 394 | * Locking Note: Called with the rport lock held. |
361 | * | 395 | * |
@@ -382,8 +416,8 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, | |||
382 | } | 416 | } |
383 | 417 | ||
384 | /** | 418 | /** |
385 | * fc_rport_logoff() - Logoff and remove an rport | 419 | * fc_rport_logoff() - Logoff and remove a remote port |
386 | * @rdata: private remote port | 420 | * @rdata: The remote port to be logged off of |
387 | * | 421 | * |
388 | * Locking Note: Called without the rport lock held. This | 422 | * Locking Note: Called without the rport lock held. This |
389 | * function will hold the rport lock, call an _enter_* | 423 | * function will hold the rport lock, call an _enter_* |
@@ -397,26 +431,27 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) | |||
397 | 431 | ||
398 | if (rdata->rp_state == RPORT_ST_DELETE) { | 432 | if (rdata->rp_state == RPORT_ST_DELETE) { |
399 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); | 433 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); |
400 | mutex_unlock(&rdata->rp_mutex); | ||
401 | goto out; | 434 | goto out; |
402 | } | 435 | } |
403 | 436 | ||
404 | fc_rport_enter_logo(rdata); | 437 | if (rdata->rp_state == RPORT_ST_RESTART) |
438 | FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); | ||
439 | else | ||
440 | fc_rport_enter_logo(rdata); | ||
405 | 441 | ||
406 | /* | 442 | /* |
407 | * Change the state to Delete so that we discard | 443 | * Change the state to Delete so that we discard |
408 | * the response. | 444 | * the response. |
409 | */ | 445 | */ |
410 | fc_rport_enter_delete(rdata, RPORT_EV_STOP); | 446 | fc_rport_enter_delete(rdata, RPORT_EV_STOP); |
411 | mutex_unlock(&rdata->rp_mutex); | ||
412 | |||
413 | out: | 447 | out: |
448 | mutex_unlock(&rdata->rp_mutex); | ||
414 | return 0; | 449 | return 0; |
415 | } | 450 | } |
416 | 451 | ||
417 | /** | 452 | /** |
418 | * fc_rport_enter_ready() - The rport is ready | 453 | * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state |
419 | * @rdata: private remote port | 454 | * @rdata: The remote port that is ready |
420 | * | 455 | * |
421 | * Locking Note: The rport lock is expected to be held before calling | 456 | * Locking Note: The rport lock is expected to be held before calling |
422 | * this routine. | 457 | * this routine. |
@@ -433,8 +468,8 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) | |||
433 | } | 468 | } |
434 | 469 | ||
435 | /** | 470 | /** |
436 | * fc_rport_timeout() - Handler for the retry_work timer. | 471 | * fc_rport_timeout() - Handler for the retry_work timer |
437 | * @work: The work struct of the fc_rport_priv | 472 | * @work: Handle to the remote port that has timed out |
438 | * | 473 | * |
439 | * Locking Note: Called without the rport lock held. This | 474 | * Locking Note: Called without the rport lock held. This |
440 | * function will hold the rport lock, call an _enter_* | 475 | * function will hold the rport lock, call an _enter_* |
@@ -466,6 +501,7 @@ static void fc_rport_timeout(struct work_struct *work) | |||
466 | case RPORT_ST_READY: | 501 | case RPORT_ST_READY: |
467 | case RPORT_ST_INIT: | 502 | case RPORT_ST_INIT: |
468 | case RPORT_ST_DELETE: | 503 | case RPORT_ST_DELETE: |
504 | case RPORT_ST_RESTART: | ||
469 | break; | 505 | break; |
470 | } | 506 | } |
471 | 507 | ||
@@ -474,8 +510,8 @@ static void fc_rport_timeout(struct work_struct *work) | |||
474 | 510 | ||
475 | /** | 511 | /** |
476 | * fc_rport_error() - Error handler, called once retries have been exhausted | 512 | * fc_rport_error() - Error handler, called once retries have been exhausted |
477 | * @rdata: private remote port | 513 | * @rdata: The remote port the error is happened on |
478 | * @fp: The frame pointer | 514 | * @fp: The error code encapsulated in a frame pointer |
479 | * | 515 | * |
480 | * Locking Note: The rport lock is expected to be held before | 516 | * Locking Note: The rport lock is expected to be held before |
481 | * calling this routine | 517 | * calling this routine |
@@ -499,6 +535,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
499 | fc_rport_enter_logo(rdata); | 535 | fc_rport_enter_logo(rdata); |
500 | break; | 536 | break; |
501 | case RPORT_ST_DELETE: | 537 | case RPORT_ST_DELETE: |
538 | case RPORT_ST_RESTART: | ||
502 | case RPORT_ST_READY: | 539 | case RPORT_ST_READY: |
503 | case RPORT_ST_INIT: | 540 | case RPORT_ST_INIT: |
504 | break; | 541 | break; |
@@ -506,9 +543,9 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
506 | } | 543 | } |
507 | 544 | ||
508 | /** | 545 | /** |
509 | * fc_rport_error_retry() - Error handler when retries are desired | 546 | * fc_rport_error_retry() - Handler for remote port state retries |
510 | * @rdata: private remote port data | 547 | * @rdata: The remote port whose state is to be retried |
511 | * @fp: The frame pointer | 548 | * @fp: The error code encapsulated in a frame pointer |
512 | * | 549 | * |
513 | * If the error was an exchange timeout retry immediately, | 550 | * If the error was an exchange timeout retry immediately, |
514 | * otherwise wait for E_D_TOV. | 551 | * otherwise wait for E_D_TOV. |
@@ -540,10 +577,10 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, | |||
540 | } | 577 | } |
541 | 578 | ||
542 | /** | 579 | /** |
543 | * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response | 580 | * fc_rport_plogi_recv_resp() - Handler for ELS PLOGI responses |
544 | * @sp: current sequence in the PLOGI exchange | 581 | * @sp: The sequence the PLOGI is on |
545 | * @fp: response frame | 582 | * @fp: The PLOGI response frame |
546 | * @rdata_arg: private remote port data | 583 | * @rdata_arg: The remote port that sent the PLOGI response |
547 | * | 584 | * |
548 | * Locking Note: This function will be called without the rport lock | 585 | * Locking Note: This function will be called without the rport lock |
549 | * held, but it will lock, call an _enter_* function or fc_rport_error | 586 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -606,8 +643,8 @@ err: | |||
606 | } | 643 | } |
607 | 644 | ||
608 | /** | 645 | /** |
609 | * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer | 646 | * fc_rport_enter_plogi() - Send Port Login (PLOGI) request |
610 | * @rdata: private remote port data | 647 | * @rdata: The remote port to send a PLOGI to |
611 | * | 648 | * |
612 | * Locking Note: The rport lock is expected to be held before calling | 649 | * Locking Note: The rport lock is expected to be held before calling |
613 | * this routine. | 650 | * this routine. |
@@ -631,17 +668,18 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) | |||
631 | rdata->e_d_tov = lport->e_d_tov; | 668 | rdata->e_d_tov = lport->e_d_tov; |
632 | 669 | ||
633 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, | 670 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, |
634 | fc_rport_plogi_resp, rdata, lport->e_d_tov)) | 671 | fc_rport_plogi_resp, rdata, |
635 | fc_rport_error_retry(rdata, fp); | 672 | 2 * lport->r_a_tov)) |
673 | fc_rport_error_retry(rdata, NULL); | ||
636 | else | 674 | else |
637 | kref_get(&rdata->kref); | 675 | kref_get(&rdata->kref); |
638 | } | 676 | } |
639 | 677 | ||
640 | /** | 678 | /** |
641 | * fc_rport_prli_resp() - Process Login (PRLI) response handler | 679 | * fc_rport_prli_resp() - Process Login (PRLI) response handler |
642 | * @sp: current sequence in the PRLI exchange | 680 | * @sp: The sequence the PRLI response was on |
643 | * @fp: response frame | 681 | * @fp: The PRLI response frame |
644 | * @rdata_arg: private remote port data | 682 | * @rdata_arg: The remote port that sent the PRLI response |
645 | * | 683 | * |
646 | * Locking Note: This function will be called without the rport lock | 684 | * Locking Note: This function will be called without the rport lock |
647 | * held, but it will lock, call an _enter_* function or fc_rport_error | 685 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -710,10 +748,10 @@ err: | |||
710 | } | 748 | } |
711 | 749 | ||
712 | /** | 750 | /** |
713 | * fc_rport_logo_resp() - Logout (LOGO) response handler | 751 | * fc_rport_logo_resp() - Handler for logout (LOGO) responses |
714 | * @sp: current sequence in the LOGO exchange | 752 | * @sp: The sequence the LOGO was on |
715 | * @fp: response frame | 753 | * @fp: The LOGO response frame |
716 | * @rdata_arg: private remote port data | 754 | * @rdata_arg: The remote port that sent the LOGO response |
717 | * | 755 | * |
718 | * Locking Note: This function will be called without the rport lock | 756 | * Locking Note: This function will be called without the rport lock |
719 | * held, but it will lock, call an _enter_* function or fc_rport_error | 757 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -756,8 +794,8 @@ err: | |||
756 | } | 794 | } |
757 | 795 | ||
758 | /** | 796 | /** |
759 | * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer | 797 | * fc_rport_enter_prli() - Send Process Login (PRLI) request |
760 | * @rdata: private remote port data | 798 | * @rdata: The remote port to send the PRLI request to |
761 | * | 799 | * |
762 | * Locking Note: The rport lock is expected to be held before calling | 800 | * Locking Note: The rport lock is expected to be held before calling |
763 | * this routine. | 801 | * this routine. |
@@ -792,17 +830,18 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) | |||
792 | } | 830 | } |
793 | 831 | ||
794 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, | 832 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, |
795 | fc_rport_prli_resp, rdata, lport->e_d_tov)) | 833 | fc_rport_prli_resp, rdata, |
796 | fc_rport_error_retry(rdata, fp); | 834 | 2 * lport->r_a_tov)) |
835 | fc_rport_error_retry(rdata, NULL); | ||
797 | else | 836 | else |
798 | kref_get(&rdata->kref); | 837 | kref_get(&rdata->kref); |
799 | } | 838 | } |
800 | 839 | ||
801 | /** | 840 | /** |
802 | * fc_rport_els_rtv_resp() - Request Timeout Value response handler | 841 | * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses |
803 | * @sp: current sequence in the RTV exchange | 842 | * @sp: The sequence the RTV was on |
804 | * @fp: response frame | 843 | * @fp: The RTV response frame |
805 | * @rdata_arg: private remote port data | 844 | * @rdata_arg: The remote port that sent the RTV response |
806 | * | 845 | * |
807 | * Many targets don't seem to support this. | 846 | * Many targets don't seem to support this. |
808 | * | 847 | * |
@@ -865,8 +904,8 @@ err: | |||
865 | } | 904 | } |
866 | 905 | ||
867 | /** | 906 | /** |
868 | * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer | 907 | * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request |
869 | * @rdata: private remote port data | 908 | * @rdata: The remote port to send the RTV request to |
870 | * | 909 | * |
871 | * Locking Note: The rport lock is expected to be held before calling | 910 | * Locking Note: The rport lock is expected to be held before calling |
872 | * this routine. | 911 | * this routine. |
@@ -888,15 +927,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) | |||
888 | } | 927 | } |
889 | 928 | ||
890 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, | 929 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, |
891 | fc_rport_rtv_resp, rdata, lport->e_d_tov)) | 930 | fc_rport_rtv_resp, rdata, |
892 | fc_rport_error_retry(rdata, fp); | 931 | 2 * lport->r_a_tov)) |
932 | fc_rport_error_retry(rdata, NULL); | ||
893 | else | 933 | else |
894 | kref_get(&rdata->kref); | 934 | kref_get(&rdata->kref); |
895 | } | 935 | } |
896 | 936 | ||
897 | /** | 937 | /** |
898 | * fc_rport_enter_logo() - Send Logout (LOGO) request to peer | 938 | * fc_rport_enter_logo() - Send a logout (LOGO) request |
899 | * @rdata: private remote port data | 939 | * @rdata: The remote port to send the LOGO request to |
900 | * | 940 | * |
901 | * Locking Note: The rport lock is expected to be held before calling | 941 | * Locking Note: The rport lock is expected to be held before calling |
902 | * this routine. | 942 | * this routine. |
@@ -918,24 +958,25 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) | |||
918 | } | 958 | } |
919 | 959 | ||
920 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, | 960 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, |
921 | fc_rport_logo_resp, rdata, lport->e_d_tov)) | 961 | fc_rport_logo_resp, rdata, |
922 | fc_rport_error_retry(rdata, fp); | 962 | 2 * lport->r_a_tov)) |
963 | fc_rport_error_retry(rdata, NULL); | ||
923 | else | 964 | else |
924 | kref_get(&rdata->kref); | 965 | kref_get(&rdata->kref); |
925 | } | 966 | } |
926 | 967 | ||
927 | /** | 968 | /** |
928 | * fc_rport_els_adisc_resp() - Address Discovery response handler | 969 | * fc_rport_els_adisc_resp() - Handler for Address Discovery (ADISC) responses |
929 | * @sp: current sequence in the ADISC exchange | 970 | * @sp: The sequence the ADISC response was on |
930 | * @fp: response frame | 971 | * @fp: The ADISC response frame |
931 | * @rdata_arg: remote port private. | 972 | * @rdata_arg: The remote port that sent the ADISC response |
932 | * | 973 | * |
933 | * Locking Note: This function will be called without the rport lock | 974 | * Locking Note: This function will be called without the rport lock |
934 | * held, but it will lock, call an _enter_* function or fc_rport_error | 975 | * held, but it will lock, call an _enter_* function or fc_rport_error |
935 | * and then unlock the rport. | 976 | * and then unlock the rport. |
936 | */ | 977 | */ |
937 | static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, | 978 | static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, |
938 | void *rdata_arg) | 979 | void *rdata_arg) |
939 | { | 980 | { |
940 | struct fc_rport_priv *rdata = rdata_arg; | 981 | struct fc_rport_priv *rdata = rdata_arg; |
941 | struct fc_els_adisc *adisc; | 982 | struct fc_els_adisc *adisc; |
@@ -983,8 +1024,8 @@ err: | |||
983 | } | 1024 | } |
984 | 1025 | ||
985 | /** | 1026 | /** |
986 | * fc_rport_enter_adisc() - Send Address Discover (ADISC) request to peer | 1027 | * fc_rport_enter_adisc() - Send Address Discover (ADISC) request |
987 | * @rdata: remote port private data | 1028 | * @rdata: The remote port to send the ADISC request to |
988 | * | 1029 | * |
989 | * Locking Note: The rport lock is expected to be held before calling | 1030 | * Locking Note: The rport lock is expected to be held before calling |
990 | * this routine. | 1031 | * this routine. |
@@ -1005,17 +1046,18 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) | |||
1005 | return; | 1046 | return; |
1006 | } | 1047 | } |
1007 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, | 1048 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, |
1008 | fc_rport_adisc_resp, rdata, lport->e_d_tov)) | 1049 | fc_rport_adisc_resp, rdata, |
1009 | fc_rport_error_retry(rdata, fp); | 1050 | 2 * lport->r_a_tov)) |
1051 | fc_rport_error_retry(rdata, NULL); | ||
1010 | else | 1052 | else |
1011 | kref_get(&rdata->kref); | 1053 | kref_get(&rdata->kref); |
1012 | } | 1054 | } |
1013 | 1055 | ||
1014 | /** | 1056 | /** |
1015 | * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request | 1057 | * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests |
1016 | * @rdata: remote port private | 1058 | * @rdata: The remote port that sent the ADISC request |
1017 | * @sp: current sequence in the ADISC exchange | 1059 | * @sp: The sequence the ADISC request was on |
1018 | * @in_fp: ADISC request frame | 1060 | * @in_fp: The ADISC request frame |
1019 | * | 1061 | * |
1020 | * Locking Note: Called with the lport and rport locks held. | 1062 | * Locking Note: Called with the lport and rport locks held. |
1021 | */ | 1063 | */ |
@@ -1056,10 +1098,82 @@ drop: | |||
1056 | } | 1098 | } |
1057 | 1099 | ||
1058 | /** | 1100 | /** |
1059 | * fc_rport_recv_els_req() - handle a validated ELS request. | 1101 | * fc_rport_recv_rls_req() - Handle received Read Link Status request |
1060 | * @lport: Fibre Channel local port | 1102 | * @rdata: The remote port that sent the RLS request |
1061 | * @sp: current sequence in the PLOGI exchange | 1103 | * @sp: The sequence that the RLS was on |
1062 | * @fp: response frame | 1104 | * @rx_fp: The PRLI request frame |
1105 | * | ||
1106 | * Locking Note: The rport lock is expected to be held before calling | ||
1107 | * this function. | ||
1108 | */ | ||
1109 | static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | ||
1110 | struct fc_seq *sp, struct fc_frame *rx_fp) | ||
1111 | |||
1112 | { | ||
1113 | struct fc_lport *lport = rdata->local_port; | ||
1114 | struct fc_frame *fp; | ||
1115 | struct fc_exch *ep = fc_seq_exch(sp); | ||
1116 | struct fc_els_rls *rls; | ||
1117 | struct fc_els_rls_resp *rsp; | ||
1118 | struct fc_els_lesb *lesb; | ||
1119 | struct fc_seq_els_data rjt_data; | ||
1120 | struct fc_host_statistics *hst; | ||
1121 | u32 f_ctl; | ||
1122 | |||
1123 | FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n", | ||
1124 | fc_rport_state(rdata)); | ||
1125 | |||
1126 | rls = fc_frame_payload_get(rx_fp, sizeof(*rls)); | ||
1127 | if (!rls) { | ||
1128 | rjt_data.reason = ELS_RJT_PROT; | ||
1129 | rjt_data.explan = ELS_EXPL_INV_LEN; | ||
1130 | goto out_rjt; | ||
1131 | } | ||
1132 | |||
1133 | fp = fc_frame_alloc(lport, sizeof(*rsp)); | ||
1134 | if (!fp) { | ||
1135 | rjt_data.reason = ELS_RJT_UNAB; | ||
1136 | rjt_data.explan = ELS_EXPL_INSUF_RES; | ||
1137 | goto out_rjt; | ||
1138 | } | ||
1139 | |||
1140 | rsp = fc_frame_payload_get(fp, sizeof(*rsp)); | ||
1141 | memset(rsp, 0, sizeof(*rsp)); | ||
1142 | rsp->rls_cmd = ELS_LS_ACC; | ||
1143 | lesb = &rsp->rls_lesb; | ||
1144 | if (lport->tt.get_lesb) { | ||
1145 | /* get LESB from LLD if it supports it */ | ||
1146 | lport->tt.get_lesb(lport, lesb); | ||
1147 | } else { | ||
1148 | fc_get_host_stats(lport->host); | ||
1149 | hst = &lport->host_stats; | ||
1150 | lesb->lesb_link_fail = htonl(hst->link_failure_count); | ||
1151 | lesb->lesb_sync_loss = htonl(hst->loss_of_sync_count); | ||
1152 | lesb->lesb_sig_loss = htonl(hst->loss_of_signal_count); | ||
1153 | lesb->lesb_prim_err = htonl(hst->prim_seq_protocol_err_count); | ||
1154 | lesb->lesb_inv_word = htonl(hst->invalid_tx_word_count); | ||
1155 | lesb->lesb_inv_crc = htonl(hst->invalid_crc_count); | ||
1156 | } | ||
1157 | |||
1158 | sp = lport->tt.seq_start_next(sp); | ||
1159 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | ||
1160 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1161 | FC_TYPE_ELS, f_ctl, 0); | ||
1162 | lport->tt.seq_send(lport, sp, fp); | ||
1163 | goto out; | ||
1164 | |||
1165 | out_rjt: | ||
1166 | rjt_data.fp = NULL; | ||
1167 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | ||
1168 | out: | ||
1169 | fc_frame_free(rx_fp); | ||
1170 | } | ||
1171 | |||
1172 | /** | ||
1173 | * fc_rport_recv_els_req() - Handler for validated ELS requests | ||
1174 | * @lport: The local port that received the ELS request | ||
1175 | * @sp: The sequence that the ELS request was on | ||
1176 | * @fp: The ELS request frame | ||
1063 | * | 1177 | * |
1064 | * Handle incoming ELS requests that require port login. | 1178 | * Handle incoming ELS requests that require port login. |
1065 | * The ELS opcode has already been validated by the caller. | 1179 | * The ELS opcode has already been validated by the caller. |
@@ -1117,6 +1231,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, | |||
1117 | els_data.fp = fp; | 1231 | els_data.fp = fp; |
1118 | lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); | 1232 | lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); |
1119 | break; | 1233 | break; |
1234 | case ELS_RLS: | ||
1235 | fc_rport_recv_rls_req(rdata, sp, fp); | ||
1236 | break; | ||
1120 | default: | 1237 | default: |
1121 | fc_frame_free(fp); /* can't happen */ | 1238 | fc_frame_free(fp); /* can't happen */ |
1122 | break; | 1239 | break; |
@@ -1131,10 +1248,10 @@ reject: | |||
1131 | } | 1248 | } |
1132 | 1249 | ||
1133 | /** | 1250 | /** |
1134 | * fc_rport_recv_req() - Handle a received ELS request from a rport | 1251 | * fc_rport_recv_req() - Handler for requests |
1135 | * @sp: current sequence in the PLOGI exchange | 1252 | * @sp: The sequence the request was on |
1136 | * @fp: response frame | 1253 | * @fp: The request frame |
1137 | * @lport: Fibre Channel local port | 1254 | * @lport: The local port that received the request |
1138 | * | 1255 | * |
1139 | * Locking Note: Called with the lport lock held. | 1256 | * Locking Note: Called with the lport lock held. |
1140 | */ | 1257 | */ |
@@ -1161,6 +1278,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1161 | case ELS_ADISC: | 1278 | case ELS_ADISC: |
1162 | case ELS_RRQ: | 1279 | case ELS_RRQ: |
1163 | case ELS_REC: | 1280 | case ELS_REC: |
1281 | case ELS_RLS: | ||
1164 | fc_rport_recv_els_req(lport, sp, fp); | 1282 | fc_rport_recv_els_req(lport, sp, fp); |
1165 | break; | 1283 | break; |
1166 | default: | 1284 | default: |
@@ -1174,10 +1292,10 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1174 | } | 1292 | } |
1175 | 1293 | ||
1176 | /** | 1294 | /** |
1177 | * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request | 1295 | * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests |
1178 | * @lport: local port | 1296 | * @lport: The local port that received the PLOGI request |
1179 | * @sp: current sequence in the PLOGI exchange | 1297 | * @sp: The sequence that the PLOGI request was on |
1180 | * @fp: PLOGI request frame | 1298 | * @rx_fp: The PLOGI request frame |
1181 | * | 1299 | * |
1182 | * Locking Note: The rport lock is held before calling this function. | 1300 | * Locking Note: The rport lock is held before calling this function. |
1183 | */ | 1301 | */ |
@@ -1248,6 +1366,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1248 | } | 1366 | } |
1249 | break; | 1367 | break; |
1250 | case RPORT_ST_PRLI: | 1368 | case RPORT_ST_PRLI: |
1369 | case RPORT_ST_RTV: | ||
1251 | case RPORT_ST_READY: | 1370 | case RPORT_ST_READY: |
1252 | case RPORT_ST_ADISC: | 1371 | case RPORT_ST_ADISC: |
1253 | FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " | 1372 | FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " |
@@ -1255,11 +1374,14 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1255 | /* XXX TBD - should reset */ | 1374 | /* XXX TBD - should reset */ |
1256 | break; | 1375 | break; |
1257 | case RPORT_ST_DELETE: | 1376 | case RPORT_ST_DELETE: |
1258 | default: | 1377 | case RPORT_ST_LOGO: |
1259 | FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n", | 1378 | case RPORT_ST_RESTART: |
1260 | rdata->rp_state); | 1379 | FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", |
1261 | fc_frame_free(rx_fp); | 1380 | fc_rport_state(rdata)); |
1262 | goto out; | 1381 | mutex_unlock(&rdata->rp_mutex); |
1382 | rjt_data.reason = ELS_RJT_BUSY; | ||
1383 | rjt_data.explan = ELS_EXPL_NONE; | ||
1384 | goto reject; | ||
1263 | } | 1385 | } |
1264 | 1386 | ||
1265 | /* | 1387 | /* |
@@ -1295,10 +1417,10 @@ reject: | |||
1295 | } | 1417 | } |
1296 | 1418 | ||
1297 | /** | 1419 | /** |
1298 | * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request | 1420 | * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests |
1299 | * @rdata: private remote port data | 1421 | * @rdata: The remote port that sent the PRLI request |
1300 | * @sp: current sequence in the PRLI exchange | 1422 | * @sp: The sequence that the PRLI was on |
1301 | * @fp: PRLI request frame | 1423 | * @rx_fp: The PRLI request frame |
1302 | * | 1424 | * |
1303 | * Locking Note: The rport lock is exected to be held before calling | 1425 | * Locking Note: The rport lock is exected to be held before calling |
1304 | * this function. | 1426 | * this function. |
@@ -1402,7 +1524,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1402 | break; | 1524 | break; |
1403 | case FC_TYPE_FCP: | 1525 | case FC_TYPE_FCP: |
1404 | fcp_parm = ntohl(rspp->spp_params); | 1526 | fcp_parm = ntohl(rspp->spp_params); |
1405 | if (fcp_parm * FCP_SPPF_RETRY) | 1527 | if (fcp_parm & FCP_SPPF_RETRY) |
1406 | rdata->flags |= FC_RP_FLAGS_RETRY; | 1528 | rdata->flags |= FC_RP_FLAGS_RETRY; |
1407 | rdata->supported_classes = FC_COS_CLASS3; | 1529 | rdata->supported_classes = FC_COS_CLASS3; |
1408 | if (fcp_parm & FCP_SPPF_INIT_FCN) | 1530 | if (fcp_parm & FCP_SPPF_INIT_FCN) |
@@ -1452,10 +1574,10 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1452 | } | 1574 | } |
1453 | 1575 | ||
1454 | /** | 1576 | /** |
1455 | * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request | 1577 | * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests |
1456 | * @rdata: private remote port data | 1578 | * @rdata: The remote port that sent the PRLO request |
1457 | * @sp: current sequence in the PRLO exchange | 1579 | * @sp: The sequence that the PRLO was on |
1458 | * @fp: PRLO request frame | 1580 | * @fp: The PRLO request frame |
1459 | * | 1581 | * |
1460 | * Locking Note: The rport lock is exected to be held before calling | 1582 | * Locking Note: The rport lock is exected to be held before calling |
1461 | * this function. | 1583 | * this function. |
@@ -1482,10 +1604,10 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1482 | } | 1604 | } |
1483 | 1605 | ||
1484 | /** | 1606 | /** |
1485 | * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request | 1607 | * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests |
1486 | * @lport: local port. | 1608 | * @lport: The local port that received the LOGO request |
1487 | * @sp: current sequence in the LOGO exchange | 1609 | * @sp: The sequence that the LOGO request was on |
1488 | * @fp: LOGO request frame | 1610 | * @fp: The LOGO request frame |
1489 | * | 1611 | * |
1490 | * Locking Note: The rport lock is exected to be held before calling | 1612 | * Locking Note: The rport lock is exected to be held before calling |
1491 | * this function. | 1613 | * this function. |
@@ -1510,14 +1632,14 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1510 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", | 1632 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", |
1511 | fc_rport_state(rdata)); | 1633 | fc_rport_state(rdata)); |
1512 | 1634 | ||
1635 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | ||
1636 | |||
1513 | /* | 1637 | /* |
1514 | * If the remote port was created due to discovery, | 1638 | * If the remote port was created due to discovery, set state |
1515 | * log back in. It may have seen a stale RSCN about us. | 1639 | * to log back in. It may have seen a stale RSCN about us. |
1516 | */ | 1640 | */ |
1517 | if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id) | 1641 | if (rdata->disc_id) |
1518 | fc_rport_enter_plogi(rdata); | 1642 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); |
1519 | else | ||
1520 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | ||
1521 | mutex_unlock(&rdata->rp_mutex); | 1643 | mutex_unlock(&rdata->rp_mutex); |
1522 | } else | 1644 | } else |
1523 | FC_RPORT_ID_DBG(lport, sid, | 1645 | FC_RPORT_ID_DBG(lport, sid, |
@@ -1526,11 +1648,18 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1526 | fc_frame_free(fp); | 1648 | fc_frame_free(fp); |
1527 | } | 1649 | } |
1528 | 1650 | ||
1651 | /** | ||
1652 | * fc_rport_flush_queue() - Flush the rport_event_queue | ||
1653 | */ | ||
1529 | static void fc_rport_flush_queue(void) | 1654 | static void fc_rport_flush_queue(void) |
1530 | { | 1655 | { |
1531 | flush_workqueue(rport_event_queue); | 1656 | flush_workqueue(rport_event_queue); |
1532 | } | 1657 | } |
1533 | 1658 | ||
1659 | /** | ||
1660 | * fc_rport_init() - Initialize the remote port layer for a local port | ||
1661 | * @lport: The local port to initialize the remote port layer for | ||
1662 | */ | ||
1534 | int fc_rport_init(struct fc_lport *lport) | 1663 | int fc_rport_init(struct fc_lport *lport) |
1535 | { | 1664 | { |
1536 | if (!lport->tt.rport_lookup) | 1665 | if (!lport->tt.rport_lookup) |
@@ -1558,25 +1687,33 @@ int fc_rport_init(struct fc_lport *lport) | |||
1558 | } | 1687 | } |
1559 | EXPORT_SYMBOL(fc_rport_init); | 1688 | EXPORT_SYMBOL(fc_rport_init); |
1560 | 1689 | ||
1561 | int fc_setup_rport(void) | 1690 | /** |
1691 | * fc_setup_rport() - Initialize the rport_event_queue | ||
1692 | */ | ||
1693 | int fc_setup_rport() | ||
1562 | { | 1694 | { |
1563 | rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); | 1695 | rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); |
1564 | if (!rport_event_queue) | 1696 | if (!rport_event_queue) |
1565 | return -ENOMEM; | 1697 | return -ENOMEM; |
1566 | return 0; | 1698 | return 0; |
1567 | } | 1699 | } |
1568 | EXPORT_SYMBOL(fc_setup_rport); | ||
1569 | 1700 | ||
1570 | void fc_destroy_rport(void) | 1701 | /** |
1702 | * fc_destroy_rport() - Destroy the rport_event_queue | ||
1703 | */ | ||
1704 | void fc_destroy_rport() | ||
1571 | { | 1705 | { |
1572 | destroy_workqueue(rport_event_queue); | 1706 | destroy_workqueue(rport_event_queue); |
1573 | } | 1707 | } |
1574 | EXPORT_SYMBOL(fc_destroy_rport); | ||
1575 | 1708 | ||
1709 | /** | ||
1710 | * fc_rport_terminate_io() - Stop all outstanding I/O on a remote port | ||
1711 | * @rport: The remote port whose I/O should be terminated | ||
1712 | */ | ||
1576 | void fc_rport_terminate_io(struct fc_rport *rport) | 1713 | void fc_rport_terminate_io(struct fc_rport *rport) |
1577 | { | 1714 | { |
1578 | struct fc_rport_libfc_priv *rp = rport->dd_data; | 1715 | struct fc_rport_libfc_priv *rpriv = rport->dd_data; |
1579 | struct fc_lport *lport = rp->local_port; | 1716 | struct fc_lport *lport = rpriv->local_port; |
1580 | 1717 | ||
1581 | lport->tt.exch_mgr_reset(lport, 0, rport->port_id); | 1718 | lport->tt.exch_mgr_reset(lport, 0, rport->port_id); |
1582 | lport->tt.exch_mgr_reset(lport, rport->port_id, 0); | 1719 | lport->tt.exch_mgr_reset(lport, rport->port_id, 0); |