Commit 11aea16a authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Add ability to send PRLO

Add ability to send Implicit PRLO to flush IOs
from FW back to driver.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9ecf0b0d
...@@ -507,6 +507,7 @@ struct srb_iocb { ...@@ -507,6 +507,7 @@ struct srb_iocb {
#define SRB_NVME_LS 20 #define SRB_NVME_LS 20
#define SRB_PRLI_CMD 21 #define SRB_PRLI_CMD 21
#define SRB_CTRL_VP 22 #define SRB_CTRL_VP 22
#define SRB_PRLO_CMD 23
enum { enum {
TYPE_SRB, TYPE_SRB,
...@@ -3140,6 +3141,8 @@ enum qla_work_type { ...@@ -3140,6 +3141,8 @@ enum qla_work_type {
QLA_EVT_GNL, QLA_EVT_GNL,
QLA_EVT_NACK, QLA_EVT_NACK,
QLA_EVT_RELOGIN, QLA_EVT_RELOGIN,
QLA_EVT_ASYNC_PRLO,
QLA_EVT_ASYNC_PRLO_DONE,
}; };
......
...@@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *); ...@@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
uint16_t *); uint16_t *);
extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
uint16_t *); uint16_t *);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
...@@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, ...@@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
int qla24xx_detect_sfp(scsi_qla_host_t *vha); int qla24xx_detect_sfp(scsi_qla_host_t *vha);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *,
fc_port_t *, uint16_t *);
/* /*
* Global Data in qla_os.c source file. * Global Data in qla_os.c source file.
*/ */
......
...@@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
fcport->flags &= ~FCF_ASYNC_SENT; fcport->flags &= ~FCF_ASYNC_SENT;
return rval; return rval;
} }
void
qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
{
/* Don't re-login in target mode */
if (!fcport->tgt_session)
qla2x00_mark_device_lost(vha, fcport, 1, 0);
qlt_logo_completion_handler(fcport, data[0]);
}
static void
qla2x00_async_prlo_sp_done(void *s, int res)
{
srb_t *sp = (srb_t *)s;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
if (!test_bit(UNLOADING, &vha->dpc_flags))
qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
lio->u.logio.data);
sp->free(sp);
}
int
qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
{
srb_t *sp;
struct srb_iocb *lio;
int rval;
rval = QLA_FUNCTION_FAILED;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
sp->type = SRB_PRLO_CMD;
sp->name = "prlo";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
lio = &sp->u.iocb_cmd;
lio->timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_prlo_sp_done;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0x2070,
"Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
done_free_sp:
sp->free(sp);
done:
return rval;
}
static static
void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
{ {
......
...@@ -3390,6 +3390,20 @@ qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce) ...@@ -3390,6 +3390,20 @@ qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce)
vce->vp_idx_map[map] |= 1 << pos; vce->vp_idx_map[map] |= 1 << pos;
} }
static void
qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
{
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_PRLO|LCF_IMPL_PRLO);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
logio->port_id[1] = sp->fcport->d_id.b.area;
logio->port_id[2] = sp->fcport->d_id.b.domain;
logio->vp_index = sp->fcport->vha->vp_idx;
}
int int
qla2x00_start_sp(srb_t *sp) qla2x00_start_sp(srb_t *sp)
{ {
...@@ -3471,6 +3485,9 @@ qla2x00_start_sp(srb_t *sp) ...@@ -3471,6 +3485,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_CTRL_VP: case SRB_CTRL_VP:
qla25xx_ctrlvp_iocb(sp, pkt); qla25xx_ctrlvp_iocb(sp, pkt);
break; break;
case SRB_PRLO_CMD:
qla24xx_prlo_iocb(sp, pkt);
break;
default: default:
break; break;
} }
......
...@@ -4690,6 +4690,8 @@ qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); ...@@ -4690,6 +4690,8 @@ qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC); qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE); qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
qla2x00_post_async_work(prlo, QLA_EVT_ASYNC_PRLO);
qla2x00_post_async_work(prlo_done, QLA_EVT_ASYNC_PRLO_DONE);
int int
qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
...@@ -4943,6 +4945,13 @@ qla2x00_do_work(struct scsi_qla_host *vha) ...@@ -4943,6 +4945,13 @@ qla2x00_do_work(struct scsi_qla_host *vha)
case QLA_EVT_NACK: case QLA_EVT_NACK:
qla24xx_do_nack_work(vha, e); qla24xx_do_nack_work(vha, e);
break; break;
case QLA_EVT_ASYNC_PRLO:
qla2x00_async_prlo(vha, e->u.logio.fcport);
break;
case QLA_EVT_ASYNC_PRLO_DONE:
qla2x00_async_prlo_done(vha, e->u.logio.fcport,
e->u.logio.data);
break;
} }
if (e->flags & QLA_EVT_FLAG_FREE) if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e); kfree(e);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment