diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_lport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 210 |
1 files changed, 98 insertions, 112 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 79c9e3ccd341..6eb334a8a7fa 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -375,41 +375,36 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) | |||
375 | 375 | ||
376 | /** | 376 | /** |
377 | * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. | 377 | * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. |
378 | * @sp: The sequence in the RLIR exchange | ||
379 | * @fp: The RLIR request frame | ||
380 | * @lport: Fibre Channel local port recieving the RLIR | 378 | * @lport: Fibre Channel local port recieving the RLIR |
379 | * @fp: The RLIR request frame | ||
381 | * | 380 | * |
382 | * Locking Note: The lport lock is expected to be held before calling | 381 | * Locking Note: The lport lock is expected to be held before calling |
383 | * this function. | 382 | * this function. |
384 | */ | 383 | */ |
385 | static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, | 384 | static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) |
386 | struct fc_lport *lport) | ||
387 | { | 385 | { |
388 | FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", | 386 | FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", |
389 | fc_lport_state(lport)); | 387 | fc_lport_state(lport)); |
390 | 388 | ||
391 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 389 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
392 | fc_frame_free(fp); | 390 | fc_frame_free(fp); |
393 | } | 391 | } |
394 | 392 | ||
395 | /** | 393 | /** |
396 | * fc_lport_recv_echo_req() - Handle received ECHO request | 394 | * fc_lport_recv_echo_req() - Handle received ECHO request |
397 | * @sp: The sequence in the ECHO exchange | ||
398 | * @fp: ECHO request frame | ||
399 | * @lport: The local port recieving the ECHO | 395 | * @lport: The local port recieving the ECHO |
396 | * @fp: ECHO request frame | ||
400 | * | 397 | * |
401 | * Locking Note: The lport lock is expected to be held before calling | 398 | * Locking Note: The lport lock is expected to be held before calling |
402 | * this function. | 399 | * this function. |
403 | */ | 400 | */ |
404 | static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | 401 | static void fc_lport_recv_echo_req(struct fc_lport *lport, |
405 | struct fc_lport *lport) | 402 | struct fc_frame *in_fp) |
406 | { | 403 | { |
407 | struct fc_frame *fp; | 404 | struct fc_frame *fp; |
408 | struct fc_exch *ep = fc_seq_exch(sp); | ||
409 | unsigned int len; | 405 | unsigned int len; |
410 | void *pp; | 406 | void *pp; |
411 | void *dp; | 407 | void *dp; |
412 | u32 f_ctl; | ||
413 | 408 | ||
414 | FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", | 409 | FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", |
415 | fc_lport_state(lport)); | 410 | fc_lport_state(lport)); |
@@ -425,29 +420,24 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
425 | dp = fc_frame_payload_get(fp, len); | 420 | dp = fc_frame_payload_get(fp, len); |
426 | memcpy(dp, pp, len); | 421 | memcpy(dp, pp, len); |
427 | *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); | 422 | *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); |
428 | sp = lport->tt.seq_start_next(sp); | 423 | fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); |
429 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 424 | lport->tt.frame_send(lport, fp); |
430 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
431 | FC_TYPE_ELS, f_ctl, 0); | ||
432 | lport->tt.seq_send(lport, sp, fp); | ||
433 | } | 425 | } |
434 | fc_frame_free(in_fp); | 426 | fc_frame_free(in_fp); |
435 | } | 427 | } |
436 | 428 | ||
437 | /** | 429 | /** |
438 | * fc_lport_recv_rnid_req() - Handle received Request Node ID data request | 430 | * fc_lport_recv_rnid_req() - Handle received Request Node ID data request |
439 | * @sp: The sequence in the RNID exchange | ||
440 | * @fp: The RNID request frame | ||
441 | * @lport: The local port recieving the RNID | 431 | * @lport: The local port recieving the RNID |
432 | * @fp: The RNID request frame | ||
442 | * | 433 | * |
443 | * Locking Note: The lport lock is expected to be held before calling | 434 | * Locking Note: The lport lock is expected to be held before calling |
444 | * this function. | 435 | * this function. |
445 | */ | 436 | */ |
446 | static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | 437 | static void fc_lport_recv_rnid_req(struct fc_lport *lport, |
447 | struct fc_lport *lport) | 438 | struct fc_frame *in_fp) |
448 | { | 439 | { |
449 | struct fc_frame *fp; | 440 | struct fc_frame *fp; |
450 | struct fc_exch *ep = fc_seq_exch(sp); | ||
451 | struct fc_els_rnid *req; | 441 | struct fc_els_rnid *req; |
452 | struct { | 442 | struct { |
453 | struct fc_els_rnid_resp rnid; | 443 | struct fc_els_rnid_resp rnid; |
@@ -457,17 +447,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
457 | struct fc_seq_els_data rjt_data; | 447 | struct fc_seq_els_data rjt_data; |
458 | u8 fmt; | 448 | u8 fmt; |
459 | size_t len; | 449 | size_t len; |
460 | u32 f_ctl; | ||
461 | 450 | ||
462 | FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", | 451 | FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", |
463 | fc_lport_state(lport)); | 452 | fc_lport_state(lport)); |
464 | 453 | ||
465 | req = fc_frame_payload_get(in_fp, sizeof(*req)); | 454 | req = fc_frame_payload_get(in_fp, sizeof(*req)); |
466 | if (!req) { | 455 | if (!req) { |
467 | rjt_data.fp = NULL; | ||
468 | rjt_data.reason = ELS_RJT_LOGIC; | 456 | rjt_data.reason = ELS_RJT_LOGIC; |
469 | rjt_data.explan = ELS_EXPL_NONE; | 457 | rjt_data.explan = ELS_EXPL_NONE; |
470 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 458 | lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); |
471 | } else { | 459 | } else { |
472 | fmt = req->rnid_fmt; | 460 | fmt = req->rnid_fmt; |
473 | len = sizeof(*rp); | 461 | len = sizeof(*rp); |
@@ -490,12 +478,8 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
490 | memcpy(&rp->gen, &lport->rnid_gen, | 478 | memcpy(&rp->gen, &lport->rnid_gen, |
491 | sizeof(rp->gen)); | 479 | sizeof(rp->gen)); |
492 | } | 480 | } |
493 | sp = lport->tt.seq_start_next(sp); | 481 | fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); |
494 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | 482 | lport->tt.frame_send(lport, fp); |
495 | f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | ||
496 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
497 | FC_TYPE_ELS, f_ctl, 0); | ||
498 | lport->tt.seq_send(lport, sp, fp); | ||
499 | } | 483 | } |
500 | } | 484 | } |
501 | fc_frame_free(in_fp); | 485 | fc_frame_free(in_fp); |
@@ -503,17 +487,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
503 | 487 | ||
504 | /** | 488 | /** |
505 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request | 489 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request |
506 | * @sp: The sequence in the LOGO exchange | ||
507 | * @fp: The LOGO request frame | ||
508 | * @lport: The local port recieving the LOGO | 490 | * @lport: The local port recieving the LOGO |
491 | * @fp: The LOGO request frame | ||
509 | * | 492 | * |
510 | * Locking Note: The lport lock is exected to be held before calling | 493 | * Locking Note: The lport lock is exected to be held before calling |
511 | * this function. | 494 | * this function. |
512 | */ | 495 | */ |
513 | static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, | 496 | static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) |
514 | struct fc_lport *lport) | ||
515 | { | 497 | { |
516 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 498 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
517 | fc_lport_enter_reset(lport); | 499 | fc_lport_enter_reset(lport); |
518 | fc_frame_free(fp); | 500 | fc_frame_free(fp); |
519 | } | 501 | } |
@@ -755,10 +737,37 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id, | |||
755 | } | 737 | } |
756 | 738 | ||
757 | /** | 739 | /** |
740 | * fc_lport_set_port_id() - set the local port Port ID for point-to-multipoint | ||
741 | * @lport: The local port which will have its Port ID set. | ||
742 | * @port_id: The new port ID. | ||
743 | * | ||
744 | * Called by the lower-level driver when transport sets the local port_id. | ||
745 | * This is used in VN_port to VN_port mode for FCoE, and causes FLOGI and | ||
746 | * discovery to be skipped. | ||
747 | */ | ||
748 | void fc_lport_set_local_id(struct fc_lport *lport, u32 port_id) | ||
749 | { | ||
750 | mutex_lock(&lport->lp_mutex); | ||
751 | |||
752 | fc_lport_set_port_id(lport, port_id, NULL); | ||
753 | |||
754 | switch (lport->state) { | ||
755 | case LPORT_ST_RESET: | ||
756 | case LPORT_ST_FLOGI: | ||
757 | if (port_id) | ||
758 | fc_lport_enter_ready(lport); | ||
759 | break; | ||
760 | default: | ||
761 | break; | ||
762 | } | ||
763 | mutex_unlock(&lport->lp_mutex); | ||
764 | } | ||
765 | EXPORT_SYMBOL(fc_lport_set_local_id); | ||
766 | |||
767 | /** | ||
758 | * fc_lport_recv_flogi_req() - Receive a FLOGI request | 768 | * fc_lport_recv_flogi_req() - Receive a FLOGI request |
759 | * @sp_in: The sequence the FLOGI is on | ||
760 | * @rx_fp: The FLOGI frame | ||
761 | * @lport: The local port that recieved the request | 769 | * @lport: The local port that recieved the request |
770 | * @rx_fp: The FLOGI frame | ||
762 | * | 771 | * |
763 | * A received FLOGI request indicates a point-to-point connection. | 772 | * A received FLOGI request indicates a point-to-point connection. |
764 | * Accept it with the common service parameters indicating our N port. | 773 | * Accept it with the common service parameters indicating our N port. |
@@ -767,26 +776,21 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id, | |||
767 | * Locking Note: The lport lock is expected to be held before calling | 776 | * Locking Note: The lport lock is expected to be held before calling |
768 | * this function. | 777 | * this function. |
769 | */ | 778 | */ |
770 | static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | 779 | static void fc_lport_recv_flogi_req(struct fc_lport *lport, |
771 | struct fc_frame *rx_fp, | 780 | struct fc_frame *rx_fp) |
772 | struct fc_lport *lport) | ||
773 | { | 781 | { |
774 | struct fc_frame *fp; | 782 | struct fc_frame *fp; |
775 | struct fc_frame_header *fh; | 783 | struct fc_frame_header *fh; |
776 | struct fc_seq *sp; | ||
777 | struct fc_exch *ep; | ||
778 | struct fc_els_flogi *flp; | 784 | struct fc_els_flogi *flp; |
779 | struct fc_els_flogi *new_flp; | 785 | struct fc_els_flogi *new_flp; |
780 | u64 remote_wwpn; | 786 | u64 remote_wwpn; |
781 | u32 remote_fid; | 787 | u32 remote_fid; |
782 | u32 local_fid; | 788 | u32 local_fid; |
783 | u32 f_ctl; | ||
784 | 789 | ||
785 | FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", | 790 | FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", |
786 | fc_lport_state(lport)); | 791 | fc_lport_state(lport)); |
787 | 792 | ||
788 | fh = fc_frame_header_get(rx_fp); | 793 | remote_fid = fc_frame_sid(rx_fp); |
789 | remote_fid = ntoh24(fh->fh_s_id); | ||
790 | flp = fc_frame_payload_get(rx_fp, sizeof(*flp)); | 794 | flp = fc_frame_payload_get(rx_fp, sizeof(*flp)); |
791 | if (!flp) | 795 | if (!flp) |
792 | goto out; | 796 | goto out; |
@@ -817,7 +821,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
817 | 821 | ||
818 | fp = fc_frame_alloc(lport, sizeof(*flp)); | 822 | fp = fc_frame_alloc(lport, sizeof(*flp)); |
819 | if (fp) { | 823 | if (fp) { |
820 | sp = lport->tt.seq_start_next(fr_seq(rx_fp)); | ||
821 | new_flp = fc_frame_payload_get(fp, sizeof(*flp)); | 824 | new_flp = fc_frame_payload_get(fp, sizeof(*flp)); |
822 | fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI); | 825 | fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI); |
823 | new_flp->fl_cmd = (u8) ELS_LS_ACC; | 826 | new_flp->fl_cmd = (u8) ELS_LS_ACC; |
@@ -826,27 +829,24 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
826 | * Send the response. If this fails, the originator should | 829 | * Send the response. If this fails, the originator should |
827 | * repeat the sequence. | 830 | * repeat the sequence. |
828 | */ | 831 | */ |
829 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 832 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
830 | ep = fc_seq_exch(sp); | 833 | fh = fc_frame_header_get(fp); |
831 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, remote_fid, local_fid, | 834 | hton24(fh->fh_s_id, local_fid); |
832 | FC_TYPE_ELS, f_ctl, 0); | 835 | hton24(fh->fh_d_id, remote_fid); |
833 | lport->tt.seq_send(lport, sp, fp); | 836 | lport->tt.frame_send(lport, fp); |
834 | 837 | ||
835 | } else { | 838 | } else { |
836 | fc_lport_error(lport, fp); | 839 | fc_lport_error(lport, fp); |
837 | } | 840 | } |
838 | fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, | 841 | fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, |
839 | get_unaligned_be64(&flp->fl_wwnn)); | 842 | get_unaligned_be64(&flp->fl_wwnn)); |
840 | |||
841 | out: | 843 | out: |
842 | sp = fr_seq(rx_fp); | ||
843 | fc_frame_free(rx_fp); | 844 | fc_frame_free(rx_fp); |
844 | } | 845 | } |
845 | 846 | ||
846 | /** | 847 | /** |
847 | * fc_lport_recv_req() - The generic lport request handler | 848 | * fc_lport_recv_req() - The generic lport request handler |
848 | * @lport: The local port that received the request | 849 | * @lport: The local port that received the request |
849 | * @sp: The sequence the request is on | ||
850 | * @fp: The request frame | 850 | * @fp: The request frame |
851 | * | 851 | * |
852 | * This function will see if the lport handles the request or | 852 | * This function will see if the lport handles the request or |
@@ -855,11 +855,10 @@ out: | |||
855 | * Locking Note: This function should not be called with the lport | 855 | * Locking Note: This function should not be called with the lport |
856 | * lock held becuase it will grab the lock. | 856 | * lock held becuase it will grab the lock. |
857 | */ | 857 | */ |
858 | static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | 858 | static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) |
859 | struct fc_frame *fp) | ||
860 | { | 859 | { |
861 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 860 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
862 | void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); | 861 | void (*recv)(struct fc_lport *, struct fc_frame *); |
863 | 862 | ||
864 | mutex_lock(&lport->lp_mutex); | 863 | mutex_lock(&lport->lp_mutex); |
865 | 864 | ||
@@ -878,11 +877,11 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | |||
878 | recv = lport->tt.rport_recv_req; | 877 | recv = lport->tt.rport_recv_req; |
879 | switch (fc_frame_payload_op(fp)) { | 878 | switch (fc_frame_payload_op(fp)) { |
880 | case ELS_FLOGI: | 879 | case ELS_FLOGI: |
881 | recv = fc_lport_recv_flogi_req; | 880 | if (!lport->point_to_multipoint) |
881 | recv = fc_lport_recv_flogi_req; | ||
882 | break; | 882 | break; |
883 | case ELS_LOGO: | 883 | case ELS_LOGO: |
884 | fh = fc_frame_header_get(fp); | 884 | if (fc_frame_sid(fp) == FC_FID_FLOGI) |
885 | if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) | ||
886 | recv = fc_lport_recv_logo_req; | 885 | recv = fc_lport_recv_logo_req; |
887 | break; | 886 | break; |
888 | case ELS_RSCN: | 887 | case ELS_RSCN: |
@@ -899,19 +898,13 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | |||
899 | break; | 898 | break; |
900 | } | 899 | } |
901 | 900 | ||
902 | recv(sp, fp, lport); | 901 | recv(lport, fp); |
903 | } else { | 902 | } else { |
904 | FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", | 903 | FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", |
905 | fr_eof(fp)); | 904 | fr_eof(fp)); |
906 | fc_frame_free(fp); | 905 | fc_frame_free(fp); |
907 | } | 906 | } |
908 | mutex_unlock(&lport->lp_mutex); | 907 | mutex_unlock(&lport->lp_mutex); |
909 | |||
910 | /* | ||
911 | * The common exch_done for all request may not be good | ||
912 | * if any request requires longer hold on exhange. XXX | ||
913 | */ | ||
914 | lport->tt.exch_done(sp); | ||
915 | } | 908 | } |
916 | 909 | ||
917 | /** | 910 | /** |
@@ -954,7 +947,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport) | |||
954 | lport->tt.exch_mgr_reset(lport, 0, 0); | 947 | lport->tt.exch_mgr_reset(lport, 0, 0); |
955 | fc_host_fabric_name(lport->host) = 0; | 948 | fc_host_fabric_name(lport->host) = 0; |
956 | 949 | ||
957 | if (lport->port_id) | 950 | if (lport->port_id && (!lport->point_to_multipoint || !lport->link_up)) |
958 | fc_lport_set_port_id(lport, 0, NULL); | 951 | fc_lport_set_port_id(lport, 0, NULL); |
959 | } | 952 | } |
960 | 953 | ||
@@ -1019,38 +1012,24 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) | |||
1019 | PTR_ERR(fp), fc_lport_state(lport), | 1012 | PTR_ERR(fp), fc_lport_state(lport), |
1020 | lport->retry_count); | 1013 | lport->retry_count); |
1021 | 1014 | ||
1022 | if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { | 1015 | if (PTR_ERR(fp) == -FC_EX_CLOSED) |
1023 | /* | 1016 | return; |
1024 | * Memory allocation failure, or the exchange timed out. | 1017 | |
1025 | * Retry after delay | 1018 | /* |
1026 | */ | 1019 | * Memory allocation failure, or the exchange timed out |
1027 | if (lport->retry_count < lport->max_retry_count) { | 1020 | * or we received LS_RJT. |
1028 | lport->retry_count++; | 1021 | * Retry after delay |
1029 | if (!fp) | 1022 | */ |
1030 | delay = msecs_to_jiffies(500); | 1023 | if (lport->retry_count < lport->max_retry_count) { |
1031 | else | 1024 | lport->retry_count++; |
1032 | delay = msecs_to_jiffies(lport->e_d_tov); | 1025 | if (!fp) |
1033 | 1026 | delay = msecs_to_jiffies(500); | |
1034 | schedule_delayed_work(&lport->retry_work, delay); | 1027 | else |
1035 | } else { | 1028 | delay = msecs_to_jiffies(lport->e_d_tov); |
1036 | switch (lport->state) { | 1029 | |
1037 | case LPORT_ST_DISABLED: | 1030 | schedule_delayed_work(&lport->retry_work, delay); |
1038 | case LPORT_ST_READY: | 1031 | } else |
1039 | case LPORT_ST_RESET: | 1032 | fc_lport_enter_reset(lport); |
1040 | case LPORT_ST_RNN_ID: | ||
1041 | case LPORT_ST_RSNN_NN: | ||
1042 | case LPORT_ST_RSPN_ID: | ||
1043 | case LPORT_ST_RFT_ID: | ||
1044 | case LPORT_ST_RFF_ID: | ||
1045 | case LPORT_ST_SCR: | ||
1046 | case LPORT_ST_DNS: | ||
1047 | case LPORT_ST_FLOGI: | ||
1048 | case LPORT_ST_LOGO: | ||
1049 | fc_lport_enter_reset(lport); | ||
1050 | break; | ||
1051 | } | ||
1052 | } | ||
1053 | } | ||
1054 | } | 1033 | } |
1055 | 1034 | ||
1056 | /** | 1035 | /** |
@@ -1440,7 +1419,6 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1440 | void *lp_arg) | 1419 | void *lp_arg) |
1441 | { | 1420 | { |
1442 | struct fc_lport *lport = lp_arg; | 1421 | struct fc_lport *lport = lp_arg; |
1443 | struct fc_frame_header *fh; | ||
1444 | struct fc_els_flogi *flp; | 1422 | struct fc_els_flogi *flp; |
1445 | u32 did; | 1423 | u32 did; |
1446 | u16 csp_flags; | 1424 | u16 csp_flags; |
@@ -1468,9 +1446,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1468 | goto err; | 1446 | goto err; |
1469 | } | 1447 | } |
1470 | 1448 | ||
1471 | fh = fc_frame_header_get(fp); | 1449 | did = fc_frame_did(fp); |
1472 | did = ntoh24(fh->fh_d_id); | 1450 | |
1473 | if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { | 1451 | if (!did) { |
1452 | FC_LPORT_DBG(lport, "Bad FLOGI response\n"); | ||
1453 | goto out; | ||
1454 | } | ||
1455 | |||
1456 | if (fc_frame_payload_op(fp) == ELS_LS_ACC) { | ||
1474 | flp = fc_frame_payload_get(fp, sizeof(*flp)); | 1457 | flp = fc_frame_payload_get(fp, sizeof(*flp)); |
1475 | if (flp) { | 1458 | if (flp) { |
1476 | mfs = ntohs(flp->fl_csp.sp_bb_data) & | 1459 | mfs = ntohs(flp->fl_csp.sp_bb_data) & |
@@ -1495,7 +1478,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1495 | "Port (%6.6x) entered " | 1478 | "Port (%6.6x) entered " |
1496 | "point-to-point mode\n", | 1479 | "point-to-point mode\n", |
1497 | lport->host->host_no, did); | 1480 | lport->host->host_no, did); |
1498 | fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id), | 1481 | fc_lport_ptp_setup(lport, fc_frame_sid(fp), |
1499 | get_unaligned_be64( | 1482 | get_unaligned_be64( |
1500 | &flp->fl_wwpn), | 1483 | &flp->fl_wwpn), |
1501 | get_unaligned_be64( | 1484 | get_unaligned_be64( |
@@ -1509,9 +1492,8 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1509 | fc_lport_enter_dns(lport); | 1492 | fc_lport_enter_dns(lport); |
1510 | } | 1493 | } |
1511 | } | 1494 | } |
1512 | } else { | 1495 | } else |
1513 | FC_LPORT_DBG(lport, "Bad FLOGI response\n"); | 1496 | fc_lport_error(lport, fp); |
1514 | } | ||
1515 | 1497 | ||
1516 | out: | 1498 | out: |
1517 | fc_frame_free(fp); | 1499 | fc_frame_free(fp); |
@@ -1536,6 +1518,12 @@ void fc_lport_enter_flogi(struct fc_lport *lport) | |||
1536 | 1518 | ||
1537 | fc_lport_state_enter(lport, LPORT_ST_FLOGI); | 1519 | fc_lport_state_enter(lport, LPORT_ST_FLOGI); |
1538 | 1520 | ||
1521 | if (lport->point_to_multipoint) { | ||
1522 | if (lport->port_id) | ||
1523 | fc_lport_enter_ready(lport); | ||
1524 | return; | ||
1525 | } | ||
1526 | |||
1539 | fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); | 1527 | fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); |
1540 | if (!fp) | 1528 | if (!fp) |
1541 | return fc_lport_error(lport, fp); | 1529 | return fc_lport_error(lport, fp); |
@@ -1701,8 +1689,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, | |||
1701 | hton24(fh->fh_d_id, did); | 1689 | hton24(fh->fh_d_id, did); |
1702 | hton24(fh->fh_s_id, lport->port_id); | 1690 | hton24(fh->fh_s_id, lport->port_id); |
1703 | fh->fh_type = FC_TYPE_ELS; | 1691 | fh->fh_type = FC_TYPE_ELS; |
1704 | hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | | 1692 | hton24(fh->fh_f_ctl, FC_FCTL_REQ); |
1705 | FC_FC_END_SEQ | FC_FC_SEQ_INIT); | ||
1706 | fh->fh_cs_ctl = 0; | 1693 | fh->fh_cs_ctl = 0; |
1707 | fh->fh_df_ctl = 0; | 1694 | fh->fh_df_ctl = 0; |
1708 | fh->fh_parm_offset = 0; | 1695 | fh->fh_parm_offset = 0; |
@@ -1761,8 +1748,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, | |||
1761 | hton24(fh->fh_d_id, did); | 1748 | hton24(fh->fh_d_id, did); |
1762 | hton24(fh->fh_s_id, lport->port_id); | 1749 | hton24(fh->fh_s_id, lport->port_id); |
1763 | fh->fh_type = FC_TYPE_CT; | 1750 | fh->fh_type = FC_TYPE_CT; |
1764 | hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | | 1751 | hton24(fh->fh_f_ctl, FC_FCTL_REQ); |
1765 | FC_FC_END_SEQ | FC_FC_SEQ_INIT); | ||
1766 | fh->fh_cs_ctl = 0; | 1752 | fh->fh_cs_ctl = 0; |
1767 | fh->fh_df_ctl = 0; | 1753 | fh->fh_df_ctl = 0; |
1768 | fh->fh_parm_offset = 0; | 1754 | fh->fh_parm_offset = 0; |