diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2012-08-22 22:50:43 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-24 04:10:56 -0400 |
commit | ee1a4a42f6198c2b6e7c9fba6a952d1f4f89d627 (patch) | |
tree | ead7372ab22e9cf4734148b02f28a713f40c321d /drivers/scsi/bfa | |
parent | ebfe83921bd860e0b28a1a74e90be57baf2c8255 (diff) |
[SCSI] bfa: FCS remote port enhancements.
- Introduced rport qualifier structure and modified design to
export remote ports with valid pid or valid pwwn to the user space.
- Introduced old_pid field in the rport structure and made changes to
prevent re-creating a new remote port for an already existing rport
that is transitioning to a delete state. (Happens if we receive a RSCN
on the existing remote port that is getting deleted).
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r-- | drivers/scsi/bfa/bfa_defs_fcs.h | 5 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcs.h | 10 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcs_lport.c | 56 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcs_rport.c | 3 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_attr.c | 7 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 14 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.h | 2 |
7 files changed, 83 insertions, 14 deletions
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h index 3bbc583f65cf..5871a1b6e2bc 100644 --- a/drivers/scsi/bfa/bfa_defs_fcs.h +++ b/drivers/scsi/bfa/bfa_defs_fcs.h | |||
@@ -410,6 +410,11 @@ struct bfa_rport_remote_link_stats_s { | |||
410 | u32 icc; /* Invalid CRC Count */ | 410 | u32 icc; /* Invalid CRC Count */ |
411 | }; | 411 | }; |
412 | 412 | ||
413 | struct bfa_rport_qualifier_s { | ||
414 | wwn_t pwwn; /* Port WWN */ | ||
415 | u32 pid; /* port ID */ | ||
416 | u32 rsvd; | ||
417 | }; | ||
413 | 418 | ||
414 | #define BFA_MAX_IO_INDEX 7 | 419 | #define BFA_MAX_IO_INDEX 7 |
415 | #define BFA_NO_IO_INDEX 9 | 420 | #define BFA_NO_IO_INDEX 9 |
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 050a7e900434..ef0ec66f714a 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h | |||
@@ -286,9 +286,8 @@ bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port) | |||
286 | 286 | ||
287 | bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port); | 287 | bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port); |
288 | struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs); | 288 | struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs); |
289 | void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, | 289 | void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, |
290 | wwn_t rport_wwns[], int *nrports); | 290 | struct bfa_rport_qualifier_s rport[], int *nrports); |
291 | |||
292 | wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, | 291 | wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, |
293 | int index, int nrports, bfa_boolean_t bwwn); | 292 | int index, int nrports, bfa_boolean_t bwwn); |
294 | 293 | ||
@@ -326,10 +325,14 @@ void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port); | |||
326 | void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port); | 325 | void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port); |
327 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid( | 326 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid( |
328 | struct bfa_fcs_lport_s *port, u32 pid); | 327 | struct bfa_fcs_lport_s *port, u32 pid); |
328 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid( | ||
329 | struct bfa_fcs_lport_s *port, u32 pid); | ||
329 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn( | 330 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn( |
330 | struct bfa_fcs_lport_s *port, wwn_t pwwn); | 331 | struct bfa_fcs_lport_s *port, wwn_t pwwn); |
331 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn( | 332 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn( |
332 | struct bfa_fcs_lport_s *port, wwn_t nwwn); | 333 | struct bfa_fcs_lport_s *port, wwn_t nwwn); |
334 | struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_qualifier( | ||
335 | struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 pid); | ||
333 | void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port, | 336 | void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port, |
334 | struct bfa_fcs_rport_s *rport); | 337 | struct bfa_fcs_rport_s *rport); |
335 | void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port, | 338 | void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port, |
@@ -421,6 +424,7 @@ struct bfa_fcs_rport_s { | |||
421 | struct bfa_fcs_s *fcs; /* fcs instance */ | 424 | struct bfa_fcs_s *fcs; /* fcs instance */ |
422 | struct bfad_rport_s *rp_drv; /* driver peer instance */ | 425 | struct bfad_rport_s *rp_drv; /* driver peer instance */ |
423 | u32 pid; /* port ID of rport */ | 426 | u32 pid; /* port ID of rport */ |
427 | u32 old_pid; /* PID before rport goes offline */ | ||
424 | u16 maxfrsize; /* maximum frame size */ | 428 | u16 maxfrsize; /* maximum frame size */ |
425 | __be16 reply_oxid; /* OX_ID of inbound requests */ | 429 | __be16 reply_oxid; /* OX_ID of inbound requests */ |
426 | enum fc_cos fc_cos; /* FC classes of service supp */ | 430 | enum fc_cos fc_cos; /* FC classes of service supp */ |
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index f8e801747ea7..5392df5c51ab 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c | |||
@@ -854,6 +854,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid) | |||
854 | } | 854 | } |
855 | 855 | ||
856 | /* | 856 | /* |
857 | * OLD_PID based Lookup for a R-Port in the Port R-Port Queue | ||
858 | */ | ||
859 | struct bfa_fcs_rport_s * | ||
860 | bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid) | ||
861 | { | ||
862 | struct bfa_fcs_rport_s *rport; | ||
863 | struct list_head *qe; | ||
864 | |||
865 | list_for_each(qe, &port->rport_q) { | ||
866 | rport = (struct bfa_fcs_rport_s *) qe; | ||
867 | if (rport->old_pid == pid) | ||
868 | return rport; | ||
869 | } | ||
870 | |||
871 | bfa_trc(port->fcs, pid); | ||
872 | return NULL; | ||
873 | } | ||
874 | |||
875 | /* | ||
857 | * PWWN based Lookup for a R-Port in the Port R-Port Queue | 876 | * PWWN based Lookup for a R-Port in the Port R-Port Queue |
858 | */ | 877 | */ |
859 | struct bfa_fcs_rport_s * | 878 | struct bfa_fcs_rport_s * |
@@ -892,6 +911,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn) | |||
892 | } | 911 | } |
893 | 912 | ||
894 | /* | 913 | /* |
914 | * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue | ||
915 | */ | ||
916 | struct bfa_fcs_rport_s * | ||
917 | bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port, | ||
918 | wwn_t pwwn, u32 pid) | ||
919 | { | ||
920 | struct bfa_fcs_rport_s *rport; | ||
921 | struct list_head *qe; | ||
922 | |||
923 | list_for_each(qe, &port->rport_q) { | ||
924 | rport = (struct bfa_fcs_rport_s *) qe; | ||
925 | if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid) | ||
926 | return rport; | ||
927 | } | ||
928 | |||
929 | bfa_trc(port->fcs, pwwn); | ||
930 | return NULL; | ||
931 | } | ||
932 | |||
933 | /* | ||
895 | * Called by rport module when new rports are discovered. | 934 | * Called by rport module when new rports are discovered. |
896 | */ | 935 | */ |
897 | void | 936 | void |
@@ -4759,6 +4798,9 @@ bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid) | |||
4759 | * Otherwise let rport handle the RSCN event. | 4798 | * Otherwise let rport handle the RSCN event. |
4760 | */ | 4799 | */ |
4761 | rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); | 4800 | rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); |
4801 | if (!rport) | ||
4802 | rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid); | ||
4803 | |||
4762 | if (rport == NULL) { | 4804 | if (rport == NULL) { |
4763 | /* | 4805 | /* |
4764 | * If min cfg mode is enabled, we donot need to | 4806 | * If min cfg mode is enabled, we donot need to |
@@ -4951,15 +4993,15 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index, | |||
4951 | } | 4993 | } |
4952 | 4994 | ||
4953 | void | 4995 | void |
4954 | bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, | 4996 | bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, |
4955 | wwn_t rport_wwns[], int *nrports) | 4997 | struct bfa_rport_qualifier_s rports[], int *nrports) |
4956 | { | 4998 | { |
4957 | struct list_head *qh, *qe; | 4999 | struct list_head *qh, *qe; |
4958 | struct bfa_fcs_rport_s *rport = NULL; | 5000 | struct bfa_fcs_rport_s *rport = NULL; |
4959 | int i; | 5001 | int i; |
4960 | struct bfa_fcs_s *fcs; | 5002 | struct bfa_fcs_s *fcs; |
4961 | 5003 | ||
4962 | if (port == NULL || rport_wwns == NULL || *nrports == 0) | 5004 | if (port == NULL || rports == NULL || *nrports == 0) |
4963 | return; | 5005 | return; |
4964 | 5006 | ||
4965 | fcs = port->fcs; | 5007 | fcs = port->fcs; |
@@ -4979,7 +5021,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, | |||
4979 | continue; | 5021 | continue; |
4980 | } | 5022 | } |
4981 | 5023 | ||
4982 | rport_wwns[i] = rport->pwwn; | 5024 | if (!rport->pwwn && !rport->pid) { |
5025 | qe = bfa_q_next(qe); | ||
5026 | continue; | ||
5027 | } | ||
5028 | |||
5029 | rports[i].pwwn = rport->pwwn; | ||
5030 | rports[i].pid = rport->pid; | ||
4983 | 5031 | ||
4984 | i++; | 5032 | i++; |
4985 | qe = bfa_q_next(qe); | 5033 | qe = bfa_q_next(qe); |
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index fe0463a1db04..fa2df04d9662 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c | |||
@@ -397,6 +397,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) | |||
397 | BFA_FCS_RETRY_TIMEOUT); | 397 | BFA_FCS_RETRY_TIMEOUT); |
398 | } else { | 398 | } else { |
399 | bfa_stats(rport->port, rport_del_max_plogi_retry); | 399 | bfa_stats(rport->port, rport_del_max_plogi_retry); |
400 | rport->old_pid = rport->pid; | ||
400 | rport->pid = 0; | 401 | rport->pid = 0; |
401 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | 402 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); |
402 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | 403 | bfa_timer_start(rport->fcs->bfa, &rport->timer, |
@@ -1296,6 +1297,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, | |||
1296 | bfa_fcs_rport_sm_nsdisc_sending); | 1297 | bfa_fcs_rport_sm_nsdisc_sending); |
1297 | bfa_fcs_rport_send_nsdisc(rport, NULL); | 1298 | bfa_fcs_rport_send_nsdisc(rport, NULL); |
1298 | } else { | 1299 | } else { |
1300 | rport->old_pid = rport->pid; | ||
1299 | rport->pid = 0; | 1301 | rport->pid = 0; |
1300 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | 1302 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); |
1301 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | 1303 | bfa_timer_start(rport->fcs->bfa, &rport->timer, |
@@ -1981,6 +1983,7 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid) | |||
1981 | rport->rp_drv = rport_drv; | 1983 | rport->rp_drv = rport_drv; |
1982 | rport->pid = rpid; | 1984 | rport->pid = rpid; |
1983 | rport->pwwn = pwwn; | 1985 | rport->pwwn = pwwn; |
1986 | rport->old_pid = 0; | ||
1984 | 1987 | ||
1985 | /* | 1988 | /* |
1986 | * allocate BFA rport | 1989 | * allocate BFA rport |
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 1d18a803cff0..91a204470a43 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c | |||
@@ -941,15 +941,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev, | |||
941 | struct bfad_port_s *port = im_port->port; | 941 | struct bfad_port_s *port = im_port->port; |
942 | struct bfad_s *bfad = im_port->bfad; | 942 | struct bfad_s *bfad = im_port->bfad; |
943 | int nrports = 2048; | 943 | int nrports = 2048; |
944 | wwn_t *rports = NULL; | 944 | struct bfa_rport_qualifier_s *rports = NULL; |
945 | unsigned long flags; | 945 | unsigned long flags; |
946 | 946 | ||
947 | rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC); | 947 | rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports, |
948 | GFP_ATOMIC); | ||
948 | if (rports == NULL) | 949 | if (rports == NULL) |
949 | return snprintf(buf, PAGE_SIZE, "Failed\n"); | 950 | return snprintf(buf, PAGE_SIZE, "Failed\n"); |
950 | 951 | ||
951 | spin_lock_irqsave(&bfad->bfad_lock, flags); | 952 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
952 | bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports); | 953 | bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports); |
953 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 954 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
954 | kfree(rports); | 955 | kfree(rports); |
955 | 956 | ||
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 9c1495b321d9..d9463d8249e3 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c | |||
@@ -535,7 +535,8 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd, | |||
535 | 535 | ||
536 | if (bfad_chk_iocmd_sz(payload_len, | 536 | if (bfad_chk_iocmd_sz(payload_len, |
537 | sizeof(struct bfa_bsg_lport_get_rports_s), | 537 | sizeof(struct bfa_bsg_lport_get_rports_s), |
538 | sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) { | 538 | sizeof(struct bfa_rport_qualifier_s) * iocmd->nrports) |
539 | != BFA_STATUS_OK) { | ||
539 | iocmd->status = BFA_STATUS_VERSION_FAIL; | 540 | iocmd->status = BFA_STATUS_VERSION_FAIL; |
540 | return 0; | 541 | return 0; |
541 | } | 542 | } |
@@ -552,8 +553,9 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd, | |||
552 | goto out; | 553 | goto out; |
553 | } | 554 | } |
554 | 555 | ||
555 | bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr, | 556 | bfa_fcs_lport_get_rport_quals(fcs_port, |
556 | &iocmd->nrports); | 557 | (struct bfa_rport_qualifier_s *)iocmd_bufptr, |
558 | &iocmd->nrports); | ||
557 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 559 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
558 | iocmd->status = BFA_STATUS_OK; | 560 | iocmd->status = BFA_STATUS_OK; |
559 | out: | 561 | out: |
@@ -578,7 +580,11 @@ bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd) | |||
578 | goto out; | 580 | goto out; |
579 | } | 581 | } |
580 | 582 | ||
581 | fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); | 583 | if (iocmd->pid) |
584 | fcs_rport = bfa_fcs_lport_get_rport_by_qualifier(fcs_port, | ||
585 | iocmd->rpwwn, iocmd->pid); | ||
586 | else | ||
587 | fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); | ||
582 | if (fcs_rport == NULL) { | 588 | if (fcs_rport == NULL) { |
583 | bfa_trc(bfad, 0); | 589 | bfa_trc(bfad, 0); |
584 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 590 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 17ad67283130..8c569ddb750d 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h | |||
@@ -319,6 +319,8 @@ struct bfa_bsg_rport_attr_s { | |||
319 | u16 vf_id; | 319 | u16 vf_id; |
320 | wwn_t pwwn; | 320 | wwn_t pwwn; |
321 | wwn_t rpwwn; | 321 | wwn_t rpwwn; |
322 | u32 pid; | ||
323 | u32 rsvd; | ||
322 | struct bfa_rport_attr_s attr; | 324 | struct bfa_rport_attr_s attr; |
323 | }; | 325 | }; |
324 | 326 | ||