[SCSI] libfc: introduce LLD event callback
This patch enables LLD to listen to rport events and perform LLD specific operations based on the rport event. This patch also stores sp_features and spp_type in rdata for further reference by LLD. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.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:
parent
acc1a92165
commit
75a2792df2
|
@ -86,6 +86,7 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
|
||||||
|
|
||||||
return lport;
|
return lport;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(fc_vport_id_lookup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When setting the link state of vports during an lport state change, it's
|
* When setting the link state of vports during an lport state change, it's
|
||||||
|
|
|
@ -145,8 +145,10 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
|
||||||
rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
|
rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
|
||||||
INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
|
INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
|
||||||
INIT_WORK(&rdata->event_work, fc_rport_work);
|
INIT_WORK(&rdata->event_work, fc_rport_work);
|
||||||
if (port_id != FC_FID_DIR_SERV)
|
if (port_id != FC_FID_DIR_SERV) {
|
||||||
|
rdata->lld_event_callback = lport->tt.rport_event_callback;
|
||||||
list_add_rcu(&rdata->peers, &lport->disc.rports);
|
list_add_rcu(&rdata->peers, &lport->disc.rports);
|
||||||
|
}
|
||||||
return rdata;
|
return rdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,6 +304,10 @@ static void fc_rport_work(struct work_struct *work)
|
||||||
FC_RPORT_DBG(rdata, "callback ev %d\n", event);
|
FC_RPORT_DBG(rdata, "callback ev %d\n", event);
|
||||||
rport_ops->event_callback(lport, rdata, event);
|
rport_ops->event_callback(lport, rdata, event);
|
||||||
}
|
}
|
||||||
|
if (rdata->lld_event_callback) {
|
||||||
|
FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
|
||||||
|
rdata->lld_event_callback(lport, rdata, event);
|
||||||
|
}
|
||||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -324,6 +330,10 @@ static void fc_rport_work(struct work_struct *work)
|
||||||
FC_RPORT_DBG(rdata, "callback ev %d\n", event);
|
FC_RPORT_DBG(rdata, "callback ev %d\n", event);
|
||||||
rport_ops->event_callback(lport, rdata, event);
|
rport_ops->event_callback(lport, rdata, event);
|
||||||
}
|
}
|
||||||
|
if (rdata->lld_event_callback) {
|
||||||
|
FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
|
||||||
|
rdata->lld_event_callback(lport, rdata, event);
|
||||||
|
}
|
||||||
cancel_delayed_work_sync(&rdata->retry_work);
|
cancel_delayed_work_sync(&rdata->retry_work);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -890,6 +900,9 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
|
||||||
rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
|
rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
|
||||||
rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
|
rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
|
||||||
|
|
||||||
|
/* save plogi response sp_features for further reference */
|
||||||
|
rdata->sp_features = ntohs(plp->fl_csp.sp_features);
|
||||||
|
|
||||||
if (lport->point_to_multipoint)
|
if (lport->point_to_multipoint)
|
||||||
fc_rport_login_complete(rdata, fp);
|
fc_rport_login_complete(rdata, fp);
|
||||||
csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
|
csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
|
||||||
|
@ -997,6 +1010,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
|
||||||
resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
|
resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
|
||||||
FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
|
FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
|
||||||
pp->spp.spp_flags);
|
pp->spp.spp_flags);
|
||||||
|
rdata->spp_type = pp->spp.spp_type;
|
||||||
if (resp_code != FC_SPP_RESP_ACK) {
|
if (resp_code != FC_SPP_RESP_ACK) {
|
||||||
if (resp_code == FC_SPP_RESP_CONF)
|
if (resp_code == FC_SPP_RESP_CONF)
|
||||||
fc_rport_error(rdata, fp);
|
fc_rport_error(rdata, fp);
|
||||||
|
@ -1010,6 +1024,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
|
||||||
fcp_parm = ntohl(pp->spp.spp_params);
|
fcp_parm = ntohl(pp->spp.spp_params);
|
||||||
if (fcp_parm & FCP_SPPF_RETRY)
|
if (fcp_parm & FCP_SPPF_RETRY)
|
||||||
rdata->flags |= FC_RP_FLAGS_RETRY;
|
rdata->flags |= FC_RP_FLAGS_RETRY;
|
||||||
|
if (fcp_parm & FCP_SPPF_CONF_COMPL)
|
||||||
|
rdata->flags |= FC_RP_FLAGS_CONF_REQ;
|
||||||
|
|
||||||
prov = fc_passive_prov[FC_TYPE_FCP];
|
prov = fc_passive_prov[FC_TYPE_FCP];
|
||||||
if (prov) {
|
if (prov) {
|
||||||
|
@ -1719,6 +1735,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
|
||||||
spp = &pp->spp;
|
spp = &pp->spp;
|
||||||
mutex_lock(&fc_prov_mutex);
|
mutex_lock(&fc_prov_mutex);
|
||||||
while (len >= plen) {
|
while (len >= plen) {
|
||||||
|
rdata->spp_type = rspp->spp_type;
|
||||||
spp->spp_type = rspp->spp_type;
|
spp->spp_type = rspp->spp_type;
|
||||||
spp->spp_type_ext = rspp->spp_type_ext;
|
spp->spp_type_ext = rspp->spp_type_ext;
|
||||||
resp = 0;
|
resp = 0;
|
||||||
|
|
|
@ -158,6 +158,7 @@ struct fc_rport_libfc_priv {
|
||||||
#define FC_RP_FLAGS_REC_SUPPORTED (1 << 0)
|
#define FC_RP_FLAGS_REC_SUPPORTED (1 << 0)
|
||||||
#define FC_RP_FLAGS_RETRY (1 << 1)
|
#define FC_RP_FLAGS_RETRY (1 << 1)
|
||||||
#define FC_RP_STARTED (1 << 2)
|
#define FC_RP_STARTED (1 << 2)
|
||||||
|
#define FC_RP_FLAGS_CONF_REQ (1 << 3)
|
||||||
unsigned int e_d_tov;
|
unsigned int e_d_tov;
|
||||||
unsigned int r_a_tov;
|
unsigned int r_a_tov;
|
||||||
};
|
};
|
||||||
|
@ -207,6 +208,11 @@ struct fc_rport_priv {
|
||||||
u32 supported_classes;
|
u32 supported_classes;
|
||||||
u16 prli_count;
|
u16 prli_count;
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
|
u16 sp_features;
|
||||||
|
u8 spp_type;
|
||||||
|
void (*lld_event_callback)(struct fc_lport *,
|
||||||
|
struct fc_rport_priv *,
|
||||||
|
enum fc_rport_event);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -676,6 +682,15 @@ struct libfc_function_template {
|
||||||
*/
|
*/
|
||||||
void (*rport_destroy)(struct kref *);
|
void (*rport_destroy)(struct kref *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback routine after the remote port is logged in
|
||||||
|
*
|
||||||
|
* STATUS: OPTIONAL
|
||||||
|
*/
|
||||||
|
void (*rport_event_callback)(struct fc_lport *,
|
||||||
|
struct fc_rport_priv *,
|
||||||
|
enum fc_rport_event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a fcp cmd from fsp pkt.
|
* Send a fcp cmd from fsp pkt.
|
||||||
* Called with the SCSI host lock unlocked and irqs disabled.
|
* Called with the SCSI host lock unlocked and irqs disabled.
|
||||||
|
|
Loading…
Reference in New Issue