Commit ee1a4a42 authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[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: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent ebfe8392
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -410,6 +410,11 @@ struct bfa_rport_remote_link_stats_s {
	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_NO_IO_INDEX 9
+7 −3
Original line number Diff line number Diff line
@@ -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);
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,
			      wwn_t rport_wwns[], int *nrports);

void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
			struct bfa_rport_qualifier_s rport[], int *nrports);
wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
			      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);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_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_lport_s *port, wwn_t pwwn);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_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,
				       struct bfa_fcs_rport_s *rport);
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 bfad_rport_s	*rp_drv;	/*  driver peer instance */
	u32	pid;	/*  port ID of rport */
	u32	old_pid;	/* PID before rport goes offline */
	u16	maxfrsize;	/*  maximum frame size */
	__be16	reply_oxid;	/*  OX_ID of inbound requests */
	enum fc_cos	fc_cos;	/*  FC classes of service supp */
+52 −4
Original line number Diff line number Diff line
@@ -853,6 +853,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
	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
 */
@@ -891,6 +910,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
	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.
 */
@@ -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.
	 */
	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 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
bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
	 wwn_t rport_wwns[], int *nrports)
bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
		struct bfa_rport_qualifier_s rports[], int *nrports)
{
	struct list_head	*qh, *qe;
	struct bfa_fcs_rport_s *rport = NULL;
	int	i;
	struct bfa_fcs_s	*fcs;

	if (port == NULL || rport_wwns == NULL || *nrports == 0)
	if (port == NULL || rports == NULL || *nrports == 0)
		return;

	fcs = port->fcs;
@@ -4979,7 +5021,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
			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++;
		qe = bfa_q_next(qe);
+3 −0
Original line number Diff line number Diff line
@@ -397,6 +397,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
					BFA_FCS_RETRY_TIMEOUT);
		} else {
			bfa_stats(rport->port, rport_del_max_plogi_retry);
			rport->old_pid = rport->pid;
			rport->pid = 0;
			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
			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_send_nsdisc(rport, NULL);
		} else {
			rport->old_pid = rport->pid;
			rport->pid = 0;
			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
			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->pid = rpid;
	rport->pwwn = pwwn;
	rport->old_pid = 0;

	/*
	 * allocate BFA rport
+4 −3
Original line number Diff line number Diff line
@@ -941,15 +941,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
	struct bfad_port_s    *port = im_port->port;
	struct bfad_s         *bfad = im_port->bfad;
	int        nrports = 2048;
	wwn_t          *rports = NULL;
	struct bfa_rport_qualifier_s *rports = NULL;
	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)
		return snprintf(buf, PAGE_SIZE, "Failed\n");

	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);
	kfree(rports);

Loading