diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-18 01:37:44 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-18 01:37:49 -0400 |
commit | dc3f81b129b5439ba7bac265bbc6a51a39275dae (patch) | |
tree | 216030731d911249496d2e97206cd61431e31c89 /drivers/scsi/libfc/fc_rport.c | |
parent | d2517a49d55536b38c7a87e5289550cfedaa4dcc (diff) | |
parent | 1406de8e11eb043681297adf86d6892ff8efc27a (diff) |
Merge commit 'v2.6.30-rc6' into perfcounters/core
Merge reason: this branch was on an -rc4 base, merge it up to -rc6
to get the latest upstream fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 0472bb73221e..747d73c5c8af 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -267,6 +267,10 @@ static void fc_rport_work(struct work_struct *work) | |||
267 | "(%6x).\n", ids.port_id); | 267 | "(%6x).\n", ids.port_id); |
268 | event = RPORT_EV_FAILED; | 268 | event = RPORT_EV_FAILED; |
269 | } | 269 | } |
270 | if (rport->port_id != FC_FID_DIR_SERV) | ||
271 | if (rport_ops->event_callback) | ||
272 | rport_ops->event_callback(lport, rport, | ||
273 | RPORT_EV_FAILED); | ||
270 | put_device(&rport->dev); | 274 | put_device(&rport->dev); |
271 | rport = new_rport; | 275 | rport = new_rport; |
272 | rdata = new_rport->dd_data; | 276 | rdata = new_rport->dd_data; |
@@ -325,11 +329,20 @@ int fc_rport_login(struct fc_rport *rport) | |||
325 | int fc_rport_logoff(struct fc_rport *rport) | 329 | int fc_rport_logoff(struct fc_rport *rport) |
326 | { | 330 | { |
327 | struct fc_rport_libfc_priv *rdata = rport->dd_data; | 331 | struct fc_rport_libfc_priv *rdata = rport->dd_data; |
332 | struct fc_lport *lport = rdata->local_port; | ||
328 | 333 | ||
329 | mutex_lock(&rdata->rp_mutex); | 334 | mutex_lock(&rdata->rp_mutex); |
330 | 335 | ||
331 | FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id); | 336 | FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id); |
332 | 337 | ||
338 | if (rdata->rp_state == RPORT_ST_NONE) { | ||
339 | FC_DEBUG_RPORT("(%6x): Port (%6x) in NONE state," | ||
340 | " not removing", fc_host_port_id(lport->host), | ||
341 | rport->port_id); | ||
342 | mutex_unlock(&rdata->rp_mutex); | ||
343 | goto out; | ||
344 | } | ||
345 | |||
333 | fc_rport_enter_logo(rport); | 346 | fc_rport_enter_logo(rport); |
334 | 347 | ||
335 | /* | 348 | /* |
@@ -349,6 +362,7 @@ int fc_rport_logoff(struct fc_rport *rport) | |||
349 | 362 | ||
350 | mutex_unlock(&rdata->rp_mutex); | 363 | mutex_unlock(&rdata->rp_mutex); |
351 | 364 | ||
365 | out: | ||
352 | return 0; | 366 | return 0; |
353 | } | 367 | } |
354 | 368 | ||
@@ -430,6 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) | |||
430 | case RPORT_ST_PRLI: | 444 | case RPORT_ST_PRLI: |
431 | case RPORT_ST_LOGO: | 445 | case RPORT_ST_LOGO: |
432 | rdata->event = RPORT_EV_FAILED; | 446 | rdata->event = RPORT_EV_FAILED; |
447 | fc_rport_state_enter(rport, RPORT_ST_NONE); | ||
433 | queue_work(rport_event_queue, | 448 | queue_work(rport_event_queue, |
434 | &rdata->event_work); | 449 | &rdata->event_work); |
435 | break; | 450 | break; |
@@ -494,7 +509,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
494 | struct fc_rport *rport = rp_arg; | 509 | struct fc_rport *rport = rp_arg; |
495 | struct fc_rport_libfc_priv *rdata = rport->dd_data; | 510 | struct fc_rport_libfc_priv *rdata = rport->dd_data; |
496 | struct fc_lport *lport = rdata->local_port; | 511 | struct fc_lport *lport = rdata->local_port; |
497 | struct fc_els_flogi *plp; | 512 | struct fc_els_flogi *plp = NULL; |
498 | unsigned int tov; | 513 | unsigned int tov; |
499 | u16 csp_seq; | 514 | u16 csp_seq; |
500 | u16 cssp_seq; | 515 | u16 cssp_seq; |
@@ -505,17 +520,19 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
505 | FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", | 520 | FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", |
506 | rport->port_id); | 521 | rport->port_id); |
507 | 522 | ||
508 | if (IS_ERR(fp)) { | ||
509 | fc_rport_error_retry(rport, fp); | ||
510 | goto err; | ||
511 | } | ||
512 | |||
513 | if (rdata->rp_state != RPORT_ST_PLOGI) { | 523 | if (rdata->rp_state != RPORT_ST_PLOGI) { |
514 | FC_DBG("Received a PLOGI response, but in state %s\n", | 524 | FC_DBG("Received a PLOGI response, but in state %s\n", |
515 | fc_rport_state(rport)); | 525 | fc_rport_state(rport)); |
526 | if (IS_ERR(fp)) | ||
527 | goto err; | ||
516 | goto out; | 528 | goto out; |
517 | } | 529 | } |
518 | 530 | ||
531 | if (IS_ERR(fp)) { | ||
532 | fc_rport_error_retry(rport, fp); | ||
533 | goto err; | ||
534 | } | ||
535 | |||
519 | op = fc_frame_payload_op(fp); | 536 | op = fc_frame_payload_op(fp); |
520 | if (op == ELS_LS_ACC && | 537 | if (op == ELS_LS_ACC && |
521 | (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { | 538 | (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { |
@@ -614,17 +631,19 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
614 | FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", | 631 | FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", |
615 | rport->port_id); | 632 | rport->port_id); |
616 | 633 | ||
617 | if (IS_ERR(fp)) { | ||
618 | fc_rport_error_retry(rport, fp); | ||
619 | goto err; | ||
620 | } | ||
621 | |||
622 | if (rdata->rp_state != RPORT_ST_PRLI) { | 634 | if (rdata->rp_state != RPORT_ST_PRLI) { |
623 | FC_DBG("Received a PRLI response, but in state %s\n", | 635 | FC_DBG("Received a PRLI response, but in state %s\n", |
624 | fc_rport_state(rport)); | 636 | fc_rport_state(rport)); |
637 | if (IS_ERR(fp)) | ||
638 | goto err; | ||
625 | goto out; | 639 | goto out; |
626 | } | 640 | } |
627 | 641 | ||
642 | if (IS_ERR(fp)) { | ||
643 | fc_rport_error_retry(rport, fp); | ||
644 | goto err; | ||
645 | } | ||
646 | |||
628 | op = fc_frame_payload_op(fp); | 647 | op = fc_frame_payload_op(fp); |
629 | if (op == ELS_LS_ACC) { | 648 | if (op == ELS_LS_ACC) { |
630 | pp = fc_frame_payload_get(fp, sizeof(*pp)); | 649 | pp = fc_frame_payload_get(fp, sizeof(*pp)); |
@@ -646,6 +665,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
646 | } else { | 665 | } else { |
647 | FC_DBG("Bad ELS response\n"); | 666 | FC_DBG("Bad ELS response\n"); |
648 | rdata->event = RPORT_EV_FAILED; | 667 | rdata->event = RPORT_EV_FAILED; |
668 | fc_rport_state_enter(rport, RPORT_ST_NONE); | ||
649 | queue_work(rport_event_queue, &rdata->event_work); | 669 | queue_work(rport_event_queue, &rdata->event_work); |
650 | } | 670 | } |
651 | 671 | ||
@@ -678,23 +698,26 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
678 | FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n", | 698 | FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n", |
679 | rport->port_id); | 699 | rport->port_id); |
680 | 700 | ||
681 | if (IS_ERR(fp)) { | ||
682 | fc_rport_error_retry(rport, fp); | ||
683 | goto err; | ||
684 | } | ||
685 | |||
686 | if (rdata->rp_state != RPORT_ST_LOGO) { | 701 | if (rdata->rp_state != RPORT_ST_LOGO) { |
687 | FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n", | 702 | FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n", |
688 | fc_rport_state(rport)); | 703 | fc_rport_state(rport)); |
704 | if (IS_ERR(fp)) | ||
705 | goto err; | ||
689 | goto out; | 706 | goto out; |
690 | } | 707 | } |
691 | 708 | ||
709 | if (IS_ERR(fp)) { | ||
710 | fc_rport_error_retry(rport, fp); | ||
711 | goto err; | ||
712 | } | ||
713 | |||
692 | op = fc_frame_payload_op(fp); | 714 | op = fc_frame_payload_op(fp); |
693 | if (op == ELS_LS_ACC) { | 715 | if (op == ELS_LS_ACC) { |
694 | fc_rport_enter_rtv(rport); | 716 | fc_rport_enter_rtv(rport); |
695 | } else { | 717 | } else { |
696 | FC_DBG("Bad ELS response\n"); | 718 | FC_DBG("Bad ELS response\n"); |
697 | rdata->event = RPORT_EV_LOGO; | 719 | rdata->event = RPORT_EV_LOGO; |
720 | fc_rport_state_enter(rport, RPORT_ST_NONE); | ||
698 | queue_work(rport_event_queue, &rdata->event_work); | 721 | queue_work(rport_event_queue, &rdata->event_work); |
699 | } | 722 | } |
700 | 723 | ||
@@ -764,17 +787,19 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
764 | FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", | 787 | FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", |
765 | rport->port_id); | 788 | rport->port_id); |
766 | 789 | ||
767 | if (IS_ERR(fp)) { | ||
768 | fc_rport_error(rport, fp); | ||
769 | goto err; | ||
770 | } | ||
771 | |||
772 | if (rdata->rp_state != RPORT_ST_RTV) { | 790 | if (rdata->rp_state != RPORT_ST_RTV) { |
773 | FC_DBG("Received a RTV response, but in state %s\n", | 791 | FC_DBG("Received a RTV response, but in state %s\n", |
774 | fc_rport_state(rport)); | 792 | fc_rport_state(rport)); |
793 | if (IS_ERR(fp)) | ||
794 | goto err; | ||
775 | goto out; | 795 | goto out; |
776 | } | 796 | } |
777 | 797 | ||
798 | if (IS_ERR(fp)) { | ||
799 | fc_rport_error(rport, fp); | ||
800 | goto err; | ||
801 | } | ||
802 | |||
778 | op = fc_frame_payload_op(fp); | 803 | op = fc_frame_payload_op(fp); |
779 | if (op == ELS_LS_ACC) { | 804 | if (op == ELS_LS_ACC) { |
780 | struct fc_els_rtv_acc *rtv; | 805 | struct fc_els_rtv_acc *rtv; |
@@ -1007,6 +1032,8 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, | |||
1007 | default: | 1032 | default: |
1008 | FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected " | 1033 | FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected " |
1009 | "state %d\n", sid, rdata->rp_state); | 1034 | "state %d\n", sid, rdata->rp_state); |
1035 | fc_frame_free(fp); | ||
1036 | return; | ||
1010 | break; | 1037 | break; |
1011 | } | 1038 | } |
1012 | 1039 | ||
@@ -1098,6 +1125,8 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, | |||
1098 | reason = ELS_RJT_NONE; | 1125 | reason = ELS_RJT_NONE; |
1099 | break; | 1126 | break; |
1100 | default: | 1127 | default: |
1128 | fc_frame_free(rx_fp); | ||
1129 | return; | ||
1101 | break; | 1130 | break; |
1102 | } | 1131 | } |
1103 | len = fr_len(rx_fp) - sizeof(*fh); | 1132 | len = fr_len(rx_fp) - sizeof(*fh); |
@@ -1227,6 +1256,11 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, | |||
1227 | "while in state %s\n", ntoh24(fh->fh_s_id), | 1256 | "while in state %s\n", ntoh24(fh->fh_s_id), |
1228 | fc_rport_state(rport)); | 1257 | fc_rport_state(rport)); |
1229 | 1258 | ||
1259 | if (rdata->rp_state == RPORT_ST_NONE) { | ||
1260 | fc_frame_free(fp); | ||
1261 | return; | ||
1262 | } | ||
1263 | |||
1230 | rjt_data.fp = NULL; | 1264 | rjt_data.fp = NULL; |
1231 | rjt_data.reason = ELS_RJT_UNAB; | 1265 | rjt_data.reason = ELS_RJT_UNAB; |
1232 | rjt_data.explan = ELS_EXPL_NONE; | 1266 | rjt_data.explan = ELS_EXPL_NONE; |
@@ -1256,7 +1290,13 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp, | |||
1256 | "while in state %s\n", ntoh24(fh->fh_s_id), | 1290 | "while in state %s\n", ntoh24(fh->fh_s_id), |
1257 | fc_rport_state(rport)); | 1291 | fc_rport_state(rport)); |
1258 | 1292 | ||
1293 | if (rdata->rp_state == RPORT_ST_NONE) { | ||
1294 | fc_frame_free(fp); | ||
1295 | return; | ||
1296 | } | ||
1297 | |||
1259 | rdata->event = RPORT_EV_LOGO; | 1298 | rdata->event = RPORT_EV_LOGO; |
1299 | fc_rport_state_enter(rport, RPORT_ST_NONE); | ||
1260 | queue_work(rport_event_queue, &rdata->event_work); | 1300 | queue_work(rport_event_queue, &rdata->event_work); |
1261 | 1301 | ||
1262 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 1302 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); |