[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>
This commit is contained in:
parent
ebfe83921b
commit
ee1a4a42f6
7 changed files with 83 additions and 14 deletions
|
@ -410,6 +410,11 @@ struct bfa_rport_remote_link_stats_s {
|
||||||
u32 icc; /* Invalid CRC Count */
|
u32 icc; /* Invalid CRC Count */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bfa_rport_qualifier_s {
|
||||||
|
wwn_t pwwn; /* Port WWN */
|
||||||
|
u32 pid; /* port ID */
|
||||||
|
u32 rsvd;
|
||||||
|
};
|
||||||
|
|
||||||
#define BFA_MAX_IO_INDEX 7
|
#define BFA_MAX_IO_INDEX 7
|
||||||
#define BFA_NO_IO_INDEX 9
|
#define BFA_NO_IO_INDEX 9
|
||||||
|
|
|
@ -286,9 +286,8 @@ bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
|
||||||
|
|
||||||
bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
|
bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
|
||||||
struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
|
struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
|
||||||
void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
|
void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
|
||||||
wwn_t rport_wwns[], int *nrports);
|
struct bfa_rport_qualifier_s rport[], int *nrports);
|
||||||
|
|
||||||
wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
|
wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
|
||||||
int index, int nrports, bfa_boolean_t bwwn);
|
int index, int nrports, bfa_boolean_t bwwn);
|
||||||
|
|
||||||
|
@ -326,10 +325,14 @@ void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
|
||||||
void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
|
void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
|
||||||
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
|
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
|
||||||
struct bfa_fcs_lport_s *port, u32 pid);
|
struct bfa_fcs_lport_s *port, u32 pid);
|
||||||
|
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid(
|
||||||
|
struct bfa_fcs_lport_s *port, u32 pid);
|
||||||
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
|
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
|
||||||
struct bfa_fcs_lport_s *port, wwn_t pwwn);
|
struct bfa_fcs_lport_s *port, wwn_t pwwn);
|
||||||
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
|
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
|
||||||
struct bfa_fcs_lport_s *port, wwn_t nwwn);
|
struct bfa_fcs_lport_s *port, wwn_t nwwn);
|
||||||
|
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_qualifier(
|
||||||
|
struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 pid);
|
||||||
void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
|
void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
|
||||||
struct bfa_fcs_rport_s *rport);
|
struct bfa_fcs_rport_s *rport);
|
||||||
void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
|
void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
|
||||||
|
@ -421,6 +424,7 @@ struct bfa_fcs_rport_s {
|
||||||
struct bfa_fcs_s *fcs; /* fcs instance */
|
struct bfa_fcs_s *fcs; /* fcs instance */
|
||||||
struct bfad_rport_s *rp_drv; /* driver peer instance */
|
struct bfad_rport_s *rp_drv; /* driver peer instance */
|
||||||
u32 pid; /* port ID of rport */
|
u32 pid; /* port ID of rport */
|
||||||
|
u32 old_pid; /* PID before rport goes offline */
|
||||||
u16 maxfrsize; /* maximum frame size */
|
u16 maxfrsize; /* maximum frame size */
|
||||||
__be16 reply_oxid; /* OX_ID of inbound requests */
|
__be16 reply_oxid; /* OX_ID of inbound requests */
|
||||||
enum fc_cos fc_cos; /* FC classes of service supp */
|
enum fc_cos fc_cos; /* FC classes of service supp */
|
||||||
|
|
|
@ -853,6 +853,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OLD_PID based Lookup for a R-Port in the Port R-Port Queue
|
||||||
|
*/
|
||||||
|
struct bfa_fcs_rport_s *
|
||||||
|
bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
|
||||||
|
{
|
||||||
|
struct bfa_fcs_rport_s *rport;
|
||||||
|
struct list_head *qe;
|
||||||
|
|
||||||
|
list_for_each(qe, &port->rport_q) {
|
||||||
|
rport = (struct bfa_fcs_rport_s *) qe;
|
||||||
|
if (rport->old_pid == pid)
|
||||||
|
return rport;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfa_trc(port->fcs, pid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PWWN based Lookup for a R-Port in the Port R-Port Queue
|
* PWWN based Lookup for a R-Port in the Port R-Port Queue
|
||||||
*/
|
*/
|
||||||
|
@ -891,6 +910,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
|
||||||
|
*/
|
||||||
|
struct bfa_fcs_rport_s *
|
||||||
|
bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
|
||||||
|
wwn_t pwwn, u32 pid)
|
||||||
|
{
|
||||||
|
struct bfa_fcs_rport_s *rport;
|
||||||
|
struct list_head *qe;
|
||||||
|
|
||||||
|
list_for_each(qe, &port->rport_q) {
|
||||||
|
rport = (struct bfa_fcs_rport_s *) qe;
|
||||||
|
if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
|
||||||
|
return rport;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfa_trc(port->fcs, pwwn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by rport module when new rports are discovered.
|
* Called by rport module when new rports are discovered.
|
||||||
*/
|
*/
|
||||||
|
@ -4759,6 +4798,9 @@ bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
|
||||||
* Otherwise let rport handle the RSCN event.
|
* Otherwise let rport handle the RSCN event.
|
||||||
*/
|
*/
|
||||||
rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
|
rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
|
||||||
|
if (!rport)
|
||||||
|
rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
|
||||||
|
|
||||||
if (rport == NULL) {
|
if (rport == NULL) {
|
||||||
/*
|
/*
|
||||||
* If min cfg mode is enabled, we donot need to
|
* 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
|
bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
|
||||||
wwn_t rport_wwns[], int *nrports)
|
struct bfa_rport_qualifier_s rports[], int *nrports)
|
||||||
{
|
{
|
||||||
struct list_head *qh, *qe;
|
struct list_head *qh, *qe;
|
||||||
struct bfa_fcs_rport_s *rport = NULL;
|
struct bfa_fcs_rport_s *rport = NULL;
|
||||||
int i;
|
int i;
|
||||||
struct bfa_fcs_s *fcs;
|
struct bfa_fcs_s *fcs;
|
||||||
|
|
||||||
if (port == NULL || rport_wwns == NULL || *nrports == 0)
|
if (port == NULL || rports == NULL || *nrports == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fcs = port->fcs;
|
fcs = port->fcs;
|
||||||
|
@ -4979,7 +5021,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rport_wwns[i] = rport->pwwn;
|
if (!rport->pwwn && !rport->pid) {
|
||||||
|
qe = bfa_q_next(qe);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rports[i].pwwn = rport->pwwn;
|
||||||
|
rports[i].pid = rport->pid;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
qe = bfa_q_next(qe);
|
qe = bfa_q_next(qe);
|
||||||
|
|
|
@ -397,6 +397,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
|
||||||
BFA_FCS_RETRY_TIMEOUT);
|
BFA_FCS_RETRY_TIMEOUT);
|
||||||
} else {
|
} else {
|
||||||
bfa_stats(rport->port, rport_del_max_plogi_retry);
|
bfa_stats(rport->port, rport_del_max_plogi_retry);
|
||||||
|
rport->old_pid = rport->pid;
|
||||||
rport->pid = 0;
|
rport->pid = 0;
|
||||||
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
|
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
|
||||||
bfa_timer_start(rport->fcs->bfa, &rport->timer,
|
bfa_timer_start(rport->fcs->bfa, &rport->timer,
|
||||||
|
@ -1296,6 +1297,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
|
||||||
bfa_fcs_rport_sm_nsdisc_sending);
|
bfa_fcs_rport_sm_nsdisc_sending);
|
||||||
bfa_fcs_rport_send_nsdisc(rport, NULL);
|
bfa_fcs_rport_send_nsdisc(rport, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
rport->old_pid = rport->pid;
|
||||||
rport->pid = 0;
|
rport->pid = 0;
|
||||||
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
|
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
|
||||||
bfa_timer_start(rport->fcs->bfa, &rport->timer,
|
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)
|
||||||
rport->rp_drv = rport_drv;
|
rport->rp_drv = rport_drv;
|
||||||
rport->pid = rpid;
|
rport->pid = rpid;
|
||||||
rport->pwwn = pwwn;
|
rport->pwwn = pwwn;
|
||||||
|
rport->old_pid = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate BFA rport
|
* allocate BFA rport
|
||||||
|
|
|
@ -941,15 +941,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
|
||||||
struct bfad_port_s *port = im_port->port;
|
struct bfad_port_s *port = im_port->port;
|
||||||
struct bfad_s *bfad = im_port->bfad;
|
struct bfad_s *bfad = im_port->bfad;
|
||||||
int nrports = 2048;
|
int nrports = 2048;
|
||||||
wwn_t *rports = NULL;
|
struct bfa_rport_qualifier_s *rports = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
|
rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports,
|
||||||
|
GFP_ATOMIC);
|
||||||
if (rports == NULL)
|
if (rports == NULL)
|
||||||
return snprintf(buf, PAGE_SIZE, "Failed\n");
|
return snprintf(buf, PAGE_SIZE, "Failed\n");
|
||||||
|
|
||||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||||
bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
|
bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
|
||||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||||
kfree(rports);
|
kfree(rports);
|
||||||
|
|
||||||
|
|
|
@ -535,7 +535,8 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
|
||||||
|
|
||||||
if (bfad_chk_iocmd_sz(payload_len,
|
if (bfad_chk_iocmd_sz(payload_len,
|
||||||
sizeof(struct bfa_bsg_lport_get_rports_s),
|
sizeof(struct bfa_bsg_lport_get_rports_s),
|
||||||
sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) {
|
sizeof(struct bfa_rport_qualifier_s) * iocmd->nrports)
|
||||||
|
!= BFA_STATUS_OK) {
|
||||||
iocmd->status = BFA_STATUS_VERSION_FAIL;
|
iocmd->status = BFA_STATUS_VERSION_FAIL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -552,8 +553,9 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr,
|
bfa_fcs_lport_get_rport_quals(fcs_port,
|
||||||
&iocmd->nrports);
|
(struct bfa_rport_qualifier_s *)iocmd_bufptr,
|
||||||
|
&iocmd->nrports);
|
||||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||||
iocmd->status = BFA_STATUS_OK;
|
iocmd->status = BFA_STATUS_OK;
|
||||||
out:
|
out:
|
||||||
|
@ -578,7 +580,11 @@ bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
|
if (iocmd->pid)
|
||||||
|
fcs_rport = bfa_fcs_lport_get_rport_by_qualifier(fcs_port,
|
||||||
|
iocmd->rpwwn, iocmd->pid);
|
||||||
|
else
|
||||||
|
fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
|
||||||
if (fcs_rport == NULL) {
|
if (fcs_rport == NULL) {
|
||||||
bfa_trc(bfad, 0);
|
bfa_trc(bfad, 0);
|
||||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||||
|
|
|
@ -319,6 +319,8 @@ struct bfa_bsg_rport_attr_s {
|
||||||
u16 vf_id;
|
u16 vf_id;
|
||||||
wwn_t pwwn;
|
wwn_t pwwn;
|
||||||
wwn_t rpwwn;
|
wwn_t rpwwn;
|
||||||
|
u32 pid;
|
||||||
|
u32 rsvd;
|
||||||
struct bfa_rport_attr_s attr;
|
struct bfa_rport_attr_s attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue