Message ID | 20210531070545.32072-7-njavali@marvell.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | qla2xxx: Add EDIF support | expand |
On 5/31/21 9:05 AM, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > Latest FC adapter from Marvell has the ability to encrypt > data in flight (EDIF) feature. This feature require an > application (ex: ipsec, etc) to act as an authenticator. > > On completion of the authentication process, the authentication > application will notify driver on whether it is successful or not. > > If success, application will use the QL_VND_SC_AUTH_OK BSG call > to tell driver to proceed to the PRLI phase. > > If fail, application will use the QL_VND_SC_AUTH_FAIL bsg call > to tell driver to tear down the connection and retry. In > the case where an existing session is active, the re-key > process can fail. The session tear down ensure data is not > further compromise. > > Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com> > Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com> > Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com> > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_edif.c | 214 ++++++++++++++++++++++++++++++++ > drivers/scsi/qla2xxx/qla_gbl.h | 1 + > drivers/scsi/qla2xxx/qla_init.c | 3 +- > 3 files changed, 216 insertions(+), 2 deletions(-) > Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes
On 5/31/21 2:05 AM, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > Latest FC adapter from Marvell has the ability to encrypt > data in flight (EDIF) feature. This feature require an > application (ex: ipsec, etc) to act as an authenticator. > > On completion of the authentication process, the authentication > application will notify driver on whether it is successful or not. > > If success, application will use the QL_VND_SC_AUTH_OK BSG call > to tell driver to proceed to the PRLI phase. > > If fail, application will use the QL_VND_SC_AUTH_FAIL bsg call > to tell driver to tear down the connection and retry. In > the case where an existing session is active, the re-key > process can fail. The session tear down ensure data is not > further compromise. > > Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com> > Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com> > Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com> > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_edif.c | 214 ++++++++++++++++++++++++++++++++ > drivers/scsi/qla2xxx/qla_gbl.h | 1 + > drivers/scsi/qla2xxx/qla_init.c | 3 +- > 3 files changed, 216 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c > index 4c5cc99bdbd4..c86d64512702 100644 > --- a/drivers/scsi/qla2xxx/qla_edif.c > +++ b/drivers/scsi/qla2xxx/qla_edif.c > @@ -661,6 +661,214 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > return rval; > } > > +static int > +qla_edif_app_chk_sa_update(scsi_qla_host_t *vha, fc_port_t *fcport, > + struct app_plogi_reply *appplogireply) > +{ > + int ret = 0; > + > + if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n", > + __func__, fcport->port_name, fcport->edif.tx_sa_set, > + fcport->edif.rx_sa_set); > + appplogireply->prli_status = 0; > + ret = 1; > + } else { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s wwpn %8phC Both SA(s) updated.\n", __func__, > + fcport->port_name); > + fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0; > + fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0; > + appplogireply->prli_status = 1; > + } > + return ret; > +} > + > +/* > + * event that the app has approved plogi to complete (e.g., finish > + * up with prli > + */ > +static int > +qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > +{ > + int32_t rval = 0; > + struct auth_complete_cmd appplogiok; > + struct app_plogi_reply appplogireply = {0}; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + fc_port_t *fcport = NULL; > + port_id_t portid = {0}; > + /* port_id_t portid = {0x10100}; */ > + /* int i; */ remove debug code > + > + /* ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth ok\n", __func__); */ > + move to verbose bit or remove this > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + bsg_job->request_payload.sg_cnt, &appplogiok, > + sizeof(struct auth_complete_cmd)); > + > + switch (appplogiok.type) { > + case PL_TYPE_WWPN: > + fcport = qla2x00_find_fcport_by_wwpn(vha, > + appplogiok.u.wwpn, 0); > + if (!fcport) > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s wwpn lookup failed: %8phC\n", > + __func__, appplogiok.u.wwpn); > + break; > + case PL_TYPE_DID: > + fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id); > + if (!fcport) > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s d_id lookup failed: %x\n", __func__, > + portid.b24); > + break; > + default: > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s undefined type: %x\n", __func__, > + appplogiok.type); > + break; > + } > + > + if (!fcport) { > + SET_DID_STATUS(bsg_reply->result, DID_ERROR); > + goto errstate_exit; > + } > + > + /* TODO: edif: Kill prli timer... */ > + > + /* > + * if port is online then this is a REKEY operation > + * Only do sa update checking > + */ > + if (atomic_read(&fcport->state) == FCS_ONLINE) { > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s Skipping PRLI complete based on rekey\n", __func__); > + appplogireply.prli_status = 1; > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + qla_edif_app_chk_sa_update(vha, fcport, &appplogireply); > + goto errstate_exit; > + } > + > + /* make sure in AUTH_PENDING or else reject */ > + if (fcport->disc_state != DSC_LOGIN_AUTH_PEND) { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s wwpn %8phC is not in auth pending state (%x)\n", > + __func__, fcport->port_name, fcport->disc_state); > + /* SET_DID_STATUS(bsg_reply->result, DID_ERROR); */ remove debug code > + /* App can't fix us - initaitor will retry */ > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + appplogireply.prli_status = 0; > + goto errstate_exit; > + } > + > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + appplogireply.prli_status = 1; > + if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n", > + __func__, fcport->port_name, fcport->edif.tx_sa_set, > + fcport->edif.rx_sa_set); > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + appplogireply.prli_status = 0; > + goto errstate_exit; > + > + } else { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s wwpn %8phC Both SA(s) updated.\n", __func__, > + fcport->port_name); > + fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0; > + fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0; > + } add newline here > + /* qla_edif_app_chk_sa_update(vha, fcport, &appplogireply); */ > + /* > + * TODO: edif: check this - discovery state changed by prli work? > + * TODO: Can't call this for target mode > + */ > + if (qla_ini_mode_enabled(vha)) { > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s AUTH complete - RESUME with prli for wwpn %8phC\n", > + __func__, fcport->port_name); > + qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1); > + /* qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_PEND); */ > + qla24xx_post_prli_work(vha, fcport); > + } > + > +errstate_exit: > + remove empty line > + bsg_job->reply_len = sizeof(struct fc_bsg_reply); > + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, > + bsg_job->reply_payload.sg_cnt, &appplogireply, > + sizeof(struct app_plogi_reply)); > + > + return rval; > +} > + > +/* > + * event that the app has failed the plogi. logout the device (tbd) > + */ > +static int > +qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > +{ > + int32_t rval = 0; > + struct auth_complete_cmd appplogifail; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + fc_port_t *fcport = NULL; > + port_id_t portid = {0}; > + > + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth fail\n", __func__); > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + bsg_job->request_payload.sg_cnt, &appplogifail, > + sizeof(struct auth_complete_cmd)); > + > + /* > + * TODO: edif: app has failed this plogi. Inform driver to > + * take any action (if any). > + */ > + switch (appplogifail.type) { > + case PL_TYPE_WWPN: > + fcport = qla2x00_find_fcport_by_wwpn(vha, > + appplogifail.u.wwpn, 0); > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + break; > + case PL_TYPE_DID: > + fcport = qla2x00_find_fcport_by_pid(vha, &appplogifail.u.d_id); > + if (!fcport) > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s d_id lookup failed: %x\n", __func__, > + portid.b24); > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + break; > + default: > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s undefined type: %x\n", __func__, > + appplogifail.type); > + bsg_job->reply_len = sizeof(struct fc_bsg_reply); > + SET_DID_STATUS(bsg_reply->result, DID_ERROR); > + rval = -1; > + break; > + } > + > + ql_dbg(ql_dbg_edif, vha, 0x911d, > + "%s fcport is 0x%p\n", __func__, fcport); > + > + if (fcport) { > + /* set/reset edif values and flags */ > + ql_dbg(ql_dbg_edif, vha, 0x911e, > + "%s reset the auth process - %8phC, loopid=%x portid=%06x.\n", > + __func__, fcport->port_name, fcport->loop_id, > + fcport->d_id.b24); > + > + if (qla_ini_mode_enabled(fcport->vha)) { > + fcport->send_els_logo = 1; > + qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); > + } > + } > + > + return rval; > +} > + > /* > * event that the app needs fc port info (either all or individual d_id) > */ > @@ -887,6 +1095,12 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) > case QL_VND_SC_APP_STOP: > rval = qla_edif_app_stop(vha, bsg_job); > break; > + case QL_VND_SC_AUTH_OK: > + rval = qla_edif_app_authok(vha, bsg_job); > + break; > + case QL_VND_SC_AUTH_FAIL: > + rval = qla_edif_app_authfail(vha, bsg_job); > + break; > case QL_VND_SC_GET_FCINFO: > rval = qla_edif_app_getfcinfo(vha, bsg_job); > break; > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h > index f4a98d92c4b3..236eb610b5be 100644 > --- a/drivers/scsi/qla2xxx/qla_gbl.h > +++ b/drivers/scsi/qla2xxx/qla_gbl.h > @@ -12,6 +12,7 @@ > * Global Function Prototypes in qla_init.c source file. > */ > extern int qla2x00_initialize_adapter(scsi_qla_host_t *); > +extern int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport); > > extern int qla2100_pci_config(struct scsi_qla_host *); > extern int qla2300_pci_config(struct scsi_qla_host *); > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 97da4ebadc33..bd528c249aa7 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -34,7 +34,6 @@ static int qla2x00_restart_isp(scsi_qla_host_t *); > static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); > static int qla84xx_init_chip(scsi_qla_host_t *); > static int qla25xx_init_queues(struct qla_hw_data *); > -static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *); > static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, > struct event_arg *ea); > static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, > @@ -1191,7 +1190,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res) > sp->free(sp); > } > > -static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) > +int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) > { > struct qla_work_evt *e; > > Other than small nits, code looks good Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index 4c5cc99bdbd4..c86d64512702 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -661,6 +661,214 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job) return rval; } +static int +qla_edif_app_chk_sa_update(scsi_qla_host_t *vha, fc_port_t *fcport, + struct app_plogi_reply *appplogireply) +{ + int ret = 0; + + if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n", + __func__, fcport->port_name, fcport->edif.tx_sa_set, + fcport->edif.rx_sa_set); + appplogireply->prli_status = 0; + ret = 1; + } else { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s wwpn %8phC Both SA(s) updated.\n", __func__, + fcport->port_name); + fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0; + fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0; + appplogireply->prli_status = 1; + } + return ret; +} + +/* + * event that the app has approved plogi to complete (e.g., finish + * up with prli + */ +static int +qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job) +{ + int32_t rval = 0; + struct auth_complete_cmd appplogiok; + struct app_plogi_reply appplogireply = {0}; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + fc_port_t *fcport = NULL; + port_id_t portid = {0}; + /* port_id_t portid = {0x10100}; */ + /* int i; */ + + /* ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth ok\n", __func__); */ + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &appplogiok, + sizeof(struct auth_complete_cmd)); + + switch (appplogiok.type) { + case PL_TYPE_WWPN: + fcport = qla2x00_find_fcport_by_wwpn(vha, + appplogiok.u.wwpn, 0); + if (!fcport) + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s wwpn lookup failed: %8phC\n", + __func__, appplogiok.u.wwpn); + break; + case PL_TYPE_DID: + fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id); + if (!fcport) + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s d_id lookup failed: %x\n", __func__, + portid.b24); + break; + default: + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s undefined type: %x\n", __func__, + appplogiok.type); + break; + } + + if (!fcport) { + SET_DID_STATUS(bsg_reply->result, DID_ERROR); + goto errstate_exit; + } + + /* TODO: edif: Kill prli timer... */ + + /* + * if port is online then this is a REKEY operation + * Only do sa update checking + */ + if (atomic_read(&fcport->state) == FCS_ONLINE) { + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s Skipping PRLI complete based on rekey\n", __func__); + appplogireply.prli_status = 1; + SET_DID_STATUS(bsg_reply->result, DID_OK); + qla_edif_app_chk_sa_update(vha, fcport, &appplogireply); + goto errstate_exit; + } + + /* make sure in AUTH_PENDING or else reject */ + if (fcport->disc_state != DSC_LOGIN_AUTH_PEND) { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s wwpn %8phC is not in auth pending state (%x)\n", + __func__, fcport->port_name, fcport->disc_state); + /* SET_DID_STATUS(bsg_reply->result, DID_ERROR); */ + /* App can't fix us - initaitor will retry */ + SET_DID_STATUS(bsg_reply->result, DID_OK); + appplogireply.prli_status = 0; + goto errstate_exit; + } + + SET_DID_STATUS(bsg_reply->result, DID_OK); + appplogireply.prli_status = 1; + if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n", + __func__, fcport->port_name, fcport->edif.tx_sa_set, + fcport->edif.rx_sa_set); + SET_DID_STATUS(bsg_reply->result, DID_OK); + appplogireply.prli_status = 0; + goto errstate_exit; + + } else { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s wwpn %8phC Both SA(s) updated.\n", __func__, + fcport->port_name); + fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0; + fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0; + } + /* qla_edif_app_chk_sa_update(vha, fcport, &appplogireply); */ + /* + * TODO: edif: check this - discovery state changed by prli work? + * TODO: Can't call this for target mode + */ + if (qla_ini_mode_enabled(vha)) { + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s AUTH complete - RESUME with prli for wwpn %8phC\n", + __func__, fcport->port_name); + qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1); + /* qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_PEND); */ + qla24xx_post_prli_work(vha, fcport); + } + +errstate_exit: + + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, &appplogireply, + sizeof(struct app_plogi_reply)); + + return rval; +} + +/* + * event that the app has failed the plogi. logout the device (tbd) + */ +static int +qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job) +{ + int32_t rval = 0; + struct auth_complete_cmd appplogifail; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + fc_port_t *fcport = NULL; + port_id_t portid = {0}; + + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth fail\n", __func__); + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &appplogifail, + sizeof(struct auth_complete_cmd)); + + /* + * TODO: edif: app has failed this plogi. Inform driver to + * take any action (if any). + */ + switch (appplogifail.type) { + case PL_TYPE_WWPN: + fcport = qla2x00_find_fcport_by_wwpn(vha, + appplogifail.u.wwpn, 0); + SET_DID_STATUS(bsg_reply->result, DID_OK); + break; + case PL_TYPE_DID: + fcport = qla2x00_find_fcport_by_pid(vha, &appplogifail.u.d_id); + if (!fcport) + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s d_id lookup failed: %x\n", __func__, + portid.b24); + SET_DID_STATUS(bsg_reply->result, DID_OK); + break; + default: + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s undefined type: %x\n", __func__, + appplogifail.type); + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + SET_DID_STATUS(bsg_reply->result, DID_ERROR); + rval = -1; + break; + } + + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s fcport is 0x%p\n", __func__, fcport); + + if (fcport) { + /* set/reset edif values and flags */ + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s reset the auth process - %8phC, loopid=%x portid=%06x.\n", + __func__, fcport->port_name, fcport->loop_id, + fcport->d_id.b24); + + if (qla_ini_mode_enabled(fcport->vha)) { + fcport->send_els_logo = 1; + qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); + } + } + + return rval; +} + /* * event that the app needs fc port info (either all or individual d_id) */ @@ -887,6 +1095,12 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) case QL_VND_SC_APP_STOP: rval = qla_edif_app_stop(vha, bsg_job); break; + case QL_VND_SC_AUTH_OK: + rval = qla_edif_app_authok(vha, bsg_job); + break; + case QL_VND_SC_AUTH_FAIL: + rval = qla_edif_app_authfail(vha, bsg_job); + break; case QL_VND_SC_GET_FCINFO: rval = qla_edif_app_getfcinfo(vha, bsg_job); break; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f4a98d92c4b3..236eb610b5be 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -12,6 +12,7 @@ * Global Function Prototypes in qla_init.c source file. */ extern int qla2x00_initialize_adapter(scsi_qla_host_t *); +extern int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport); extern int qla2100_pci_config(struct scsi_qla_host *); extern int qla2300_pci_config(struct scsi_qla_host *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 97da4ebadc33..bd528c249aa7 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -34,7 +34,6 @@ static int qla2x00_restart_isp(scsi_qla_host_t *); static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); static int qla84xx_init_chip(scsi_qla_host_t *); static int qla25xx_init_queues(struct qla_hw_data *); -static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *); static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea); static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, @@ -1191,7 +1190,7 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res) sp->free(sp); } -static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) +int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) { struct qla_work_evt *e;