From b87aa0f0040e57b9cd62f8b596aa50ee688fa589 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 10 Mar 2019 02:28:44 +0000 Subject: [PATCH] fcst: Remove support for kernel versions <= 2.6.36 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8028 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- fcst/linux-patches/01-prli-clean | 241 --------- fcst/linux-patches/02-fc4 | 487 ------------------ fcst/linux-patches/03-seq-init | 31 -- fcst/linux-patches/04-seq-set-resp | 84 --- fcst/linux-patches/05-lport-hook | 36 -- fcst/linux-patches/06-lport-notify | 167 ------ fcst/linux-patches/07-pta-mask | 25 - fcst/linux-patches/08-ptp-ref | 49 -- fcst/linux-patches/09-ptp-type | 30 -- fcst/linux-patches/10-non-fip | 33 -- fcst/linux-patches/11-ptp-flogi-recv | 63 --- fcst/linux-patches/12-ptp-npiv | 30 -- fcst/linux-patches/13-ptp-acc | 32 -- .../14-fc-frame-sparse-workaround | 13 - fcst/linux-patches/15-fc4 | 487 ------------------ fcst/linux-patches/16-seq-set-resp | 84 --- fcst/linux-patches/17-lport-hook | 36 -- fcst/linux-patches/18-lport-notify | 167 ------ fcst/linux-patches/19-fc4-v2 | 483 ----------------- fcst/linux-patches/20-seq-set-resp | 84 --- fcst/linux-patches/21-lport-hook | 36 -- fcst/linux-patches/22-lport-notify | 167 ------ fcst/linux-patches/23-softirq | 33 -- fcst/linux-patches/24-softirq | 33 -- fcst/linux-patches/25-fip-union | 26 - fcst/linux-patches/26-exch-alloc2 | 71 --- fcst/linux-patches/series-2.6.33-rc8 | 15 - fcst/linux-patches/series-2.6.34 | 15 - fcst/linux-patches/series-2.6.35 | 7 - fcst/linux-patches/series-2.6.36 | 8 - 30 files changed, 3073 deletions(-) delete mode 100644 fcst/linux-patches/01-prli-clean delete mode 100644 fcst/linux-patches/02-fc4 delete mode 100644 fcst/linux-patches/03-seq-init delete mode 100644 fcst/linux-patches/04-seq-set-resp delete mode 100644 fcst/linux-patches/05-lport-hook delete mode 100644 fcst/linux-patches/06-lport-notify delete mode 100644 fcst/linux-patches/07-pta-mask delete mode 100644 fcst/linux-patches/08-ptp-ref delete mode 100644 fcst/linux-patches/09-ptp-type delete mode 100644 fcst/linux-patches/10-non-fip delete mode 100644 fcst/linux-patches/11-ptp-flogi-recv delete mode 100644 fcst/linux-patches/12-ptp-npiv delete mode 100644 fcst/linux-patches/13-ptp-acc delete mode 100644 fcst/linux-patches/14-fc-frame-sparse-workaround delete mode 100644 fcst/linux-patches/15-fc4 delete mode 100644 fcst/linux-patches/16-seq-set-resp delete mode 100644 fcst/linux-patches/17-lport-hook delete mode 100644 fcst/linux-patches/18-lport-notify delete mode 100644 fcst/linux-patches/19-fc4-v2 delete mode 100644 fcst/linux-patches/20-seq-set-resp delete mode 100644 fcst/linux-patches/21-lport-hook delete mode 100644 fcst/linux-patches/22-lport-notify delete mode 100644 fcst/linux-patches/23-softirq delete mode 100644 fcst/linux-patches/24-softirq delete mode 100644 fcst/linux-patches/25-fip-union delete mode 100644 fcst/linux-patches/26-exch-alloc2 delete mode 100644 fcst/linux-patches/series-2.6.33-rc8 delete mode 100644 fcst/linux-patches/series-2.6.34 delete mode 100644 fcst/linux-patches/series-2.6.35 delete mode 100644 fcst/linux-patches/series-2.6.36 diff --git a/fcst/linux-patches/01-prli-clean b/fcst/linux-patches/01-prli-clean deleted file mode 100644 index a57dc6981..000000000 --- a/fcst/linux-patches/01-prli-clean +++ /dev/null @@ -1,241 +0,0 @@ -libfc: recode incoming PRLI handling - -Reduce indentation in fc_rport_recv_prli_req() using gotos. -Also add payload length checks. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_rport.c | 195 ++++++++++++++++++----------------------- - 1 files changed, 87 insertions(+), 108 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c -index 97923bb..09ec635 100644 ---- a/drivers/scsi/libfc/fc_rport.c -+++ b/drivers/scsi/libfc/fc_rport.c -@@ -1441,136 +1441,115 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - struct fc_els_spp *spp; /* response spp */ - unsigned int len; - unsigned int plen; -- enum fc_els_rjt_reason reason = ELS_RJT_UNAB; -- enum fc_els_rjt_explan explan = ELS_EXPL_NONE; - enum fc_els_spp_resp resp; - struct fc_seq_els_data rjt_data; - u32 f_ctl; - u32 fcp_parm; - u32 roles = FC_RPORT_ROLE_UNKNOWN; -- rjt_data.fp = NULL; - -+ rjt_data.fp = NULL; - fh = fc_frame_header_get(rx_fp); - - FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", - fc_rport_state(rdata)); - -- switch (rdata->rp_state) { -- case RPORT_ST_PRLI: -- case RPORT_ST_RTV: -- case RPORT_ST_READY: -- case RPORT_ST_ADISC: -- reason = ELS_RJT_NONE; -- break; -- default: -- fc_frame_free(rx_fp); -- return; -- break; -- } - len = fr_len(rx_fp) - sizeof(*fh); - pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); -- if (pp == NULL) { -- reason = ELS_RJT_PROT; -- explan = ELS_EXPL_INV_LEN; -- } else { -- plen = ntohs(pp->prli.prli_len); -- if ((plen % 4) != 0 || plen > len) { -- reason = ELS_RJT_PROT; -- explan = ELS_EXPL_INV_LEN; -- } else if (plen < len) { -- len = plen; -- } -- plen = pp->prli.prli_spp_len; -- if ((plen % 4) != 0 || plen < sizeof(*spp) || -- plen > len || len < sizeof(*pp)) { -- reason = ELS_RJT_PROT; -- explan = ELS_EXPL_INV_LEN; -- } -- rspp = &pp->spp; -+ if (!pp) -+ goto reject_len; -+ plen = ntohs(pp->prli.prli_len); -+ if ((plen % 4) != 0 || plen > len || plen < 16) -+ goto reject_len; -+ if (plen < len) -+ len = plen; -+ plen = pp->prli.prli_spp_len; -+ if ((plen % 4) != 0 || plen < sizeof(*spp) || -+ plen > len || len < sizeof(*pp) || plen < 12) -+ goto reject_len; -+ rspp = &pp->spp; -+ -+ fp = fc_frame_alloc(lport, len); -+ if (!fp) { -+ rjt_data.reason = ELS_RJT_UNAB; -+ rjt_data.explan = ELS_EXPL_INSUF_RES; -+ goto reject; - } -- if (reason != ELS_RJT_NONE || -- (fp = fc_frame_alloc(lport, len)) == NULL) { -- rjt_data.reason = reason; -- rjt_data.explan = explan; -- lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); -- } else { -- sp = lport->tt.seq_start_next(sp); -- WARN_ON(!sp); -- pp = fc_frame_payload_get(fp, len); -- WARN_ON(!pp); -- memset(pp, 0, len); -- pp->prli.prli_cmd = ELS_LS_ACC; -- pp->prli.prli_spp_len = plen; -- pp->prli.prli_len = htons(len); -- len -= sizeof(struct fc_els_prli); -- -- /* reinitialize remote port roles */ -- rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -- -- /* -- * Go through all the service parameter pages and build -- * response. If plen indicates longer SPP than standard, -- * use that. The entire response has been pre-cleared above. -- */ -- spp = &pp->spp; -- while (len >= plen) { -- spp->spp_type = rspp->spp_type; -- spp->spp_type_ext = rspp->spp_type_ext; -- spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -- resp = FC_SPP_RESP_ACK; -- if (rspp->spp_flags & FC_SPP_RPA_VAL) -- resp = FC_SPP_RESP_NO_PA; -- switch (rspp->spp_type) { -- case 0: /* common to all FC-4 types */ -- break; -- case FC_TYPE_FCP: -- fcp_parm = ntohl(rspp->spp_params); -- if (fcp_parm & FCP_SPPF_RETRY) -- rdata->flags |= FC_RP_FLAGS_RETRY; -- rdata->supported_classes = FC_COS_CLASS3; -- if (fcp_parm & FCP_SPPF_INIT_FCN) -- roles |= FC_RPORT_ROLE_FCP_INITIATOR; -- if (fcp_parm & FCP_SPPF_TARG_FCN) -- roles |= FC_RPORT_ROLE_FCP_TARGET; -- rdata->ids.roles = roles; -- -- spp->spp_params = -- htonl(lport->service_params); -- break; -- default: -- resp = FC_SPP_RESP_INVL; -- break; -- } -- spp->spp_flags |= resp; -- len -= plen; -- rspp = (struct fc_els_spp *)((char *)rspp + plen); -- spp = (struct fc_els_spp *)((char *)spp + plen); -- } -+ sp = lport->tt.seq_start_next(sp); -+ WARN_ON(!sp); -+ pp = fc_frame_payload_get(fp, len); -+ WARN_ON(!pp); -+ memset(pp, 0, len); -+ pp->prli.prli_cmd = ELS_LS_ACC; -+ pp->prli.prli_spp_len = plen; -+ pp->prli.prli_len = htons(len); -+ len -= sizeof(struct fc_els_prli); - -- /* -- * Send LS_ACC. If this fails, the originator should retry. -- */ -- f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; -- f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; -- ep = fc_seq_exch(sp); -- fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, -- FC_TYPE_ELS, f_ctl, 0); -- lport->tt.seq_send(lport, sp, fp); -+ /* reinitialize remote port roles */ -+ rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; - -- /* -- * Get lock and re-check state. -- */ -- switch (rdata->rp_state) { -- case RPORT_ST_PRLI: -- fc_rport_enter_ready(rdata); -+ /* -+ * Go through all the service parameter pages and build -+ * response. If plen indicates longer SPP than standard, -+ * use that. The entire response has been pre-cleared above. -+ */ -+ spp = &pp->spp; -+ while (len >= plen) { -+ spp->spp_type = rspp->spp_type; -+ spp->spp_type_ext = rspp->spp_type_ext; -+ spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -+ resp = FC_SPP_RESP_ACK; -+ -+ switch (rspp->spp_type) { -+ case 0: /* common to all FC-4 types */ - break; -- case RPORT_ST_READY: -- case RPORT_ST_ADISC: -+ case FC_TYPE_FCP: -+ fcp_parm = ntohl(rspp->spp_params); -+ if (fcp_parm & FCP_SPPF_RETRY) -+ rdata->flags |= FC_RP_FLAGS_RETRY; -+ rdata->supported_classes = FC_COS_CLASS3; -+ if (fcp_parm & FCP_SPPF_INIT_FCN) -+ roles |= FC_RPORT_ROLE_FCP_INITIATOR; -+ if (fcp_parm & FCP_SPPF_TARG_FCN) -+ roles |= FC_RPORT_ROLE_FCP_TARGET; -+ rdata->ids.roles = roles; -+ -+ spp->spp_params = htonl(lport->service_params); - break; - default: -+ resp = FC_SPP_RESP_INVL; - break; - } -+ spp->spp_flags |= resp; -+ len -= plen; -+ rspp = (struct fc_els_spp *)((char *)rspp + plen); -+ spp = (struct fc_els_spp *)((char *)spp + plen); -+ } -+ -+ /* -+ * Send LS_ACC. If this fails, the originator should retry. -+ */ -+ f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; -+ f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; -+ ep = fc_seq_exch(sp); -+ fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, -+ FC_TYPE_ELS, f_ctl, 0); -+ lport->tt.seq_send(lport, sp, fp); -+ -+ switch (rdata->rp_state) { -+ case RPORT_ST_PRLI: -+ fc_rport_enter_ready(rdata); -+ break; -+ default: -+ break; - } -+ goto drop; -+ -+reject_len: -+ rjt_data.reason = ELS_RJT_PROT; -+ rjt_data.explan = ELS_EXPL_INV_LEN; -+reject: -+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); -+drop: - fc_frame_free(rx_fp); - } - diff --git a/fcst/linux-patches/02-fc4 b/fcst/linux-patches/02-fc4 deleted file mode 100644 index ecc677c67..000000000 --- a/fcst/linux-patches/02-fc4 +++ /dev/null @@ -1,487 +0,0 @@ -libfc: add hook for FC-4 provider registration - -Allow FC-4 provider modules to hook into libfc, mostly for targets. -This should allow any FC-4 module to handle PRLI requests and maintain -process-association states. - -Each provider registers its ops with libfc and then will be called for -any incoming PRLI for that FC-4 type on any instance. The provider -can decide whether to handle that particular instance using any method -it likes, such as ACLs or other configuration information. - -A count is kept of the number of successful PRLIs from the remote port. -Providers are called back with an implicit PRLO when the remote port -is about to be deleted or has been reset. - -fc_lport_recv_req() now sends incoming FC-4 requests to FC-4 providers, -and there is a built-in provider always registered for handling -incoming ELS requests. - -The call to provider recv() routines uses rcu_read_lock() -so that providers aren't removed during the call. That lock is very -cheap and shouldn't affect any performance on ELS requests. -Providers can rely on the RCU lock to protect a session lookup as well. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 60 ++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 11 +++ - drivers/scsi/libfc/fc_lport.c | 63 ++++++++++++++++--- - drivers/scsi/libfc/fc_rport.c | 133 +++++++++++++++++++++++++++++++++-------- - include/scsi/libfc.h | 26 ++++++++ - 5 files changed, 255 insertions(+), 38 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index 39f4b6a..ce0de44 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -34,6 +34,23 @@ unsigned int fc_debug_logging; - module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - -+DEFINE_MUTEX(fc_prov_mutex); -+ -+/* -+ * Providers which primarily send requests and PRLIs. -+ */ -+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = { -+ [0] = &fc_rport_t0_prov, -+ [FC_TYPE_FCP] = &fc_rport_fcp_init, -+}; -+ -+/* -+ * Providers which receive requests. -+ */ -+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = { -+ [FC_TYPE_ELS] = &fc_lport_els_prov, -+}; -+ - /** - * libfc_init() - Initialize libfc.ko - */ -@@ -132,3 +149,46 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, - } - return copy_len; - } -+ -+/** -+ * fc_fc4_register_provider() - register FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ struct fc4_prov **prov_entry; -+ int ret = 0; -+ -+ if (type >= FC_FC4_PROV_SIZE) -+ return -EINVAL; -+ mutex_lock(&fc_prov_mutex); -+ prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type; -+ if (*prov_entry) -+ ret = -EBUSY; -+ else -+ *prov_entry = prov; -+ mutex_unlock(&fc_prov_mutex); -+ return ret; -+} -+EXPORT_SYMBOL(fc_fc4_register_provider); -+ -+/** -+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ */ -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ BUG_ON(type >= FC_FC4_PROV_SIZE); -+ mutex_lock(&fc_prov_mutex); -+ if (prov->recv) -+ rcu_assign_pointer(fc_passive_prov[type], NULL); -+ else -+ rcu_assign_pointer(fc_active_prov[type], NULL); -+ mutex_unlock(&fc_prov_mutex); -+ synchronize_rcu(); -+} -+EXPORT_SYMBOL(fc_fc4_deregister_provider); -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index 741fd5c..c3d740c 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -82,6 +82,17 @@ extern unsigned int fc_debug_logging; - (lport)->host->host_no, ##args)) - - /* -+ * FC-4 Providers. -+ */ -+extern struct fc4_prov *fc_active_prov[]; /* providers without recv */ -+extern struct fc4_prov *fc_passive_prov[]; /* providers with recv */ -+extern struct mutex fc_prov_mutex; /* lock over table changes */ -+ -+extern struct fc4_prov fc_rport_t0_prov; /* type 0 provider */ -+extern struct fc4_prov fc_lport_els_prov; /* ELS provider */ -+extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */ -+ -+/* - * Set up direct-data placement for this I/O request - */ - void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index 7ec8ce7..35149f0 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -847,7 +847,7 @@ out: - } - - /** -- * fc_lport_recv_req() - The generic lport request handler -+ * fc_lport_recv_els_req() - The generic lport ELS request handler - * @lport: The local port that received the request - * @sp: The sequence the request is on - * @fp: The request frame -@@ -858,8 +858,8 @@ out: - * Locking Note: This function should not be called with the lport - * lock held becuase it will grab the lock. - */ --static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, -- struct fc_frame *fp) -+static void fc_lport_recv_els_req(struct fc_lport *lport, struct fc_seq *sp, -+ struct fc_frame *fp) - { - struct fc_frame_header *fh = fc_frame_header_get(fp); - void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); -@@ -873,8 +873,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, - */ - if (!lport->link_up) - fc_frame_free(fp); -- else if (fh->fh_type == FC_TYPE_ELS && -- fh->fh_r_ctl == FC_RCTL_ELS_REQ) { -+ else { - /* - * Check opcode. - */ -@@ -903,17 +902,59 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, - } - - recv(sp, fp, lport); -- } else { -- FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", -- fr_eof(fp)); -- fc_frame_free(fp); - } - mutex_unlock(&lport->lp_mutex); -+ lport->tt.exch_done(sp); -+} -+ -+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out) -+{ -+ return FC_SPP_RESP_INVL; -+} -+ -+struct fc4_prov fc_lport_els_prov = { -+ .prli = fc_lport_els_prli, -+ .recv = fc_lport_recv_els_req, -+}; -+ -+/** -+ * fc_lport_recv_req() - The generic lport request handler -+ * @lport: The lport that received the request -+ * @sp: The sequence the request is on -+ * @fp: The frame the request is in -+ * -+ * Locking Note: This function should not be called with the lport -+ * lock held becuase it may grab the lock. -+ */ -+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, -+ struct fc_frame *fp) -+{ -+ struct fc_frame_header *fh = fc_frame_header_get(fp); -+ struct fc4_prov *prov; - - /* -- * The common exch_done for all request may not be good -- * if any request requires longer hold on exhange. XXX -+ * Use RCU read lock and module_lock to be sure module doesn't -+ * deregister and get unloaded while we're calling it. -+ * try_module_get() is inlined and accepts a NULL parameter. -+ * Only ELSes and FCP target ops should come through here. -+ * The locking is unfortunate, and a better scheme is being sought. - */ -+ rcu_read_lock(); -+ if (fh->fh_type >= FC_FC4_PROV_SIZE) -+ goto drop; -+ prov = rcu_dereference(fc_passive_prov[fh->fh_type]); -+ if (!prov || !try_module_get(prov->module)) -+ goto drop; -+ rcu_read_unlock(); -+ prov->recv(lport, sp, fp); -+ module_put(prov->module); -+ return; -+drop: -+ rcu_read_unlock(); -+ FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type); -+ fc_frame_free(fp); - lport->tt.exch_done(sp); - } - -diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c -index 09ec635..3713060 100644 ---- a/drivers/scsi/libfc/fc_rport.c -+++ b/drivers/scsi/libfc/fc_rport.c -@@ -245,6 +245,8 @@ static void fc_rport_work(struct work_struct *work) - struct fc_rport_operations *rport_ops; - struct fc_rport_identifiers ids; - struct fc_rport *rport; -+ struct fc4_prov *prov; -+ u8 type; - int restart = 0; - - mutex_lock(&rdata->rp_mutex); -@@ -294,6 +296,15 @@ static void fc_rport_work(struct work_struct *work) - case RPORT_EV_FAILED: - case RPORT_EV_LOGO: - case RPORT_EV_STOP: -+ if (rdata->prli_count) { -+ mutex_lock(&fc_prov_mutex); -+ for (type = 1; type < FC_FC4_PROV_SIZE; type++) { -+ prov = fc_passive_prov[type]; -+ if (prov && prov->prlo) -+ prov->prlo(rdata); -+ } -+ mutex_unlock(&fc_prov_mutex); -+ } - port_id = rdata->ids.port_id; - mutex_unlock(&rdata->rp_mutex); - -@@ -1433,6 +1444,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - struct fc_exch *ep; - struct fc_frame *fp; - struct fc_frame_header *fh; -+ struct fc4_prov *prov; - struct { - struct fc_els_prli prli; - struct fc_els_spp spp; -@@ -1442,10 +1454,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - unsigned int len; - unsigned int plen; - enum fc_els_spp_resp resp; -+ enum fc_els_spp_resp passive; - struct fc_seq_els_data rjt_data; - u32 f_ctl; -- u32 fcp_parm; -- u32 roles = FC_RPORT_ROLE_UNKNOWN; - - rjt_data.fp = NULL; - fh = fc_frame_header_get(rx_fp); -@@ -1484,46 +1495,41 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - pp->prli.prli_len = htons(len); - len -= sizeof(struct fc_els_prli); - -- /* reinitialize remote port roles */ -- rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -- - /* - * Go through all the service parameter pages and build - * response. If plen indicates longer SPP than standard, - * use that. The entire response has been pre-cleared above. - */ - spp = &pp->spp; -+ mutex_lock(&fc_prov_mutex); - while (len >= plen) { - spp->spp_type = rspp->spp_type; - spp->spp_type_ext = rspp->spp_type_ext; -- spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -- resp = FC_SPP_RESP_ACK; -- -- switch (rspp->spp_type) { -- case 0: /* common to all FC-4 types */ -- break; -- case FC_TYPE_FCP: -- fcp_parm = ntohl(rspp->spp_params); -- if (fcp_parm & FCP_SPPF_RETRY) -- rdata->flags |= FC_RP_FLAGS_RETRY; -- rdata->supported_classes = FC_COS_CLASS3; -- if (fcp_parm & FCP_SPPF_INIT_FCN) -- roles |= FC_RPORT_ROLE_FCP_INITIATOR; -- if (fcp_parm & FCP_SPPF_TARG_FCN) -- roles |= FC_RPORT_ROLE_FCP_TARGET; -- rdata->ids.roles = roles; -- -- spp->spp_params = htonl(lport->service_params); -- break; -- default: -- resp = FC_SPP_RESP_INVL; -- break; -+ resp = 0; -+ -+ if (rspp->spp_type < FC_FC4_PROV_SIZE) { -+ prov = fc_active_prov[rspp->spp_type]; -+ if (prov) -+ resp = prov->prli(rdata, plen, rspp, spp); -+ prov = fc_passive_prov[rspp->spp_type]; -+ if (prov) { -+ passive = prov->prli(rdata, plen, rspp, spp); -+ if (!resp || passive == FC_SPP_RESP_ACK) -+ resp = passive; -+ } -+ } -+ if (!resp) { -+ if (spp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ resp |= FC_SPP_RESP_CONF; -+ else -+ resp |= FC_SPP_RESP_INVL; - } - spp->spp_flags |= resp; - len -= plen; - rspp = (struct fc_els_spp *)((char *)rspp + plen); - spp = (struct fc_els_spp *)((char *)spp + plen); - } -+ mutex_unlock(&fc_prov_mutex); - - /* - * Send LS_ACC. If this fails, the originator should retry. -@@ -1668,6 +1674,79 @@ int fc_rport_init(struct fc_lport *lport) - EXPORT_SYMBOL(fc_rport_init); - - /** -+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator. -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ * -+ * Returns the value for the response code to be placed in spp_flags; -+ * Returns 0 if not an initiator. -+ */ -+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ struct fc_lport *lport = rdata->local_port; -+ u32 fcp_parm; -+ -+ fcp_parm = ntohl(rspp->spp_params); -+ rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -+ if (fcp_parm & FCP_SPPF_INIT_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; -+ if (fcp_parm & FCP_SPPF_TARG_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET; -+ if (fcp_parm & FCP_SPPF_RETRY) -+ rdata->flags |= FC_RP_FLAGS_RETRY; -+ rdata->supported_classes = FC_COS_CLASS3; -+ -+ if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR)) -+ return 0; -+ -+ spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -+ -+ /* -+ * OR in our service parameters with other providers (target), if any. -+ */ -+ fcp_parm = ntohl(spp->spp_params); -+ spp->spp_params = htonl(fcp_parm | lport->service_params); -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for FCP initiator. -+ */ -+struct fc4_prov fc_rport_fcp_init = { -+ .prli = fc_rport_fcp_prli, -+}; -+ -+/** -+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0 -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ */ -+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ return FC_SPP_RESP_INVL; -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for type 0 service parameters. -+ * -+ * This handles the special case of type 0 which is always successful -+ * but doesn't do anything otherwise. -+ */ -+struct fc4_prov fc_rport_t0_prov = { -+ .prli = fc_rport_t0_prli, -+}; -+ -+/** - * fc_setup_rport() - Initialize the rport_event_queue - */ - int fc_setup_rport() -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 4b912ee..9403d4e 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -35,6 +35,8 @@ - - #include - -+#define FC_FC4_PROV_SIZE (FC_TYPE_FCP + 1) /* size of tables */ -+ - /* - * libfc error codes - */ -@@ -190,6 +192,7 @@ struct fc_rport_libfc_priv { - * @rp_mutex: The mutex that protects the remote port - * @retry_work: Handle for retries - * @event_callback: Callback when READY, FAILED or LOGO states complete -+ * @prli_count: Count of open PRLI sessions in providers - */ - struct fc_rport_priv { - struct fc_lport *local_port; -@@ -211,6 +214,7 @@ struct fc_rport_priv { - struct list_head peers; - struct work_struct event_work; - u32 supported_classes; -+ u16 prli_count; - }; - - /** -@@ -850,6 +854,28 @@ struct fc_lport { - struct delayed_work retry_work; - }; - -+/** -+ * struct fc4_prov - FC-4 provider registration -+ * @prli: Handler for incoming PRLI -+ * @prlo: Handler for session reset -+ * @recv: Handler for incoming request -+ * @module: Pointer to module. May be NULL. -+ */ -+struct fc4_prov { -+ int (*prli)(struct fc_rport_priv *, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out); -+ void (*prlo)(struct fc_rport_priv *); -+ void (*recv)(struct fc_lport *, struct fc_seq *, struct fc_frame *); -+ struct module *module; -+}; -+ -+/* -+ * Register FC-4 provider with libfc. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *); -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *); -+ - /* - * FC_LPORT HELPER FUNCTIONS - *****************************/ diff --git a/fcst/linux-patches/03-seq-init b/fcst/linux-patches/03-seq-init deleted file mode 100644 index 86cf85ce5..000000000 --- a/fcst/linux-patches/03-seq-init +++ /dev/null @@ -1,31 +0,0 @@ -libfc: fix sequence-initiative WARN in fc_seq_start_next - -The target code was getting a warning that sequence initiative -wasn't held when starting the response sequence after sending -the data sequence. - -The bug was that sequence initiative was cleared due to the -END_SEQ flag being on. The intent may have been to check LAST_SEQ. -Change just to check SEQ_INIT. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_exch.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c -index 7f43647..1ad1ded 100644 ---- a/drivers/scsi/libfc/fc_exch.c -+++ b/drivers/scsi/libfc/fc_exch.c -@@ -488,7 +488,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, - */ - spin_lock_bh(&ep->ex_lock); - ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */ -- if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) -+ if (f_ctl & FC_FC_SEQ_INIT) - ep->esb_stat &= ~ESB_ST_SEQ_INIT; - spin_unlock_bh(&ep->ex_lock); - return error; diff --git a/fcst/linux-patches/04-seq-set-resp b/fcst/linux-patches/04-seq-set-resp deleted file mode 100644 index 22abfca34..000000000 --- a/fcst/linux-patches/04-seq-set-resp +++ /dev/null @@ -1,84 +0,0 @@ -libfc: add method for setting handler for incoming exchange - -Add a method for setting handler for incoming exchange. -For multi-sequence exchanges, this allows the target driver -to add a response handler for handling subsequent sequences, -and exchange manager resets. - -The new function is called fc_seq_set_resp(). - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_exch.c | 19 +++++++++++++++++++ - include/scsi/libfc.h | 11 ++++++++++- - 2 files changed, 29 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c -index 1ad1ded..aee3c59 100644 ---- a/drivers/scsi/libfc/fc_exch.c -+++ b/drivers/scsi/libfc/fc_exch.c -@@ -545,6 +545,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) - return sp; - } - -+/* -+ * Set the response handler for the exchange associated with a sequence. -+ */ -+static void fc_seq_set_resp(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg) -+{ -+ struct fc_exch *ep = fc_seq_exch(sp); -+ -+ spin_lock_bh(&ep->ex_lock); -+ ep->resp = resp; -+ ep->arg = arg; -+ spin_unlock_bh(&ep->ex_lock); -+} -+ - /** - * fc_seq_exch_abort() - Abort an exchange and sequence - * @req_sp: The sequence to be aborted -@@ -2280,6 +2296,9 @@ int fc_exch_init(struct fc_lport *lport) - if (!lport->tt.seq_start_next) - lport->tt.seq_start_next = fc_seq_start_next; - -+ if (!lport->tt.seq_set_resp) -+ lport->tt.seq_set_resp = fc_seq_set_resp; -+ - if (!lport->tt.exch_seq_send) - lport->tt.exch_seq_send = fc_exch_seq_send; - -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 9403d4e..87204da 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -566,6 +566,16 @@ struct libfc_function_template { - struct fc_seq *(*seq_start_next)(struct fc_seq *); - - /* -+ * Set a response handler for the exchange of the sequence. -+ * -+ * STATUS: OPTIONAL -+ */ -+ void (*seq_set_resp)(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg); -+ -+ /* - * Reset an exchange manager, completing all sequences and exchanges. - * If s_id is non-zero, reset only exchanges originating from that FID. - * If d_id is non-zero, reset only exchanges sending to that FID. -@@ -1058,7 +1068,6 @@ struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did, - void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); - void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); - -- - /* - * EXCHANGE MANAGER LAYER - *****************************/ diff --git a/fcst/linux-patches/05-lport-hook b/fcst/linux-patches/05-lport-hook deleted file mode 100644 index 0b59bc34f..000000000 --- a/fcst/linux-patches/05-lport-hook +++ /dev/null @@ -1,36 +0,0 @@ -libfc: add local port hook for provider session lookup - -The target provider needs a per-instance lookup table -or other way to lookup sessions quickly without going through -a linear list or serializing too much. - -Add a simple void * array indexed by FC-4 type to the fc_lport. - -Signed-off-by: Joe Eykholt - ---- - include/scsi/libfc.h | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - - ---- -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 87204da..6817fe3 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -810,6 +810,7 @@ struct fc_disc { - * @lp_mutex: Mutex to protect the local port - * @list: Handle for list of local ports - * @retry_work: Handle to local port for delayed retry context -+ * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { - /* Associations */ -@@ -862,6 +863,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ void *prov[FC_FC4_PROV_SIZE]; - }; - - /** diff --git a/fcst/linux-patches/06-lport-notify b/fcst/linux-patches/06-lport-notify deleted file mode 100644 index 015c12e5f..000000000 --- a/fcst/linux-patches/06-lport-notify +++ /dev/null @@ -1,167 +0,0 @@ -libfc: add hook to notify providers of local port changes - -When an SCST provider is registered, it needs to know what -local ports are available for configuration as targets. - -Add a notifier chain that is invoked when any local port -that is added or deleted. - -Maintain a global list of local ports and add an -interator function that calls a given function for -every existing local port. This is used when first -loading a provider. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 41 +++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 2 ++ - drivers/scsi/libfc/fc_lport.c | 2 ++ - include/scsi/libfc.h | 14 +++++++++++++- - 4 files changed, 58 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index ce0de44..abd108a 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -35,6 +35,10 @@ module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - - DEFINE_MUTEX(fc_prov_mutex); -+static LIST_HEAD(fc_local_ports); -+struct blocking_notifier_head fc_lport_notifier_head = -+ BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head); -+EXPORT_SYMBOL(fc_lport_notifier_head); - - /* - * Providers which primarily send requests and PRLIs. -@@ -150,6 +154,17 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, - return copy_len; - } - -+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg) -+{ -+ struct fc_lport *lport; -+ -+ mutex_lock(&fc_prov_mutex); -+ list_for_each_entry(lport, &fc_local_ports, lport_list) -+ notify(lport, arg); -+ mutex_unlock(&fc_prov_mutex); -+} -+EXPORT_SYMBOL(fc_lport_iterate); -+ - /** - * fc_fc4_register_provider() - register FC-4 upper-level provider. - * @type: FC-4 type, such as FC_TYPE_FCP -@@ -192,3 +207,29 @@ void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) - synchronize_rcu(); - } - EXPORT_SYMBOL(fc_fc4_deregister_provider); -+ -+/** -+ * fc_fc4_add_lport() - add new local port to list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_add_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_add_tail(&lport->lport_list, &fc_local_ports); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_ADD, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -+ -+/** -+ * fc_fc4_del_lport() - remove local port from list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_del_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_del(&lport->lport_list); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_DEL, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index c3d740c..1bde8e2 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -111,6 +111,8 @@ void fc_destroy_fcp(void); - * Internal libfc functions - */ - const char *fc_els_resp_type(struct fc_frame *); -+extern void fc_fc4_add_lport(struct fc_lport *); -+extern void fc_fc4_del_lport(struct fc_lport *); - - /* - * Copies a buffer into an sg list -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index 35149f0..507b6c5 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -654,6 +654,7 @@ int fc_lport_destroy(struct fc_lport *lport) - lport->tt.fcp_abort_io(lport); - lport->tt.disc_stop_final(lport); - lport->tt.exch_mgr_reset(lport, 0, 0); -+ fc_fc4_del_lport(lport); - return 0; - } - EXPORT_SYMBOL(fc_lport_destroy); -@@ -1638,6 +1639,7 @@ int fc_lport_init(struct fc_lport *lport) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT; - if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; -+ fc_fc4_add_lport(lport); - - return 0; - } -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 6817fe3..12fe787 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -770,6 +770,15 @@ struct fc_disc { - enum fc_disc_event); - }; - -+/* -+ * Local port notifier and events. -+ */ -+extern struct blocking_notifier_head fc_lport_notifier_head; -+enum fc_lport_event { -+ FC_LPORT_EV_ADD, -+ FC_LPORT_EV_DEL, -+}; -+ - /** - * struct fc_lport - Local port - * @host: The SCSI host associated with a local port -@@ -808,8 +817,9 @@ struct fc_disc { - * @lso_max: The maximum large offload send size - * @fcts: FC-4 type mask - * @lp_mutex: Mutex to protect the local port -- * @list: Handle for list of local ports -+ * @list: Linkage on list of vport peers - * @retry_work: Handle to local port for delayed retry context -+ * @lport_list: Linkage on module-wide list of local ports - * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { -@@ -863,6 +873,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ struct list_head lport_list; - void *prov[FC_FC4_PROV_SIZE]; - }; - -@@ -1026,6 +1037,7 @@ int fc_set_mfs(struct fc_lport *, u32 mfs); - struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); - struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); - int fc_lport_bsg_request(struct fc_bsg_job *); -+void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); - - /* - * REMOTE PORT LAYER diff --git a/fcst/linux-patches/07-pta-mask b/fcst/linux-patches/07-pta-mask deleted file mode 100644 index 2f496d9e7..000000000 --- a/fcst/linux-patches/07-pta-mask +++ /dev/null @@ -1,25 +0,0 @@ -libfc: add definition for task attribute mask - -The FCP command header definition should define a mask for -the task attribute field. This adds that #define. - -Signed-off-by: Joe Eykholt - ---- - include/scsi/fc/fc_fcp.h | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - - ---- -diff --git a/include/scsi/fc/fc_fcp.h b/include/scsi/fc/fc_fcp.h -index 747e2c7..8e9b222 100644 ---- a/include/scsi/fc/fc_fcp.h -+++ b/include/scsi/fc/fc_fcp.h -@@ -76,6 +76,7 @@ struct fcp_cmnd32 { - #define FCP_PTA_HEADQ 1 /* head of queue task attribute */ - #define FCP_PTA_ORDERED 2 /* ordered task attribute */ - #define FCP_PTA_ACA 4 /* auto. contigent allegiance */ -+#define FCP_PTA_MASK 7 /* mask for task attribute field */ - #define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */ - #define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */ - diff --git a/fcst/linux-patches/08-ptp-ref b/fcst/linux-patches/08-ptp-ref deleted file mode 100644 index cf23c6b82..000000000 --- a/fcst/linux-patches/08-ptp-ref +++ /dev/null @@ -1,49 +0,0 @@ -libfc: fix oops in point-to-point mode - -In point-to-point mode, if the PLOGI to the remote port times -out, it can get deleted by the remote port module. Since there's -no reference by the local port, lport->ptp_data points to a freed -rport, and when the local port is reset and tries to logout again, -an oops occurs in mutex_lock_nested(). - -Hold a reference count on the point-to-point rdata. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_lport.c | 11 +++++++++-- - 1 files changed, 9 insertions(+), 2 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index 507b6c5..a728e99 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -227,9 +227,12 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, - u64 remote_wwnn) - { - mutex_lock(&lport->disc.disc_mutex); -- if (lport->ptp_rdata) -+ if (lport->ptp_rdata) { - lport->tt.rport_logoff(lport->ptp_rdata); -+ kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); -+ } - lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); -+ kref_get(&lport->ptp_rdata->kref); - lport->ptp_rdata->ids.port_name = remote_wwpn; - lport->ptp_rdata->ids.node_name = remote_wwnn; - mutex_unlock(&lport->disc.disc_mutex); -@@ -988,7 +991,11 @@ static void fc_lport_reset_locked(struct fc_lport *lport) - if (lport->dns_rdata) - lport->tt.rport_logoff(lport->dns_rdata); - -- lport->ptp_rdata = NULL; -+ if (lport->ptp_rdata) { -+ lport->tt.rport_logoff(lport->ptp_rdata); -+ kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); -+ lport->ptp_rdata = NULL; -+ } - - lport->tt.disc_stop(lport); - diff --git a/fcst/linux-patches/09-ptp-type b/fcst/linux-patches/09-ptp-type deleted file mode 100644 index 07d783f6a..000000000 --- a/fcst/linux-patches/09-ptp-type +++ /dev/null @@ -1,30 +0,0 @@ -fcoe: call fcoe_ctlr_els_send even for ELS responses - -In point-to-point mode, the destination MAC address for -the FLOGI response was zero because the LS_ACC for the FLOGI -wasn't getting intercepted by FIP. - -Change to call fcoe_ctlr_els_send when sending any ELS, -not just requests. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/fcoe.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c -index 2f47ae7..2f3b73c 100644 ---- a/drivers/scsi/fcoe/fcoe.c -+++ b/drivers/scsi/fcoe/fcoe.c -@@ -1443,7 +1443,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) - return 0; - } - -- if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && -+ if (unlikely(fh->fh_type == FC_TYPE_ELS) && - fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) - return 0; - diff --git a/fcst/linux-patches/10-non-fip b/fcst/linux-patches/10-non-fip deleted file mode 100644 index 0501ad42b..000000000 --- a/fcst/linux-patches/10-non-fip +++ /dev/null @@ -1,33 +0,0 @@ -libfcoe: fix debug message entering non-FIP mode - -The debug message that indicated we are using non-FIP mode was -being printed only if we were already in non-FIP mode. -Also changed the message text to make it more clear the mode -is being set, not that the message is indicating how FLOGI -was received. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/libfcoe.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c -index 511cb6b..b2af53f 100644 ---- a/drivers/scsi/fcoe/libfcoe.c -+++ b/drivers/scsi/fcoe/libfcoe.c -@@ -1333,9 +1333,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, - if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) { - memcpy(fip->dest_addr, sa, ETH_ALEN); - fip->map_dest = 0; -- if (fip->state == FIP_ST_NON_FIP) -- LIBFCOE_FIP_DBG(fip, "received FLOGI REQ, " -- "using non-FIP mode\n"); -+ if (fip->state == FIP_ST_AUTO) -+ LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. " -+ "Setting non-FIP mode\n"); - fip->state = FIP_ST_NON_FIP; - } - spin_unlock_bh(&fip->lock); diff --git a/fcst/linux-patches/11-ptp-flogi-recv b/fcst/linux-patches/11-ptp-flogi-recv deleted file mode 100644 index d6b192a1c..000000000 --- a/fcst/linux-patches/11-ptp-flogi-recv +++ /dev/null @@ -1,63 +0,0 @@ -fcoe: save gateway address when receiving FLOGI request - -In point-to-point mode, we need to save the source MAC -from received FLOGI requests to use as the destination MAC -for all outgoing frames. We stopped doing that at some point. - -Use the lport_set_port_id method to catch incoming FLOGI frames -and pass them to fcoe_ctlr_recv_flogi() so it can save the source MAC. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/fcoe.c | 24 ++++++++++++++++++++++++ - 1 files changed, 24 insertions(+), 0 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c -index 2f3b73c..546e69a 100644 ---- a/drivers/scsi/fcoe/fcoe.c -+++ b/drivers/scsi/fcoe/fcoe.c -@@ -145,6 +145,7 @@ static int fcoe_vport_destroy(struct fc_vport *); - static int fcoe_vport_create(struct fc_vport *, bool disabled); - static int fcoe_vport_disable(struct fc_vport *, bool disable); - static void fcoe_set_vport_symbolic_name(struct fc_vport *); -+static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); - - static struct libfc_function_template fcoe_libfc_fcn_templ = { - .frame_send = fcoe_xmit, -@@ -152,6 +153,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { - .ddp_done = fcoe_ddp_done, - .elsct_send = fcoe_elsct_send, - .get_lesb = fcoe_get_lesb, -+ .lport_set_port_id = fcoe_set_port_id, - }; - - struct fc_function_template fcoe_transport_function = { -@@ -2630,3 +2632,25 @@ static void fcoe_get_lesb(struct fc_lport *lport, - lesb->lesb_miss_fka = htonl(mdac); - lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); - } -+ -+/** -+ * fcoe_set_port_id() - Callback from libfc when Port_ID is set. -+ * @lport: the local port -+ * @port_id: the port ID -+ * @fp: the received frame, if any, that caused the port_id to be set. -+ * -+ * This routine handles the case where we received a FLOGI and are -+ * entering point-to-point mode. We need to call fcoe_ctlr_recv_flogi() -+ * so it can set the non-mapped mode and gateway address. -+ * -+ * The FLOGI LS_ACC is handled by fcoe_flogi_resp(). -+ */ -+static void fcoe_set_port_id(struct fc_lport *lport, -+ u32 port_id, struct fc_frame *fp) -+{ -+ struct fcoe_port *port = lport_priv(lport); -+ struct fcoe_interface *fcoe = port->fcoe; -+ -+ if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) -+ fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); -+} diff --git a/fcst/linux-patches/12-ptp-npiv b/fcst/linux-patches/12-ptp-npiv deleted file mode 100644 index 5664ab8da..000000000 --- a/fcst/linux-patches/12-ptp-npiv +++ /dev/null @@ -1,30 +0,0 @@ -libfc: recognize incoming FLOGI for point-to-point mode - -When receiving a FLOGI request from a point-to-point peer, -the D_ID of 0xfffffe was not recognized as belonging to one -of the lports, so it was dropped. - -Change fc_vport_id_lookup() to treat d_id 0xfffffe as a match. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_npiv.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c -index c68f6c7..45b6f1e 100644 ---- a/drivers/scsi/libfc/fc_npiv.c -+++ b/drivers/scsi/libfc/fc_npiv.c -@@ -72,6 +72,9 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id) - if (fc_host_port_id(n_port->host) == port_id) - return n_port; - -+ if (port_id == FC_FID_FLOGI) -+ return n_port; /* for point-to-point */ -+ - mutex_lock(&n_port->lp_mutex); - list_for_each_entry(vn_port, &n_port->vports, list) { - if (fc_host_port_id(vn_port->host) == port_id) { diff --git a/fcst/linux-patches/13-ptp-acc b/fcst/linux-patches/13-ptp-acc deleted file mode 100644 index 8686e5563..000000000 --- a/fcst/linux-patches/13-ptp-acc +++ /dev/null @@ -1,32 +0,0 @@ -libfc: point-to-point: send FLOGI LS_ACC to assigned D_DID - -The method we've been using for point-to-point mode requires -that the LS_ACC for the FLOGI uses the D_ID and S_ID assigned -to the remote port and local port, not those in the exchange. - -This is not the correct method, but for now, it's what works -with the old target, as well as with new targets based on libfc. - -This patch changes the addresses used accordingly. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_lport.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index a728e99..a2a49a2 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -835,7 +835,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, - */ - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; - ep = fc_seq_exch(sp); -- fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, -+ fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, remote_fid, local_fid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); - diff --git a/fcst/linux-patches/14-fc-frame-sparse-workaround b/fcst/linux-patches/14-fc-frame-sparse-workaround deleted file mode 100644 index 7c9ea5881..000000000 --- a/fcst/linux-patches/14-fc-frame-sparse-workaround +++ /dev/null @@ -1,13 +0,0 @@ ---- a/include/scsi/fc_frame.h 2010-06-13 11:08:26.000000000 +0200 -+++ b/include/scsi/fc_frame.h 2010-06-13 11:08:53.000000000 +0200 -@@ -66,8 +66,8 @@ struct fcoe_rcv_info { - struct fc_fcp_pkt *fr_fsp; /* for the corresponding fcp I/O */ - u32 fr_crc; - u16 fr_max_payload; /* max FC payload */ -- enum fc_sof fr_sof; /* start of frame delimiter */ -- enum fc_eof fr_eof; /* end of frame delimiter */ -+ u8 fr_sof; /* start of frame delimiter */ -+ u8 fr_eof; /* end of frame delimiter */ - u8 fr_flags; /* flags - see below */ - u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */ - }; diff --git a/fcst/linux-patches/15-fc4 b/fcst/linux-patches/15-fc4 deleted file mode 100644 index 64c7a7723..000000000 --- a/fcst/linux-patches/15-fc4 +++ /dev/null @@ -1,487 +0,0 @@ -libfc: add hook for FC-4 provider registration - -Allow FC-4 provider modules to hook into libfc, mostly for targets. -This should allow any FC-4 module to handle PRLI requests and maintain -process-association states. - -Each provider registers its ops with libfc and then will be called for -any incoming PRLI for that FC-4 type on any instance. The provider -can decide whether to handle that particular instance using any method -it likes, such as ACLs or other configuration information. - -A count is kept of the number of successful PRLIs from the remote port. -Providers are called back with an implicit PRLO when the remote port -is about to be deleted or has been reset. - -fc_lport_recv_req() now sends incoming FC-4 requests to FC-4 providers, -and there is a built-in provider always registered for handling -incoming ELS requests. - -The call to provider recv() routines uses rcu_read_lock() -so that providers aren't removed during the call. That lock is very -cheap and shouldn't affect any performance on ELS requests. -Providers can rely on the RCU lock to protect a session lookup as well. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 60 ++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 11 +++ - drivers/scsi/libfc/fc_lport.c | 63 ++++++++++++++++--- - drivers/scsi/libfc/fc_rport.c | 133 +++++++++++++++++++++++++++++++++-------- - include/scsi/libfc.h | 26 ++++++++ - 5 files changed, 255 insertions(+), 38 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index 39f4b6a..ce0de44 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -34,6 +34,23 @@ unsigned int fc_debug_logging; - module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - -+DEFINE_MUTEX(fc_prov_mutex); -+ -+/* -+ * Providers which primarily send requests and PRLIs. -+ */ -+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = { -+ [0] = &fc_rport_t0_prov, -+ [FC_TYPE_FCP] = &fc_rport_fcp_init, -+}; -+ -+/* -+ * Providers which receive requests. -+ */ -+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = { -+ [FC_TYPE_ELS] = &fc_lport_els_prov, -+}; -+ - /** - * libfc_init() - Initialize libfc.ko - */ -@@ -132,3 +149,46 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, - } - return copy_len; - } -+ -+/** -+ * fc_fc4_register_provider() - register FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ struct fc4_prov **prov_entry; -+ int ret = 0; -+ -+ if (type >= FC_FC4_PROV_SIZE) -+ return -EINVAL; -+ mutex_lock(&fc_prov_mutex); -+ prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type; -+ if (*prov_entry) -+ ret = -EBUSY; -+ else -+ *prov_entry = prov; -+ mutex_unlock(&fc_prov_mutex); -+ return ret; -+} -+EXPORT_SYMBOL(fc_fc4_register_provider); -+ -+/** -+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ */ -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ BUG_ON(type >= FC_FC4_PROV_SIZE); -+ mutex_lock(&fc_prov_mutex); -+ if (prov->recv) -+ rcu_assign_pointer(fc_passive_prov[type], NULL); -+ else -+ rcu_assign_pointer(fc_active_prov[type], NULL); -+ mutex_unlock(&fc_prov_mutex); -+ synchronize_rcu(); -+} -+EXPORT_SYMBOL(fc_fc4_deregister_provider); -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index f5c0ca4..2323c80 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -82,6 +82,17 @@ extern unsigned int fc_debug_logging; - (lport)->host->host_no, ##args)) - - /* -+ * FC-4 Providers. -+ */ -+extern struct fc4_prov *fc_active_prov[]; /* providers without recv */ -+extern struct fc4_prov *fc_passive_prov[]; /* providers with recv */ -+extern struct mutex fc_prov_mutex; /* lock over table changes */ -+ -+extern struct fc4_prov fc_rport_t0_prov; /* type 0 provider */ -+extern struct fc4_prov fc_lport_els_prov; /* ELS provider */ -+extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */ -+ -+/* - * Set up direct-data placement for this I/O request - */ - void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index 79c9e3c..b05329c 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -844,7 +844,7 @@ out: - } - - /** -- * fc_lport_recv_req() - The generic lport request handler -+ * fc_lport_recv_els_req() - The generic lport ELS request handler - * @lport: The local port that received the request - * @sp: The sequence the request is on - * @fp: The request frame -@@ -855,8 +855,8 @@ out: - * Locking Note: This function should not be called with the lport - * lock held becuase it will grab the lock. - */ --static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, -- struct fc_frame *fp) -+static void fc_lport_recv_els_req(struct fc_lport *lport, struct fc_seq *sp, -+ struct fc_frame *fp) - { - struct fc_frame_header *fh = fc_frame_header_get(fp); - void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); -@@ -870,8 +870,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, - */ - if (!lport->link_up) - fc_frame_free(fp); -- else if (fh->fh_type == FC_TYPE_ELS && -- fh->fh_r_ctl == FC_RCTL_ELS_REQ) { -+ else { - /* - * Check opcode. - */ -@@ -900,17 +899,59 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, - } - - recv(sp, fp, lport); -- } else { -- FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", -- fr_eof(fp)); -- fc_frame_free(fp); - } - mutex_unlock(&lport->lp_mutex); -+ lport->tt.exch_done(sp); -+} -+ -+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out) -+{ -+ return FC_SPP_RESP_INVL; -+} -+ -+struct fc4_prov fc_lport_els_prov = { -+ .prli = fc_lport_els_prli, -+ .recv = fc_lport_recv_els_req, -+}; -+ -+/** -+ * fc_lport_recv_req() - The generic lport request handler -+ * @lport: The lport that received the request -+ * @sp: The sequence the request is on -+ * @fp: The frame the request is in -+ * -+ * Locking Note: This function should not be called with the lport -+ * lock held becuase it may grab the lock. -+ */ -+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, -+ struct fc_frame *fp) -+{ -+ struct fc_frame_header *fh = fc_frame_header_get(fp); -+ struct fc4_prov *prov; - - /* -- * The common exch_done for all request may not be good -- * if any request requires longer hold on exhange. XXX -+ * Use RCU read lock and module_lock to be sure module doesn't -+ * deregister and get unloaded while we're calling it. -+ * try_module_get() is inlined and accepts a NULL parameter. -+ * Only ELSes and FCP target ops should come through here. -+ * The locking is unfortunate, and a better scheme is being sought. - */ -+ rcu_read_lock(); -+ if (fh->fh_type >= FC_FC4_PROV_SIZE) -+ goto drop; -+ prov = rcu_dereference(fc_passive_prov[fh->fh_type]); -+ if (!prov || !try_module_get(prov->module)) -+ goto drop; -+ rcu_read_unlock(); -+ prov->recv(lport, sp, fp); -+ module_put(prov->module); -+ return; -+drop: -+ rcu_read_unlock(); -+ FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type); -+ fc_frame_free(fp); - lport->tt.exch_done(sp); - } - -diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c -index 39e440f..3ec4aa5 100644 ---- a/drivers/scsi/libfc/fc_rport.c -+++ b/drivers/scsi/libfc/fc_rport.c -@@ -246,6 +246,8 @@ static void fc_rport_work(struct work_struct *work) - struct fc_rport_operations *rport_ops; - struct fc_rport_identifiers ids; - struct fc_rport *rport; -+ struct fc4_prov *prov; -+ u8 type; - int restart = 0; - - mutex_lock(&rdata->rp_mutex); -@@ -295,6 +297,15 @@ static void fc_rport_work(struct work_struct *work) - case RPORT_EV_FAILED: - case RPORT_EV_LOGO: - case RPORT_EV_STOP: -+ if (rdata->prli_count) { -+ mutex_lock(&fc_prov_mutex); -+ for (type = 1; type < FC_FC4_PROV_SIZE; type++) { -+ prov = fc_passive_prov[type]; -+ if (prov && prov->prlo) -+ prov->prlo(rdata); -+ } -+ mutex_unlock(&fc_prov_mutex); -+ } - port_id = rdata->ids.port_id; - mutex_unlock(&rdata->rp_mutex); - -@@ -1434,6 +1445,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - struct fc_exch *ep; - struct fc_frame *fp; - struct fc_frame_header *fh; -+ struct fc4_prov *prov; - struct { - struct fc_els_prli prli; - struct fc_els_spp spp; -@@ -1443,10 +1455,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - unsigned int len; - unsigned int plen; - enum fc_els_spp_resp resp; -+ enum fc_els_spp_resp passive; - struct fc_seq_els_data rjt_data; - u32 f_ctl; -- u32 fcp_parm; -- u32 roles = FC_RPORT_ROLE_UNKNOWN; - - rjt_data.fp = NULL; - fh = fc_frame_header_get(rx_fp); -@@ -1485,46 +1496,41 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - pp->prli.prli_len = htons(len); - len -= sizeof(struct fc_els_prli); - -- /* reinitialize remote port roles */ -- rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -- - /* - * Go through all the service parameter pages and build - * response. If plen indicates longer SPP than standard, - * use that. The entire response has been pre-cleared above. - */ - spp = &pp->spp; -+ mutex_lock(&fc_prov_mutex); - while (len >= plen) { - spp->spp_type = rspp->spp_type; - spp->spp_type_ext = rspp->spp_type_ext; -- spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -- resp = FC_SPP_RESP_ACK; -- -- switch (rspp->spp_type) { -- case 0: /* common to all FC-4 types */ -- break; -- case FC_TYPE_FCP: -- fcp_parm = ntohl(rspp->spp_params); -- if (fcp_parm & FCP_SPPF_RETRY) -- rdata->flags |= FC_RP_FLAGS_RETRY; -- rdata->supported_classes = FC_COS_CLASS3; -- if (fcp_parm & FCP_SPPF_INIT_FCN) -- roles |= FC_RPORT_ROLE_FCP_INITIATOR; -- if (fcp_parm & FCP_SPPF_TARG_FCN) -- roles |= FC_RPORT_ROLE_FCP_TARGET; -- rdata->ids.roles = roles; -- -- spp->spp_params = htonl(lport->service_params); -- break; -- default: -- resp = FC_SPP_RESP_INVL; -- break; -+ resp = 0; -+ -+ if (rspp->spp_type < FC_FC4_PROV_SIZE) { -+ prov = fc_active_prov[rspp->spp_type]; -+ if (prov) -+ resp = prov->prli(rdata, plen, rspp, spp); -+ prov = fc_passive_prov[rspp->spp_type]; -+ if (prov) { -+ passive = prov->prli(rdata, plen, rspp, spp); -+ if (!resp || passive == FC_SPP_RESP_ACK) -+ resp = passive; -+ } -+ } -+ if (!resp) { -+ if (spp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ resp |= FC_SPP_RESP_CONF; -+ else -+ resp |= FC_SPP_RESP_INVL; - } - spp->spp_flags |= resp; - len -= plen; - rspp = (struct fc_els_spp *)((char *)rspp + plen); - spp = (struct fc_els_spp *)((char *)spp + plen); - } -+ mutex_unlock(&fc_prov_mutex); - - /* - * Send LS_ACC. If this fails, the originator should retry. -@@ -1669,6 +1675,79 @@ int fc_rport_init(struct fc_lport *lport) - EXPORT_SYMBOL(fc_rport_init); - - /** -+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator. -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ * -+ * Returns the value for the response code to be placed in spp_flags; -+ * Returns 0 if not an initiator. -+ */ -+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ struct fc_lport *lport = rdata->local_port; -+ u32 fcp_parm; -+ -+ fcp_parm = ntohl(rspp->spp_params); -+ rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -+ if (fcp_parm & FCP_SPPF_INIT_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; -+ if (fcp_parm & FCP_SPPF_TARG_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET; -+ if (fcp_parm & FCP_SPPF_RETRY) -+ rdata->flags |= FC_RP_FLAGS_RETRY; -+ rdata->supported_classes = FC_COS_CLASS3; -+ -+ if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR)) -+ return 0; -+ -+ spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -+ -+ /* -+ * OR in our service parameters with other providers (target), if any. -+ */ -+ fcp_parm = ntohl(spp->spp_params); -+ spp->spp_params = htonl(fcp_parm | lport->service_params); -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for FCP initiator. -+ */ -+struct fc4_prov fc_rport_fcp_init = { -+ .prli = fc_rport_fcp_prli, -+}; -+ -+/** -+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0 -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ */ -+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ return FC_SPP_RESP_INVL; -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for type 0 service parameters. -+ * -+ * This handles the special case of type 0 which is always successful -+ * but doesn't do anything otherwise. -+ */ -+struct fc4_prov fc_rport_t0_prov = { -+ .prli = fc_rport_t0_prli, -+}; -+ -+/** - * fc_setup_rport() - Initialize the rport_event_queue - */ - int fc_setup_rport() -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 7495c0b..4ac290f 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -35,6 +35,8 @@ - - #include - -+#define FC_FC4_PROV_SIZE (FC_TYPE_FCP + 1) /* size of tables */ -+ - /* - * libfc error codes - */ -@@ -195,6 +197,7 @@ struct fc_rport_libfc_priv { - * @rp_mutex: The mutex that protects the remote port - * @retry_work: Handle for retries - * @event_callback: Callback when READY, FAILED or LOGO states complete -+ * @prli_count: Count of open PRLI sessions in providers - */ - struct fc_rport_priv { - struct fc_lport *local_port; -@@ -216,6 +219,7 @@ struct fc_rport_priv { - struct list_head peers; - struct work_struct event_work; - u32 supported_classes; -+ u16 prli_count; - }; - - /** -@@ -857,6 +861,28 @@ struct fc_lport { - struct delayed_work retry_work; - }; - -+/** -+ * struct fc4_prov - FC-4 provider registration -+ * @prli: Handler for incoming PRLI -+ * @prlo: Handler for session reset -+ * @recv: Handler for incoming request -+ * @module: Pointer to module. May be NULL. -+ */ -+struct fc4_prov { -+ int (*prli)(struct fc_rport_priv *, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out); -+ void (*prlo)(struct fc_rport_priv *); -+ void (*recv)(struct fc_lport *, struct fc_seq *, struct fc_frame *); -+ struct module *module; -+}; -+ -+/* -+ * Register FC-4 provider with libfc. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *); -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *); -+ - /* - * FC_LPORT HELPER FUNCTIONS - *****************************/ diff --git a/fcst/linux-patches/16-seq-set-resp b/fcst/linux-patches/16-seq-set-resp deleted file mode 100644 index 00abbb863..000000000 --- a/fcst/linux-patches/16-seq-set-resp +++ /dev/null @@ -1,84 +0,0 @@ -libfc: add method for setting handler for incoming exchange - -Add a method for setting handler for incoming exchange. -For multi-sequence exchanges, this allows the target driver -to add a response handler for handling subsequent sequences, -and exchange manager resets. - -The new function is called fc_seq_set_resp(). - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_exch.c | 19 +++++++++++++++++++ - include/scsi/libfc.h | 11 ++++++++++- - 2 files changed, 29 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c -index 104e0fb..1828d1d 100644 ---- a/drivers/scsi/libfc/fc_exch.c -+++ b/drivers/scsi/libfc/fc_exch.c -@@ -545,6 +545,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) - return sp; - } - -+/* -+ * Set the response handler for the exchange associated with a sequence. -+ */ -+static void fc_seq_set_resp(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg) -+{ -+ struct fc_exch *ep = fc_seq_exch(sp); -+ -+ spin_lock_bh(&ep->ex_lock); -+ ep->resp = resp; -+ ep->arg = arg; -+ spin_unlock_bh(&ep->ex_lock); -+} -+ - /** - * fc_seq_exch_abort() - Abort an exchange and sequence - * @req_sp: The sequence to be aborted -@@ -2263,6 +2279,9 @@ int fc_exch_init(struct fc_lport *lport) - if (!lport->tt.seq_start_next) - lport->tt.seq_start_next = fc_seq_start_next; - -+ if (!lport->tt.seq_set_resp) -+ lport->tt.seq_set_resp = fc_seq_set_resp; -+ - if (!lport->tt.exch_seq_send) - lport->tt.exch_seq_send = fc_exch_seq_send; - -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 4ac290f..64a4756 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -571,6 +571,16 @@ struct libfc_function_template { - struct fc_seq *(*seq_start_next)(struct fc_seq *); - - /* -+ * Set a response handler for the exchange of the sequence. -+ * -+ * STATUS: OPTIONAL -+ */ -+ void (*seq_set_resp)(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg); -+ -+ /* - * Reset an exchange manager, completing all sequences and exchanges. - * If s_id is non-zero, reset only exchanges originating from that FID. - * If d_id is non-zero, reset only exchanges sending to that FID. -@@ -1056,7 +1066,6 @@ struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did, - void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); - void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); - -- - /* - * EXCHANGE MANAGER LAYER - *****************************/ diff --git a/fcst/linux-patches/17-lport-hook b/fcst/linux-patches/17-lport-hook deleted file mode 100644 index 303ada0d7..000000000 --- a/fcst/linux-patches/17-lport-hook +++ /dev/null @@ -1,36 +0,0 @@ -libfc: add local port hook for provider session lookup - -The target provider needs a per-instance lookup table -or other way to lookup sessions quickly without going through -a linear list or serializing too much. - -Add a simple void * array indexed by FC-4 type to the fc_lport. - -Signed-off-by: Joe Eykholt - ---- - include/scsi/libfc.h | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - - ---- -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 64a4756..9d7c8e3 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -816,6 +816,7 @@ struct fc_disc { - * @lp_mutex: Mutex to protect the local port - * @list: Handle for list of local ports - * @retry_work: Handle to local port for delayed retry context -+ * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { - /* Associations */ -@@ -869,6 +870,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ void *prov[FC_FC4_PROV_SIZE]; - }; - - /** diff --git a/fcst/linux-patches/18-lport-notify b/fcst/linux-patches/18-lport-notify deleted file mode 100644 index 23c9dd1c0..000000000 --- a/fcst/linux-patches/18-lport-notify +++ /dev/null @@ -1,167 +0,0 @@ -libfc: add hook to notify providers of local port changes - -When an SCST provider is registered, it needs to know what -local ports are available for configuration as targets. - -Add a notifier chain that is invoked when any local port -that is added or deleted. - -Maintain a global list of local ports and add an -interator function that calls a given function for -every existing local port. This is used when first -loading a provider. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 41 +++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 2 ++ - drivers/scsi/libfc/fc_lport.c | 2 ++ - include/scsi/libfc.h | 14 +++++++++++++- - 4 files changed, 58 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index ce0de44..abd108a 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -35,6 +35,10 @@ module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - - DEFINE_MUTEX(fc_prov_mutex); -+static LIST_HEAD(fc_local_ports); -+struct blocking_notifier_head fc_lport_notifier_head = -+ BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head); -+EXPORT_SYMBOL(fc_lport_notifier_head); - - /* - * Providers which primarily send requests and PRLIs. -@@ -150,6 +154,17 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, - return copy_len; - } - -+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg) -+{ -+ struct fc_lport *lport; -+ -+ mutex_lock(&fc_prov_mutex); -+ list_for_each_entry(lport, &fc_local_ports, lport_list) -+ notify(lport, arg); -+ mutex_unlock(&fc_prov_mutex); -+} -+EXPORT_SYMBOL(fc_lport_iterate); -+ - /** - * fc_fc4_register_provider() - register FC-4 upper-level provider. - * @type: FC-4 type, such as FC_TYPE_FCP -@@ -192,3 +207,29 @@ void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) - synchronize_rcu(); - } - EXPORT_SYMBOL(fc_fc4_deregister_provider); -+ -+/** -+ * fc_fc4_add_lport() - add new local port to list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_add_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_add_tail(&lport->lport_list, &fc_local_ports); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_ADD, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -+ -+/** -+ * fc_fc4_del_lport() - remove local port from list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_del_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_del(&lport->lport_list); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_DEL, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index 2323c80..85ce01e 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -111,6 +111,8 @@ void fc_destroy_fcp(void); - * Internal libfc functions - */ - const char *fc_els_resp_type(struct fc_frame *); -+extern void fc_fc4_add_lport(struct fc_lport *); -+extern void fc_fc4_del_lport(struct fc_lport *); - - /* - * Copies a buffer into an sg list -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index b05329c..375a2a7 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -647,6 +647,7 @@ int fc_lport_destroy(struct fc_lport *lport) - lport->tt.fcp_abort_io(lport); - lport->tt.disc_stop_final(lport); - lport->tt.exch_mgr_reset(lport, 0, 0); -+ fc_fc4_del_lport(lport); - return 0; - } - EXPORT_SYMBOL(fc_lport_destroy); -@@ -1639,6 +1640,7 @@ int fc_lport_init(struct fc_lport *lport) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT; - if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; -+ fc_fc4_add_lport(lport); - - return 0; - } -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 9d7c8e3..2fa3538 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -775,6 +775,15 @@ struct fc_disc { - enum fc_disc_event); - }; - -+/* -+ * Local port notifier and events. -+ */ -+extern struct blocking_notifier_head fc_lport_notifier_head; -+enum fc_lport_event { -+ FC_LPORT_EV_ADD, -+ FC_LPORT_EV_DEL, -+}; -+ - /** - * struct fc_lport - Local port - * @host: The SCSI host associated with a local port -@@ -814,8 +823,9 @@ struct fc_disc { - * @lso_max: The maximum large offload send size - * @fcts: FC-4 type mask - * @lp_mutex: Mutex to protect the local port -- * @list: Handle for list of local ports -+ * @list: Linkage on list of vport peers - * @retry_work: Handle to local port for delayed retry context -+ * @lport_list: Linkage on module-wide list of local ports - * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { -@@ -870,6 +880,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ struct list_head lport_list; - void *prov[FC_FC4_PROV_SIZE]; - }; - -@@ -1024,6 +1035,7 @@ int fc_set_mfs(struct fc_lport *, u32 mfs); - struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); - struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); - int fc_lport_bsg_request(struct fc_bsg_job *); -+void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); - - /* - * REMOTE PORT LAYER diff --git a/fcst/linux-patches/19-fc4-v2 b/fcst/linux-patches/19-fc4-v2 deleted file mode 100644 index b21a6be8f..000000000 --- a/fcst/linux-patches/19-fc4-v2 +++ /dev/null @@ -1,483 +0,0 @@ -libfc: add hook for FC-4 provider registration - -Allow FC-4 provider modules to hook into libfc, mostly for targets. -This should allow any FC-4 module to handle PRLI requests and maintain -process-association states. - -Each provider registers its ops with libfc and then will be called for -any incoming PRLI for that FC-4 type on any instance. The provider -can decide whether to handle that particular instance using any method -it likes, such as ACLs or other configuration information. - -A count is kept of the number of successful PRLIs from the remote port. -Providers are called back with an implicit PRLO when the remote port -is about to be deleted or has been reset. - -fc_lport_recv_req() now sends incoming FC-4 requests to FC-4 providers, -and there is a built-in provider always registered for handling -incoming ELS requests. - -The call to provider recv() routines uses rcu_read_lock() -so that providers aren't removed during the call. That lock is very -cheap and shouldn't affect any performance on ELS requests. -Providers can rely on the RCU lock to protect a session lookup as well. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 60 ++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 11 +++ - drivers/scsi/libfc/fc_lport.c | 60 ++++++++++++++++-- - drivers/scsi/libfc/fc_rport.c | 133 +++++++++++++++++++++++++++++++++-------- - include/scsi/libfc.h | 26 ++++++++ - 5 files changed, 254 insertions(+), 36 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index 6a48c28..ae3abef 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -35,6 +35,23 @@ unsigned int fc_debug_logging; - module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - -+DEFINE_MUTEX(fc_prov_mutex); -+ -+/* -+ * Providers which primarily send requests and PRLIs. -+ */ -+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = { -+ [0] = &fc_rport_t0_prov, -+ [FC_TYPE_FCP] = &fc_rport_fcp_init, -+}; -+ -+/* -+ * Providers which receive requests. -+ */ -+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = { -+ [FC_TYPE_ELS] = &fc_lport_els_prov, -+}; -+ - /** - * libfc_init() - Initialize libfc.ko - */ -@@ -210,3 +227,46 @@ void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, - fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset); - } - EXPORT_SYMBOL(fc_fill_reply_hdr); -+ -+/** -+ * fc_fc4_register_provider() - register FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ struct fc4_prov **prov_entry; -+ int ret = 0; -+ -+ if (type >= FC_FC4_PROV_SIZE) -+ return -EINVAL; -+ mutex_lock(&fc_prov_mutex); -+ prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type; -+ if (*prov_entry) -+ ret = -EBUSY; -+ else -+ *prov_entry = prov; -+ mutex_unlock(&fc_prov_mutex); -+ return ret; -+} -+EXPORT_SYMBOL(fc_fc4_register_provider); -+ -+/** -+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider. -+ * @type: FC-4 type, such as FC_TYPE_FCP -+ * @prov: structure describing provider including ops vector. -+ */ -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) -+{ -+ BUG_ON(type >= FC_FC4_PROV_SIZE); -+ mutex_lock(&fc_prov_mutex); -+ if (prov->recv) -+ rcu_assign_pointer(fc_passive_prov[type], NULL); -+ else -+ rcu_assign_pointer(fc_active_prov[type], NULL); -+ mutex_unlock(&fc_prov_mutex); -+ synchronize_rcu(); -+} -+EXPORT_SYMBOL(fc_fc4_deregister_provider); -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index 16d2162..a01b80d 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -82,6 +82,17 @@ extern unsigned int fc_debug_logging; - (lport)->host->host_no, ##args)) - - /* -+ * FC-4 Providers. -+ */ -+extern struct fc4_prov *fc_active_prov[]; /* providers without recv */ -+extern struct fc4_prov *fc_passive_prov[]; /* providers with recv */ -+extern struct mutex fc_prov_mutex; /* lock over table changes */ -+ -+extern struct fc4_prov fc_rport_t0_prov; /* type 0 provider */ -+extern struct fc4_prov fc_lport_els_prov; /* ELS provider */ -+extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */ -+ -+/* - * Set up direct-data placement for this I/O request - */ - void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index d9b6e11..eec9d31 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -845,7 +845,7 @@ out: - } - - /** -- * fc_lport_recv_req() - The generic lport request handler -+ * fc_lport_recv_els_req() - The generic lport ELS request handler - * @lport: The local port that received the request - * @fp: The request frame - * -@@ -855,9 +855,8 @@ out: - * Locking Note: This function should not be called with the lport - * lock held becuase it will grab the lock. - */ --static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) -+static void fc_lport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) - { -- struct fc_frame_header *fh = fc_frame_header_get(fp); - void (*recv)(struct fc_lport *, struct fc_frame *); - - mutex_lock(&lport->lp_mutex); -@@ -869,8 +868,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) - */ - if (!lport->link_up) - fc_frame_free(fp); -- else if (fh->fh_type == FC_TYPE_ELS && -- fh->fh_r_ctl == FC_RCTL_ELS_REQ) { -+ else { - /* - * Check opcode. - */ -@@ -899,14 +897,58 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) - } - - recv(lport, fp); -- } else { -- FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", -- fr_eof(fp)); -- fc_frame_free(fp); - } - mutex_unlock(&lport->lp_mutex); - } - -+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out) -+{ -+ return FC_SPP_RESP_INVL; -+} -+ -+struct fc4_prov fc_lport_els_prov = { -+ .prli = fc_lport_els_prli, -+ .recv = fc_lport_recv_els_req, -+}; -+ -+/** -+ * fc_lport_recv_req() - The generic lport request handler -+ * @lport: The lport that received the request -+ * @fp: The frame the request is in -+ * -+ * Locking Note: This function should not be called with the lport -+ * lock held becuase it may grab the lock. -+ */ -+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) -+{ -+ struct fc_frame_header *fh = fc_frame_header_get(fp); -+ struct fc4_prov *prov; -+ -+ /* -+ * Use RCU read lock and module_lock to be sure module doesn't -+ * deregister and get unloaded while we're calling it. -+ * try_module_get() is inlined and accepts a NULL parameter. -+ * Only ELSes and FCP target ops should come through here. -+ * The locking is unfortunate, and a better scheme is being sought. -+ */ -+ rcu_read_lock(); -+ if (fh->fh_type >= FC_FC4_PROV_SIZE) -+ goto drop; -+ prov = rcu_dereference(fc_passive_prov[fh->fh_type]); -+ if (!prov || !try_module_get(prov->module)) -+ goto drop; -+ rcu_read_unlock(); -+ prov->recv(lport, fp); -+ module_put(prov->module); -+ return; -+drop: -+ rcu_read_unlock(); -+ FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type); -+ fc_frame_free(fp); -+} -+ - /** - * fc_lport_reset() - Reset a local port - * @lport: The local port which should be reset -diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c -index b9f2286..9a3f1d3 100644 ---- a/drivers/scsi/libfc/fc_rport.c -+++ b/drivers/scsi/libfc/fc_rport.c -@@ -257,6 +257,8 @@ static void fc_rport_work(struct work_struct *work) - struct fc_rport_operations *rport_ops; - struct fc_rport_identifiers ids; - struct fc_rport *rport; -+ struct fc4_prov *prov; -+ u8 type; - - mutex_lock(&rdata->rp_mutex); - event = rdata->event; -@@ -306,6 +308,15 @@ static void fc_rport_work(struct work_struct *work) - case RPORT_EV_FAILED: - case RPORT_EV_LOGO: - case RPORT_EV_STOP: -+ if (rdata->prli_count) { -+ mutex_lock(&fc_prov_mutex); -+ for (type = 1; type < FC_FC4_PROV_SIZE; type++) { -+ prov = fc_passive_prov[type]; -+ if (prov && prov->prlo) -+ prov->prlo(rdata); -+ } -+ mutex_unlock(&fc_prov_mutex); -+ } - port_id = rdata->ids.port_id; - mutex_unlock(&rdata->rp_mutex); - -@@ -1632,6 +1643,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - { - struct fc_lport *lport = rdata->local_port; - struct fc_frame *fp; -+ struct fc4_prov *prov; - struct { - struct fc_els_prli prli; - struct fc_els_spp spp; -@@ -1641,9 +1653,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - unsigned int len; - unsigned int plen; - enum fc_els_spp_resp resp; -+ enum fc_els_spp_resp passive; - struct fc_seq_els_data rjt_data; -- u32 fcp_parm; -- u32 roles = FC_RPORT_ROLE_UNKNOWN; - - FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", - fc_rport_state(rdata)); -@@ -1677,46 +1688,41 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - pp->prli.prli_len = htons(len); - len -= sizeof(struct fc_els_prli); - -- /* reinitialize remote port roles */ -- rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -- - /* - * Go through all the service parameter pages and build - * response. If plen indicates longer SPP than standard, - * use that. The entire response has been pre-cleared above. - */ - spp = &pp->spp; -+ mutex_lock(&fc_prov_mutex); - while (len >= plen) { - spp->spp_type = rspp->spp_type; - spp->spp_type_ext = rspp->spp_type_ext; -- spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -- resp = FC_SPP_RESP_ACK; -- -- switch (rspp->spp_type) { -- case 0: /* common to all FC-4 types */ -- break; -- case FC_TYPE_FCP: -- fcp_parm = ntohl(rspp->spp_params); -- if (fcp_parm & FCP_SPPF_RETRY) -- rdata->flags |= FC_RP_FLAGS_RETRY; -- rdata->supported_classes = FC_COS_CLASS3; -- if (fcp_parm & FCP_SPPF_INIT_FCN) -- roles |= FC_RPORT_ROLE_FCP_INITIATOR; -- if (fcp_parm & FCP_SPPF_TARG_FCN) -- roles |= FC_RPORT_ROLE_FCP_TARGET; -- rdata->ids.roles = roles; -- -- spp->spp_params = htonl(lport->service_params); -- break; -- default: -- resp = FC_SPP_RESP_INVL; -- break; -+ resp = 0; -+ -+ if (rspp->spp_type < FC_FC4_PROV_SIZE) { -+ prov = fc_active_prov[rspp->spp_type]; -+ if (prov) -+ resp = prov->prli(rdata, plen, rspp, spp); -+ prov = fc_passive_prov[rspp->spp_type]; -+ if (prov) { -+ passive = prov->prli(rdata, plen, rspp, spp); -+ if (!resp || passive == FC_SPP_RESP_ACK) -+ resp = passive; -+ } -+ } -+ if (!resp) { -+ if (spp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ resp |= FC_SPP_RESP_CONF; -+ else -+ resp |= FC_SPP_RESP_INVL; - } - spp->spp_flags |= resp; - len -= plen; - rspp = (struct fc_els_spp *)((char *)rspp + plen); - spp = (struct fc_els_spp *)((char *)spp + plen); - } -+ mutex_unlock(&fc_prov_mutex); - - /* - * Send LS_ACC. If this fails, the originator should retry. -@@ -1886,6 +1892,79 @@ int fc_rport_init(struct fc_lport *lport) - EXPORT_SYMBOL(fc_rport_init); - - /** -+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator. -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ * -+ * Returns the value for the response code to be placed in spp_flags; -+ * Returns 0 if not an initiator. -+ */ -+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ struct fc_lport *lport = rdata->local_port; -+ u32 fcp_parm; -+ -+ fcp_parm = ntohl(rspp->spp_params); -+ rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; -+ if (fcp_parm & FCP_SPPF_INIT_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; -+ if (fcp_parm & FCP_SPPF_TARG_FCN) -+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET; -+ if (fcp_parm & FCP_SPPF_RETRY) -+ rdata->flags |= FC_RP_FLAGS_RETRY; -+ rdata->supported_classes = FC_COS_CLASS3; -+ -+ if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR)) -+ return 0; -+ -+ spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR; -+ -+ /* -+ * OR in our service parameters with other providers (target), if any. -+ */ -+ fcp_parm = ntohl(spp->spp_params); -+ spp->spp_params = htonl(fcp_parm | lport->service_params); -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for FCP initiator. -+ */ -+struct fc4_prov fc_rport_fcp_init = { -+ .prli = fc_rport_fcp_prli, -+}; -+ -+/** -+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0 -+ * @rdata: remote port private -+ * @spp_len: service parameter page length -+ * @rspp: received service parameter page -+ * @spp: response service parameter page -+ */ -+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len, -+ const struct fc_els_spp *rspp, -+ struct fc_els_spp *spp) -+{ -+ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) -+ return FC_SPP_RESP_INVL; -+ return FC_SPP_RESP_ACK; -+} -+ -+/* -+ * FC-4 provider ops for type 0 service parameters. -+ * -+ * This handles the special case of type 0 which is always successful -+ * but doesn't do anything otherwise. -+ */ -+struct fc4_prov fc_rport_t0_prov = { -+ .prli = fc_rport_t0_prli, -+}; -+ -+/** - * fc_setup_rport() - Initialize the rport_event_queue - */ - int fc_setup_rport() -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 14be49b..8b907e1 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -35,6 +35,8 @@ - - #include - -+#define FC_FC4_PROV_SIZE (FC_TYPE_FCP + 1) /* size of tables */ -+ - /* - * libfc error codes - */ -@@ -179,6 +181,7 @@ struct fc_rport_libfc_priv { - * @rp_mutex: The mutex that protects the remote port - * @retry_work: Handle for retries - * @event_callback: Callback when READY, FAILED or LOGO states complete -+ * @prli_count: Count of open PRLI sessions in providers - * @rcu: Structure used for freeing in an RCU-safe manner - */ - struct fc_rport_priv { -@@ -202,6 +205,7 @@ struct fc_rport_priv { - struct list_head peers; - struct work_struct event_work; - u32 supported_classes; -+ u16 prli_count; - struct rcu_head rcu; - }; - -@@ -850,6 +854,28 @@ struct fc_lport { - struct delayed_work retry_work; - }; - -+/** -+ * struct fc4_prov - FC-4 provider registration -+ * @prli: Handler for incoming PRLI -+ * @prlo: Handler for session reset -+ * @recv: Handler for incoming request -+ * @module: Pointer to module. May be NULL. -+ */ -+struct fc4_prov { -+ int (*prli)(struct fc_rport_priv *, u32 spp_len, -+ const struct fc_els_spp *spp_in, -+ struct fc_els_spp *spp_out); -+ void (*prlo)(struct fc_rport_priv *); -+ void (*recv)(struct fc_lport *, struct fc_frame *); -+ struct module *module; -+}; -+ -+/* -+ * Register FC-4 provider with libfc. -+ */ -+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *); -+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *); -+ - /* - * FC_LPORT HELPER FUNCTIONS - *****************************/ diff --git a/fcst/linux-patches/20-seq-set-resp b/fcst/linux-patches/20-seq-set-resp deleted file mode 100644 index 28b7070ed..000000000 --- a/fcst/linux-patches/20-seq-set-resp +++ /dev/null @@ -1,84 +0,0 @@ -libfc: add method for setting handler for incoming exchange - -Add a method for setting handler for incoming exchange. -For multi-sequence exchanges, this allows the target driver -to add a response handler for handling subsequent sequences, -and exchange manager resets. - -The new function is called fc_seq_set_resp(). - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_exch.c | 19 +++++++++++++++++++ - include/scsi/libfc.h | 11 ++++++++++- - 2 files changed, 29 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c -index ec2a1ae..0000ddf 100644 ---- a/drivers/scsi/libfc/fc_exch.c -+++ b/drivers/scsi/libfc/fc_exch.c -@@ -544,6 +544,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) - return sp; - } - -+/* -+ * Set the response handler for the exchange associated with a sequence. -+ */ -+static void fc_seq_set_resp(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg) -+{ -+ struct fc_exch *ep = fc_seq_exch(sp); -+ -+ spin_lock_bh(&ep->ex_lock); -+ ep->resp = resp; -+ ep->arg = arg; -+ spin_unlock_bh(&ep->ex_lock); -+} -+ - /** - * fc_seq_exch_abort() - Abort an exchange and sequence - * @req_sp: The sequence to be aborted -@@ -2297,6 +2313,9 @@ int fc_exch_init(struct fc_lport *lport) - if (!lport->tt.seq_start_next) - lport->tt.seq_start_next = fc_seq_start_next; - -+ if (!lport->tt.seq_set_resp) -+ lport->tt.seq_set_resp = fc_seq_set_resp; -+ - if (!lport->tt.exch_seq_send) - lport->tt.exch_seq_send = fc_exch_seq_send; - -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 8b907e1..06cabab 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -564,6 +564,16 @@ struct libfc_function_template { - struct fc_seq *(*seq_assign)(struct fc_lport *, struct fc_frame *); - - /* -+ * Set a response handler for the exchange of the sequence. -+ * -+ * STATUS: OPTIONAL -+ */ -+ void (*seq_set_resp)(struct fc_seq *sp, -+ void (*resp)(struct fc_seq *, struct fc_frame *, -+ void *), -+ void *arg); -+ -+ /* - * Reset an exchange manager, completing all sequences and exchanges. - * If s_id is non-zero, reset only exchanges originating from that FID. - * If d_id is non-zero, reset only exchanges sending to that FID. -@@ -1059,7 +1069,6 @@ void fc_fill_reply_hdr(struct fc_frame *, const struct fc_frame *, - void fc_fill_hdr(struct fc_frame *, const struct fc_frame *, - enum fc_rctl, u32 f_ctl, u16 seq_cnt, u32 parm_offset); - -- - /* - * EXCHANGE MANAGER LAYER - *****************************/ diff --git a/fcst/linux-patches/21-lport-hook b/fcst/linux-patches/21-lport-hook deleted file mode 100644 index 8dd8e81b9..000000000 --- a/fcst/linux-patches/21-lport-hook +++ /dev/null @@ -1,36 +0,0 @@ -libfc: add local port hook for provider session lookup - -The target provider needs a per-instance lookup table -or other way to lookup sessions quickly without going through -a linear list or serializing too much. - -Add a simple void * array indexed by FC-4 type to the fc_lport. - -Signed-off-by: Joe Eykholt - ---- - include/scsi/libfc.h | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - - ---- -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 06cabab..769d480 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -807,6 +807,7 @@ struct fc_disc { - * @lp_mutex: Mutex to protect the local port - * @list: Handle for list of local ports - * @retry_work: Handle to local port for delayed retry context -+ * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { - /* Associations */ -@@ -862,6 +863,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ void *prov[FC_FC4_PROV_SIZE]; - }; - - /** diff --git a/fcst/linux-patches/22-lport-notify b/fcst/linux-patches/22-lport-notify deleted file mode 100644 index bcf6fccb0..000000000 --- a/fcst/linux-patches/22-lport-notify +++ /dev/null @@ -1,167 +0,0 @@ -libfc: add hook to notify providers of local port changes - -When an SCST provider is registered, it needs to know what -local ports are available for configuration as targets. - -Add a notifier chain that is invoked when any local port -that is added or deleted. - -Maintain a global list of local ports and add an -interator function that calls a given function for -every existing local port. This is used when first -loading a provider. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_libfc.c | 41 +++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/libfc/fc_libfc.h | 2 ++ - drivers/scsi/libfc/fc_lport.c | 2 ++ - include/scsi/libfc.h | 14 +++++++++++++- - 4 files changed, 58 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c -index ae3abef..753b7a8 100644 ---- a/drivers/scsi/libfc/fc_libfc.c -+++ b/drivers/scsi/libfc/fc_libfc.c -@@ -36,6 +36,10 @@ module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); - - DEFINE_MUTEX(fc_prov_mutex); -+static LIST_HEAD(fc_local_ports); -+struct blocking_notifier_head fc_lport_notifier_head = -+ BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head); -+EXPORT_SYMBOL(fc_lport_notifier_head); - - /* - * Providers which primarily send requests and PRLIs. -@@ -151,6 +155,17 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, - return copy_len; - } - -+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg) -+{ -+ struct fc_lport *lport; -+ -+ mutex_lock(&fc_prov_mutex); -+ list_for_each_entry(lport, &fc_local_ports, lport_list) -+ notify(lport, arg); -+ mutex_unlock(&fc_prov_mutex); -+} -+EXPORT_SYMBOL(fc_lport_iterate); -+ - /** - * fc_fill_hdr() - fill FC header fields based on request - * @fp: reply frame containing header to be filled in -@@ -270,3 +285,29 @@ void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov) - synchronize_rcu(); - } - EXPORT_SYMBOL(fc_fc4_deregister_provider); -+ -+/** -+ * fc_fc4_add_lport() - add new local port to list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_add_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_add_tail(&lport->lport_list, &fc_local_ports); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_ADD, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -+ -+/** -+ * fc_fc4_del_lport() - remove local port from list and run notifiers. -+ * @lport: The new local port. -+ */ -+void fc_fc4_del_lport(struct fc_lport *lport) -+{ -+ mutex_lock(&fc_prov_mutex); -+ list_del(&lport->lport_list); -+ blocking_notifier_call_chain(&fc_lport_notifier_head, -+ FC_LPORT_EV_DEL, lport); -+ mutex_unlock(&fc_prov_mutex); -+} -diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h -index a01b80d..a980482 100644 ---- a/drivers/scsi/libfc/fc_libfc.h -+++ b/drivers/scsi/libfc/fc_libfc.h -@@ -111,6 +111,8 @@ void fc_destroy_fcp(void); - * Internal libfc functions - */ - const char *fc_els_resp_type(struct fc_frame *); -+extern void fc_fc4_add_lport(struct fc_lport *); -+extern void fc_fc4_del_lport(struct fc_lport *); - - /* - * Copies a buffer into an sg list -diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c -index eec9d31..e2311f0 100644 ---- a/drivers/scsi/libfc/fc_lport.c -+++ b/drivers/scsi/libfc/fc_lport.c -@@ -629,6 +629,7 @@ int fc_lport_destroy(struct fc_lport *lport) - lport->tt.fcp_abort_io(lport); - lport->tt.disc_stop_final(lport); - lport->tt.exch_mgr_reset(lport, 0, 0); -+ fc_fc4_del_lport(lport); - return 0; - } - EXPORT_SYMBOL(fc_lport_destroy); -@@ -1628,6 +1629,7 @@ int fc_lport_init(struct fc_lport *lport) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT; - if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) - fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; -+ fc_fc4_add_lport(lport); - - return 0; - } -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index 769d480..af8a6e8 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -765,6 +765,15 @@ struct fc_disc { - enum fc_disc_event); - }; - -+/* -+ * Local port notifier and events. -+ */ -+extern struct blocking_notifier_head fc_lport_notifier_head; -+enum fc_lport_event { -+ FC_LPORT_EV_ADD, -+ FC_LPORT_EV_DEL, -+}; -+ - /** - * struct fc_lport - Local port - * @host: The SCSI host associated with a local port -@@ -805,8 +814,9 @@ struct fc_disc { - * @lso_max: The maximum large offload send size - * @fcts: FC-4 type mask - * @lp_mutex: Mutex to protect the local port -- * @list: Handle for list of local ports -+ * @list: Linkage on list of vport peers - * @retry_work: Handle to local port for delayed retry context -+ * @lport_list: Linkage on module-wide list of local ports - * @prov: Pointers available for use by passive FC-4 providers - */ - struct fc_lport { -@@ -863,6 +873,7 @@ struct fc_lport { - struct mutex lp_mutex; - struct list_head list; - struct delayed_work retry_work; -+ struct list_head lport_list; - void *prov[FC_FC4_PROV_SIZE]; - }; - -@@ -1018,6 +1029,7 @@ struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); - struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); - int fc_lport_bsg_request(struct fc_bsg_job *); - void fc_lport_set_local_id(struct fc_lport *, u32 port_id); -+void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *); - - /* - * REMOTE PORT LAYER diff --git a/fcst/linux-patches/23-softirq b/fcst/linux-patches/23-softirq deleted file mode 100644 index 2c675be2b..000000000 --- a/fcst/linux-patches/23-softirq +++ /dev/null @@ -1,33 +0,0 @@ -fcoe: don't deliver FCP frames to target modules in softirq context - -Under certain conditions when FCP frames arrive on the correct CPU -we deliver them in the softirq context. This is unexpected for -target modules like tcm_fc and fcst, and causes them to get errors. - -Add a check for the FC frame header F_CTL bit EX_CTX, and don't -deliver in softirq context if that bit is off. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/fcoe.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c -index 44a0759..d222ae4 100644 ---- a/drivers/scsi/fcoe/fcoe.c -+++ b/drivers/scsi/fcoe/fcoe.c -@@ -1293,8 +1293,11 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, - * This lets us process completions without context switching from the - * NET_RX softirq, to our receive processing thread, and then back to - * BLOCK softirq context. -+ * Don't do this if EX_CTX is off as it causes problems for target -+ * modules that don't expect to be called in softirq context. - */ - if (fh->fh_type == FC_TYPE_FCP && -+ (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX) && - cpu == smp_processor_id() && - skb_queue_empty(&fps->fcoe_rx_list)) { - spin_unlock_bh(&fps->fcoe_rx_list.lock); diff --git a/fcst/linux-patches/24-softirq b/fcst/linux-patches/24-softirq deleted file mode 100644 index a02f25453..000000000 --- a/fcst/linux-patches/24-softirq +++ /dev/null @@ -1,33 +0,0 @@ -fcoe: don't deliver FCP frames to target modules in softirq context - -Under certain conditions when FCP frames arrive on the correct CPU -we deliver them in the softirq context. This is unexpected for -target modules like tcm_fc and fcst, and causes them to get errors. - -Add a check for the FC frame header F_CTL bit EX_CTX, and don't -deliver in softirq context if that bit is off. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/fcoe.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c -index 844d618..e4c3128 100644 ---- a/drivers/scsi/fcoe/fcoe.c -+++ b/drivers/scsi/fcoe/fcoe.c -@@ -1340,8 +1340,11 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, - * This lets us process completions without context switching from the - * NET_RX softirq, to our receive processing thread, and then back to - * BLOCK softirq context. -+ * Don't do this if EX_CTX is off as it causes problems for target -+ * modules that don't expect to be called in softirq context. - */ - if (fh->fh_type == FC_TYPE_FCP && -+ (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX) && - cpu == smp_processor_id() && - skb_queue_empty(&fps->fcoe_rx_list)) { - spin_unlock_bh(&fps->fcoe_rx_list.lock); diff --git a/fcst/linux-patches/25-fip-union b/fcst/linux-patches/25-fip-union deleted file mode 100644 index 4c827d589..000000000 --- a/fcst/linux-patches/25-fip-union +++ /dev/null @@ -1,26 +0,0 @@ -libfcoe: fix stack damage caused by using union instead of struct - -TBD. This was already submitted by someone else -but didn't make it into 2.6.36. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/fcoe/libfcoe.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - ---- -diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c -index aa503d8..bc17c71 100644 ---- a/drivers/scsi/fcoe/libfcoe.c -+++ b/drivers/scsi/fcoe/libfcoe.c -@@ -2296,7 +2296,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) - { - struct fip_header *fiph; - enum fip_vn2vn_subcode sub; -- union { -+ struct { - struct fc_rport_priv rdata; - struct fcoe_rport frport; - } buf; diff --git a/fcst/linux-patches/26-exch-alloc2 b/fcst/linux-patches/26-exch-alloc2 deleted file mode 100644 index ca640da2a..000000000 --- a/fcst/linux-patches/26-exch-alloc2 +++ /dev/null @@ -1,71 +0,0 @@ -libfc: export seq_release() for users of seq_assign() - -Target modules using lport->tt.seq_assign() get a hold on the -exchange but have no way of releasing it. Add that. - -Signed-off-by: Joe Eykholt - ---- - drivers/scsi/libfc/fc_exch.c | 14 ++++++++++++++ - include/scsi/libfc.h | 7 +++++++ - 2 files changed, 21 insertions(+), 0 deletions(-) - - ---- -diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c -index 0000ddf..0deb901 100644 ---- a/drivers/scsi/libfc/fc_exch.c -+++ b/drivers/scsi/libfc/fc_exch.c -@@ -1252,6 +1252,8 @@ free: - * @fp: The request frame - * - * On success, the sequence pointer will be returned and also in fr_seq(@fp). -+ * A reference will be held on the exchange/sequence for the caller, which -+ * must call fc_seq_release(). - */ - static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) - { -@@ -1269,6 +1271,15 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) - } - - /** -+ * fc_seq_release() - Release the hold -+ * @sp: The sequence. -+ */ -+static void fc_seq_release(struct fc_seq *sp) -+{ -+ fc_exch_release(fc_seq_exch(sp)); -+} -+ -+/** - * fc_exch_recv_req() - Handler for an incoming request - * @lport: The local port that received the request - * @mp: The EM that the exchange is on -@@ -2337,6 +2348,9 @@ int fc_exch_init(struct fc_lport *lport) - if (!lport->tt.seq_assign) - lport->tt.seq_assign = fc_seq_assign; - -+ if (!lport->tt.seq_release) -+ lport->tt.seq_release = fc_seq_release; -+ - return 0; - } - EXPORT_SYMBOL(fc_exch_init); -diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h -index af8a6e8..875e3a8 100644 ---- a/include/scsi/libfc.h -+++ b/include/scsi/libfc.h -@@ -574,6 +574,13 @@ struct libfc_function_template { - void *arg); - - /* -+ * Release the reference on the sequence returned by seq_assign(). -+ * -+ * STATUS: OPTIONAL -+ */ -+ void (*seq_release)(struct fc_seq *); -+ -+ /* - * Reset an exchange manager, completing all sequences and exchanges. - * If s_id is non-zero, reset only exchanges originating from that FID. - * If d_id is non-zero, reset only exchanges sending to that FID. diff --git a/fcst/linux-patches/series-2.6.33-rc8 b/fcst/linux-patches/series-2.6.33-rc8 deleted file mode 100644 index 1d341c08c..000000000 --- a/fcst/linux-patches/series-2.6.33-rc8 +++ /dev/null @@ -1,15 +0,0 @@ -# This series applies on GIT commit ec7b3b3aaf3b3b208140ac83dc19a754eebf648f -01-prli-clean -02-fc4 -03-seq-init -04-seq-set-resp -05-lport-hook -06-lport-notify -07-pta-mask -08-ptp-ref -09-ptp-type -10-non-fip -11-ptp-flogi-recv -12-ptp-npiv -13-ptp-acc -14-fc-frame-sparse-workaround diff --git a/fcst/linux-patches/series-2.6.34 b/fcst/linux-patches/series-2.6.34 deleted file mode 100644 index 1d341c08c..000000000 --- a/fcst/linux-patches/series-2.6.34 +++ /dev/null @@ -1,15 +0,0 @@ -# This series applies on GIT commit ec7b3b3aaf3b3b208140ac83dc19a754eebf648f -01-prli-clean -02-fc4 -03-seq-init -04-seq-set-resp -05-lport-hook -06-lport-notify -07-pta-mask -08-ptp-ref -09-ptp-type -10-non-fip -11-ptp-flogi-recv -12-ptp-npiv -13-ptp-acc -14-fc-frame-sparse-workaround diff --git a/fcst/linux-patches/series-2.6.35 b/fcst/linux-patches/series-2.6.35 deleted file mode 100644 index 8fa9f2515..000000000 --- a/fcst/linux-patches/series-2.6.35 +++ /dev/null @@ -1,7 +0,0 @@ -# applies to 2.6.35 -15-fc4 -16-seq-set-resp -17-lport-hook -18-lport-notify -14-fc-frame-sparse-workaround -23-softirq diff --git a/fcst/linux-patches/series-2.6.36 b/fcst/linux-patches/series-2.6.36 deleted file mode 100644 index b3fba47ce..000000000 --- a/fcst/linux-patches/series-2.6.36 +++ /dev/null @@ -1,8 +0,0 @@ -# applies to linux 2.6.36 -19-fc4-v2 -20-seq-set-resp -21-lport-hook -22-lport-notify -24-softirq -25-fip-union -26-exch-alloc2