[SCSI] libfc: use ADISC to verify rport login state

When rport_login is called on an rport that is already thought
to be logged in, use ADISC.  If that fails, redo PLOGI.
This is less disruptive after fabric changes that don't affect
the state of the target.

Implement the sending of ADISC via fc_els_fill.

Add ADISC state to the rport state machine.  This is entered from READY
and returns to READY after successful completion.  If it fails, the rport
is either logged off and deleted or re-does PLOGI.

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>
This commit is contained in:
Joe Eykholt
2009-08-25 14:03:47 -07:00
committed by James Bottomley
parent 68a1750b46
commit 370c3bd05c
3 changed files with 139 additions and 5 deletions

View File

@ -56,6 +56,23 @@ static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
fh->fh_parm_offset = htonl(parm_offset);
}
/**
* fc_adisc_fill() - Fill in adisc request frame
* @lport: local port.
* @fp: fc frame where payload will be placed.
*/
static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
{
struct fc_els_adisc *adisc;
adisc = fc_frame_payload_get(fp, sizeof(*adisc));
memset(adisc, 0, sizeof(*adisc));
adisc->adisc_cmd = ELS_ADISC;
put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
hton24(adisc->adisc_port_id, fc_host_port_id(lport->host));
}
/**
* fc_ct_hdr_fill- fills ct header and reset ct payload
* returns pointer to ct request.
@ -255,6 +272,10 @@ static inline int fc_els_fill(struct fc_lport *lport,
enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
{
switch (op) {
case ELS_ADISC:
fc_adisc_fill(lport, fp);
break;
case ELS_PLOGI:
fc_plogi_fill(lport, fp, ELS_PLOGI);
break;

View File

@ -143,6 +143,7 @@ enum fc_rport_state {
RPORT_ST_RTV, /* waiting for RTV completion */
RPORT_ST_READY, /* ready for use */
RPORT_ST_LOGO, /* port logout sent */
RPORT_ST_ADISC, /* Discover Address sent */
RPORT_ST_DELETE, /* port being deleted */
};