aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libfc/fc_rport.c75
-rw-r--r--include/scsi/libfc.h5
2 files changed, 33 insertions, 47 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index df85e19079f..d385efc68c1 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 7495c0ba67e..db54c4a2d14 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*/
109enum fc_rport_state { 108enum 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