diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2010-07-20 18:20:35 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 10:05:57 -0400 |
commit | 5554345bc5275afed760631277fdab0a5a19472e (patch) | |
tree | bef6ffe6cf1a0a8181247a3c3f6f0965bfcebf27 /drivers/scsi/fcoe/libfcoe.c | |
parent | e10f8c667b874a57512c936089092a3d1ef7ab8a (diff) |
[SCSI] libfcoe: Fix FIP ELS encapsulation details for FLOGI responses
When sending a FLOGI LS_ACC, which we only do in point-to-multipoint
mode, the MAC descriptor should have the granted MAC set to
0x0efd00 || D_ID.
When sending an LS_RJT, there should be no MAC descriptor.
When sending either an LS_ACC or LS_RJT, the subcode should indicate
an reply, not a request.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe/libfcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 79df78f2b085..4865e8181172 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -469,11 +469,15 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
469 | struct fip_header fip; | 469 | struct fip_header fip; |
470 | struct fip_encaps encaps; | 470 | struct fip_encaps encaps; |
471 | } __attribute__((packed)) *cap; | 471 | } __attribute__((packed)) *cap; |
472 | struct fc_frame_header *fh; | ||
472 | struct fip_mac_desc *mac; | 473 | struct fip_mac_desc *mac; |
473 | struct fcoe_fcf *fcf; | 474 | struct fcoe_fcf *fcf; |
474 | size_t dlen; | 475 | size_t dlen; |
475 | u16 fip_flags; | 476 | u16 fip_flags; |
477 | u8 op; | ||
476 | 478 | ||
479 | fh = (struct fc_frame_header *)skb->data; | ||
480 | op = *(u8 *)(fh + 1); | ||
477 | dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ | 481 | dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ |
478 | cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); | 482 | cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); |
479 | memset(cap, 0, sizeof(*cap)); | 483 | memset(cap, 0, sizeof(*cap)); |
@@ -481,6 +485,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
481 | if (lport->point_to_multipoint) { | 485 | if (lport->point_to_multipoint) { |
482 | if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest)) | 486 | if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest)) |
483 | return -ENODEV; | 487 | return -ENODEV; |
488 | fip_flags = 0; | ||
484 | } else { | 489 | } else { |
485 | fcf = fip->sel_fcf; | 490 | fcf = fip->sel_fcf; |
486 | if (!fcf) | 491 | if (!fcf) |
@@ -497,26 +502,35 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
497 | 502 | ||
498 | cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); | 503 | cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); |
499 | cap->fip.fip_op = htons(FIP_OP_LS); | 504 | cap->fip.fip_op = htons(FIP_OP_LS); |
500 | cap->fip.fip_subcode = FIP_SC_REQ; | 505 | if (op == ELS_LS_ACC || op == ELS_LS_RJT) |
501 | cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); | 506 | cap->fip.fip_subcode = FIP_SC_REP; |
507 | else | ||
508 | cap->fip.fip_subcode = FIP_SC_REQ; | ||
502 | cap->fip.fip_flags = htons(fip_flags); | 509 | cap->fip.fip_flags = htons(fip_flags); |
503 | 510 | ||
504 | cap->encaps.fd_desc.fip_dtype = dtype; | 511 | cap->encaps.fd_desc.fip_dtype = dtype; |
505 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; | 512 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; |
506 | 513 | ||
507 | mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); | 514 | if (op != ELS_LS_RJT) { |
508 | memset(mac, 0, sizeof(*mac)); | 515 | dlen += sizeof(*mac); |
509 | mac->fd_desc.fip_dtype = FIP_DT_MAC; | 516 | mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); |
510 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; | 517 | memset(mac, 0, sizeof(*mac)); |
511 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { | 518 | mac->fd_desc.fip_dtype = FIP_DT_MAC; |
512 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); | 519 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; |
513 | } else if (fip_flags & FIP_FL_SPMA) { | 520 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { |
514 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); | 521 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
515 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | 522 | } else if (fip->mode == FIP_MODE_VN2VN) { |
516 | } else { | 523 | hton24(mac->fd_mac, FIP_VN_FC_MAP); |
517 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); | 524 | hton24(mac->fd_mac + 3, fip->port_id); |
518 | /* FPMA only FLOGI must leave the MAC desc set to all 0s */ | 525 | } else if (fip_flags & FIP_FL_SPMA) { |
526 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); | ||
527 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | ||
528 | } else { | ||
529 | LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); | ||
530 | /* FPMA only FLOGI. Must leave the MAC desc zeroed. */ | ||
531 | } | ||
519 | } | 532 | } |
533 | cap->fip.fip_dl_len = htons(dlen / FIP_BPW); | ||
520 | 534 | ||
521 | skb->protocol = htons(ETH_P_FIP); | 535 | skb->protocol = htons(ETH_P_FIP); |
522 | skb_reset_mac_header(skb); | 536 | skb_reset_mac_header(skb); |