diff options
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 75 | ||||
-rw-r--r-- | include/scsi/libfc.h | 5 |
2 files changed, 33 insertions, 47 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index df85e19079fb..d385efc68c15 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -89,7 +89,6 @@ static const char *fc_rport_state_names[] = { | |||
89 | [RPORT_ST_LOGO] = "LOGO", | 89 | [RPORT_ST_LOGO] = "LOGO", |
90 | [RPORT_ST_ADISC] = "ADISC", | 90 | [RPORT_ST_ADISC] = "ADISC", |
91 | [RPORT_ST_DELETE] = "Delete", | 91 | [RPORT_ST_DELETE] = "Delete", |
92 | [RPORT_ST_RESTART] = "Restart", | ||
93 | }; | 92 | }; |
94 | 93 | ||
95 | /** | 94 | /** |
@@ -246,7 +245,6 @@ static void fc_rport_work(struct work_struct *work) | |||
246 | struct fc_rport_operations *rport_ops; | 245 | struct fc_rport_operations *rport_ops; |
247 | struct fc_rport_identifiers ids; | 246 | struct fc_rport_identifiers ids; |
248 | struct fc_rport *rport; | 247 | struct fc_rport *rport; |
249 | int restart = 0; | ||
250 | 248 | ||
251 | mutex_lock(&rdata->rp_mutex); | 249 | mutex_lock(&rdata->rp_mutex); |
252 | event = rdata->event; | 250 | event = rdata->event; |
@@ -298,24 +296,6 @@ static void fc_rport_work(struct work_struct *work) | |||
298 | port_id = rdata->ids.port_id; | 296 | port_id = rdata->ids.port_id; |
299 | mutex_unlock(&rdata->rp_mutex); | 297 | mutex_unlock(&rdata->rp_mutex); |
300 | 298 | ||
301 | if (port_id != FC_FID_DIR_SERV) { | ||
302 | /* | ||
303 | * We must drop rp_mutex before taking disc_mutex. | ||
304 | * Re-evaluate state to allow for restart. | ||
305 | * A transition to RESTART state must only happen | ||
306 | * while disc_mutex is held and rdata is on the list. | ||
307 | */ | ||
308 | mutex_lock(&lport->disc.disc_mutex); | ||
309 | mutex_lock(&rdata->rp_mutex); | ||
310 | if (rdata->rp_state == RPORT_ST_RESTART) | ||
311 | restart = 1; | ||
312 | else | ||
313 | list_del(&rdata->peers); | ||
314 | rdata->event = RPORT_EV_NONE; | ||
315 | mutex_unlock(&rdata->rp_mutex); | ||
316 | mutex_unlock(&lport->disc.disc_mutex); | ||
317 | } | ||
318 | |||
319 | if (rport_ops && rport_ops->event_callback) { | 299 | if (rport_ops && rport_ops->event_callback) { |
320 | FC_RPORT_DBG(rdata, "callback ev %d\n", event); | 300 | FC_RPORT_DBG(rdata, "callback ev %d\n", event); |
321 | rport_ops->event_callback(lport, rdata, event); | 301 | rport_ops->event_callback(lport, rdata, event); |
@@ -336,13 +316,34 @@ static void fc_rport_work(struct work_struct *work) | |||
336 | mutex_unlock(&rdata->rp_mutex); | 316 | mutex_unlock(&rdata->rp_mutex); |
337 | fc_remote_port_delete(rport); | 317 | fc_remote_port_delete(rport); |
338 | } | 318 | } |
339 | if (restart) { | 319 | |
340 | mutex_lock(&rdata->rp_mutex); | 320 | mutex_lock(&lport->disc.disc_mutex); |
341 | FC_RPORT_DBG(rdata, "work restart\n"); | 321 | mutex_lock(&rdata->rp_mutex); |
342 | fc_rport_enter_plogi(rdata); | 322 | if (rdata->rp_state == RPORT_ST_DELETE) { |
323 | if (port_id == FC_FID_DIR_SERV) { | ||
324 | rdata->event = RPORT_EV_NONE; | ||
325 | mutex_unlock(&rdata->rp_mutex); | ||
326 | } else if (rdata->flags & FC_RP_STARTED) { | ||
327 | rdata->event = RPORT_EV_NONE; | ||
328 | FC_RPORT_DBG(rdata, "work restart\n"); | ||
329 | fc_rport_enter_plogi(rdata); | ||
330 | mutex_unlock(&rdata->rp_mutex); | ||
331 | } else { | ||
332 | FC_RPORT_DBG(rdata, "work delete\n"); | ||
333 | list_del(&rdata->peers); | ||
334 | mutex_unlock(&rdata->rp_mutex); | ||
335 | kref_put(&rdata->kref, lport->tt.rport_destroy); | ||
336 | } | ||
337 | } else { | ||
338 | /* | ||
339 | * Re-open for events. Reissue READY event if ready. | ||
340 | */ | ||
341 | rdata->event = RPORT_EV_NONE; | ||
342 | if (rdata->rp_state == RPORT_ST_READY) | ||
343 | fc_rport_enter_ready(rdata); | ||
343 | mutex_unlock(&rdata->rp_mutex); | 344 | mutex_unlock(&rdata->rp_mutex); |
344 | } else | 345 | } |
345 | kref_put(&rdata->kref, lport->tt.rport_destroy); | 346 | mutex_unlock(&lport->disc.disc_mutex); |
346 | break; | 347 | break; |
347 | 348 | ||
348 | default: | 349 | default: |
@@ -367,16 +368,14 @@ int fc_rport_login(struct fc_rport_priv *rdata) | |||
367 | { | 368 | { |
368 | mutex_lock(&rdata->rp_mutex); | 369 | mutex_lock(&rdata->rp_mutex); |
369 | 370 | ||
371 | rdata->flags |= FC_RP_STARTED; | ||
370 | switch (rdata->rp_state) { | 372 | switch (rdata->rp_state) { |
371 | case RPORT_ST_READY: | 373 | case RPORT_ST_READY: |
372 | FC_RPORT_DBG(rdata, "ADISC port\n"); | 374 | FC_RPORT_DBG(rdata, "ADISC port\n"); |
373 | fc_rport_enter_adisc(rdata); | 375 | fc_rport_enter_adisc(rdata); |
374 | break; | 376 | break; |
375 | case RPORT_ST_RESTART: | ||
376 | break; | ||
377 | case RPORT_ST_DELETE: | 377 | case RPORT_ST_DELETE: |
378 | FC_RPORT_DBG(rdata, "Restart deleted port\n"); | 378 | FC_RPORT_DBG(rdata, "Restart deleted port\n"); |
379 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); | ||
380 | break; | 379 | break; |
381 | default: | 380 | default: |
382 | FC_RPORT_DBG(rdata, "Login to port\n"); | 381 | FC_RPORT_DBG(rdata, "Login to port\n"); |
@@ -431,15 +430,12 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) | |||
431 | 430 | ||
432 | FC_RPORT_DBG(rdata, "Remove port\n"); | 431 | FC_RPORT_DBG(rdata, "Remove port\n"); |
433 | 432 | ||
433 | rdata->flags &= ~FC_RP_STARTED; | ||
434 | if (rdata->rp_state == RPORT_ST_DELETE) { | 434 | if (rdata->rp_state == RPORT_ST_DELETE) { |
435 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); | 435 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); |
436 | goto out; | 436 | goto out; |
437 | } | 437 | } |
438 | 438 | fc_rport_enter_logo(rdata); | |
439 | if (rdata->rp_state == RPORT_ST_RESTART) | ||
440 | FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); | ||
441 | else | ||
442 | fc_rport_enter_logo(rdata); | ||
443 | 439 | ||
444 | /* | 440 | /* |
445 | * Change the state to Delete so that we discard | 441 | * Change the state to Delete so that we discard |
@@ -503,7 +499,6 @@ static void fc_rport_timeout(struct work_struct *work) | |||
503 | case RPORT_ST_READY: | 499 | case RPORT_ST_READY: |
504 | case RPORT_ST_INIT: | 500 | case RPORT_ST_INIT: |
505 | case RPORT_ST_DELETE: | 501 | case RPORT_ST_DELETE: |
506 | case RPORT_ST_RESTART: | ||
507 | break; | 502 | break; |
508 | } | 503 | } |
509 | 504 | ||
@@ -527,6 +522,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
527 | switch (rdata->rp_state) { | 522 | switch (rdata->rp_state) { |
528 | case RPORT_ST_PLOGI: | 523 | case RPORT_ST_PLOGI: |
529 | case RPORT_ST_LOGO: | 524 | case RPORT_ST_LOGO: |
525 | rdata->flags &= ~FC_RP_STARTED; | ||
530 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); | 526 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); |
531 | break; | 527 | break; |
532 | case RPORT_ST_RTV: | 528 | case RPORT_ST_RTV: |
@@ -537,7 +533,6 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
537 | fc_rport_enter_logo(rdata); | 533 | fc_rport_enter_logo(rdata); |
538 | break; | 534 | break; |
539 | case RPORT_ST_DELETE: | 535 | case RPORT_ST_DELETE: |
540 | case RPORT_ST_RESTART: | ||
541 | case RPORT_ST_READY: | 536 | case RPORT_ST_READY: |
542 | case RPORT_ST_INIT: | 537 | case RPORT_ST_INIT: |
543 | break; | 538 | break; |
@@ -1392,7 +1387,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1392 | break; | 1387 | break; |
1393 | case RPORT_ST_DELETE: | 1388 | case RPORT_ST_DELETE: |
1394 | case RPORT_ST_LOGO: | 1389 | case RPORT_ST_LOGO: |
1395 | case RPORT_ST_RESTART: | ||
1396 | FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", | 1390 | FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", |
1397 | fc_rport_state(rdata)); | 1391 | fc_rport_state(rdata)); |
1398 | mutex_unlock(&rdata->rp_mutex); | 1392 | mutex_unlock(&rdata->rp_mutex); |
@@ -1684,13 +1678,6 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1684 | fc_rport_state(rdata)); | 1678 | fc_rport_state(rdata)); |
1685 | 1679 | ||
1686 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1680 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); |
1687 | |||
1688 | /* | ||
1689 | * If the remote port was created due to discovery, set state | ||
1690 | * to log back in. It may have seen a stale RSCN about us. | ||
1691 | */ | ||
1692 | if (rdata->disc_id) | ||
1693 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); | ||
1694 | mutex_unlock(&rdata->rp_mutex); | 1681 | mutex_unlock(&rdata->rp_mutex); |
1695 | } else | 1682 | } else |
1696 | FC_RPORT_ID_DBG(lport, sid, | 1683 | FC_RPORT_ID_DBG(lport, sid, |
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7495c0ba67ee..db54c4a2d14b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h | |||
@@ -104,7 +104,6 @@ enum fc_disc_event { | |||
104 | * @RPORT_ST_LOGO: Remote port logout (LOGO) sent | 104 | * @RPORT_ST_LOGO: Remote port logout (LOGO) sent |
105 | * @RPORT_ST_ADISC: Discover Address sent | 105 | * @RPORT_ST_ADISC: Discover Address sent |
106 | * @RPORT_ST_DELETE: Remote port being deleted | 106 | * @RPORT_ST_DELETE: Remote port being deleted |
107 | * @RPORT_ST_RESTART: Remote port being deleted and will restart | ||
108 | */ | 107 | */ |
109 | enum fc_rport_state { | 108 | enum fc_rport_state { |
110 | RPORT_ST_INIT, | 109 | RPORT_ST_INIT, |
@@ -115,7 +114,6 @@ enum fc_rport_state { | |||
115 | RPORT_ST_LOGO, | 114 | RPORT_ST_LOGO, |
116 | RPORT_ST_ADISC, | 115 | RPORT_ST_ADISC, |
117 | RPORT_ST_DELETE, | 116 | RPORT_ST_DELETE, |
118 | RPORT_ST_RESTART, | ||
119 | }; | 117 | }; |
120 | 118 | ||
121 | /** | 119 | /** |
@@ -173,6 +171,7 @@ struct fc_rport_libfc_priv { | |||
173 | u16 flags; | 171 | u16 flags; |
174 | #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) | 172 | #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) |
175 | #define FC_RP_FLAGS_RETRY (1 << 1) | 173 | #define FC_RP_FLAGS_RETRY (1 << 1) |
174 | #define FC_RP_STARTED (1 << 2) | ||
176 | unsigned int e_d_tov; | 175 | unsigned int e_d_tov; |
177 | unsigned int r_a_tov; | 176 | unsigned int r_a_tov; |
178 | }; | 177 | }; |
@@ -185,7 +184,7 @@ struct fc_rport_libfc_priv { | |||
185 | * @rp_state: Enumeration that tracks progress of PLOGI, PRLI, | 184 | * @rp_state: Enumeration that tracks progress of PLOGI, PRLI, |
186 | * and RTV exchanges | 185 | * and RTV exchanges |
187 | * @ids: The remote port identifiers and roles | 186 | * @ids: The remote port identifiers and roles |
188 | * @flags: REC and RETRY supported flags | 187 | * @flags: STARTED, REC and RETRY_SUPPORTED flags |
189 | * @max_seq: Maximum number of concurrent sequences | 188 | * @max_seq: Maximum number of concurrent sequences |
190 | * @disc_id: The discovery identifier | 189 | * @disc_id: The discovery identifier |
191 | * @maxframe_size: The maximum frame size | 190 | * @maxframe_size: The maximum frame size |