Commit 82de802a authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Preparation for Target MQ.

In Current code, Req Q 0, RespQ 0 & hardware_lock are the main resources
for sending and process completion of Target IO. These resources are now
referenced behind a new qpair/"struct qla_qpair base_qpair".  Main path
IO handle will access those resources via the qpair pointer in
preparation for Target MQ.
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 c5419e26
......@@ -2096,7 +2096,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
}
if (qos) {
qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx);
qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx, true);
if (!qpair)
ql_log(ql_log_warn, vha, 0x7084,
"Can't create qpair for VP[%d]\n",
......
......@@ -3182,6 +3182,9 @@ struct qla_tc_param {
#define QLA_PRECONFIG_VPORTS 32
#define QLA_MAX_VPORTS_QLA24XX 128
#define QLA_MAX_VPORTS_QLA25XX 256
struct qla_qpair;
/* Response queue data structure */
struct rsp_que {
dma_addr_t dma;
......@@ -3201,6 +3204,7 @@ struct rsp_que {
struct qla_msix_entry *msix;
struct req_que *req;
srb_t *status_srb; /* status continuation entry */
struct qla_qpair *qpair;
dma_addr_t dma_fx00;
response_t *ring_fx00;
......@@ -3241,6 +3245,14 @@ struct req_que {
struct qla_qpair {
spinlock_t qp_lock;
atomic_t ref_count;
/*
* For qpair 0, qp_lock_ptr will point at hardware_lock due to
* legacy code. For other Qpair(s), it will point at qp_lock.
*/
spinlock_t *qp_lock_ptr;
struct scsi_qla_host *vha;
/* distill these fields down to 'online=0/1'
* ha->flags.eeh_busy
* ha->flags.pci_channel_io_perm_failure
......@@ -3252,10 +3264,7 @@ struct qla_qpair {
uint32_t delete_in_progress:1;
uint16_t id; /* qp number used with FW */
uint16_t num_active_cmd; /* cmds down at firmware */
cpumask_t cpu_mask; /* CPU mask for cpu affinity operation */
uint16_t vp_idx; /* vport ID */
mempool_t *srb_mempool;
/* to do: New driver: move queues to here instead of pointers */
......@@ -3266,7 +3275,7 @@ struct qla_qpair {
struct qla_hw_data *hw;
struct work_struct q_work;
struct list_head qp_list_elem; /* vha->qp_list */
struct scsi_qla_host *vha;
uint16_t cpuid;
};
/* Place holder for FW buffer parameters */
......
......@@ -77,8 +77,7 @@ struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
extern void *qla2x00_alloc_iocbs_ready(struct qla_qpair *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
extern fc_port_t *
......@@ -96,7 +95,7 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
int, int);
int, int, bool);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
......@@ -255,7 +254,8 @@ extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
extern int qla2xxx_dif_start_scsi_mq(srb_t *);
extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *__qla2x00_alloc_iocbs(struct qla_qpair *, srb_t *);
extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tc_param *);
......@@ -663,9 +663,9 @@ extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
uint16_t, int, uint8_t);
uint16_t, int, uint8_t, bool);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
uint16_t, struct qla_qpair *);
uint16_t, struct qla_qpair *, bool);
extern void qla2x00_init_response_q_entries(struct rsp_que *);
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
......@@ -839,7 +839,8 @@ extern int qla_get_exlogin_status(scsi_qla_host_t *, uint16_t *,
extern int qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr);
extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
response_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
......
......@@ -7578,7 +7578,8 @@ qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
return ret;
}
struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int vp_idx)
struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
int vp_idx, bool startqp)
{
int rsp_id = 0;
int req_id = 0;
......@@ -7605,6 +7606,8 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->hw = vha->hw;
qpair->vha = vha;
qpair->qp_lock_ptr = &qpair->qp_lock;
spin_lock_init(&qpair->qp_lock);
/* Assign available que pair id */
mutex_lock(&ha->mq_lock);
......@@ -7642,7 +7645,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
mutex_unlock(&ha->mq_lock);
/* Create response queue first */
rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair);
rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair, startqp);
if (!rsp_id) {
ql_log(ql_log_warn, vha, 0x0185,
"Failed to create response queue.\n");
......@@ -7652,7 +7655,8 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->rsp = ha->rsp_q_map[rsp_id];
/* Create request queue */
req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos);
req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos,
startqp);
if (!req_id) {
ql_log(ql_log_warn, vha, 0x0186,
"Failed to create request queue.\n");
......@@ -7661,6 +7665,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->req = ha->req_q_map[req_id];
qpair->rsp->req = qpair->req;
qpair->rsp->qpair = qpair;
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4)
......
......@@ -2109,20 +2109,13 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
/* Generic Control-SRB manipulation functions. */
/* hardware_lock assumed to be held. */
void *
qla2x00_alloc_iocbs_ready(scsi_qla_host_t *vha, srb_t *sp)
{
if (qla2x00_reset_active(vha))
return NULL;
return qla2x00_alloc_iocbs(vha, sp);
}
void *
qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
__qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
{
scsi_qla_host_t *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
struct req_que *req = qpair->req;
device_reg_t *reg = ISP_QUE_REG(ha, req->id);
uint32_t index, handle;
request_t *pkt;
......@@ -2200,6 +2193,23 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
return pkt;
}
void *
qla2x00_alloc_iocbs_ready(struct qla_qpair *qpair, srb_t *sp)
{
scsi_qla_host_t *vha = qpair->vha;
if (qla2x00_reset_active(vha))
return NULL;
return __qla2x00_alloc_iocbs(qpair, sp);
}
void *
qla2x00_alloc_iocbs(struct scsi_qla_host *vha, srb_t *sp)
{
return __qla2x00_alloc_iocbs(vha->hw->base_qpair, sp);
}
static void
qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
{
......
......@@ -2653,7 +2653,8 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
int res = DID_ERROR << 16;
ql_dbg(ql_dbg_async, vha, 0x502a,
"type of error status in response: 0x%x\n", pkt->entry_status);
"iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
pkt->entry_type, pkt->entry_status, pkt->handle, rsp->id);
if (que >= ha->max_req_queues || !ha->req_q_map[que])
goto fatal;
......@@ -2805,7 +2806,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
case ABTS_RECV_24XX:
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
/* ensure that the ATIO queue is empty */
qlt_handle_abts_recv(vha, (response_t *)pkt);
qlt_handle_abts_recv(vha, rsp,
(response_t *)pkt);
break;
} else {
/* drop through */
......@@ -2814,11 +2816,12 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
case ABTS_RESP_24XX:
case CTIO_TYPE7:
case CTIO_CRC2:
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt);
break;
case NOTIFY_ACK_TYPE:
if (pkt->handle == QLA_TGT_SKIP_HANDLE)
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
qlt_response_pkt_all_vps(vha, rsp,
(response_t *)pkt);
else
qla24xxx_nack_iocb_entry(vha, rsp->req,
(struct nack_to_isp *)pkt);
......
......@@ -640,7 +640,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
int
qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos)
uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos, bool startqp)
{
int ret = 0;
struct req_que *req = NULL;
......@@ -731,14 +731,16 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->ring_ptr, req->ring_index, req->cnt,
req->id, req->max_q_depth);
ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_fatal, base_vha, 0x00df,
"%s failed.\n", __func__);
mutex_lock(&ha->mq_lock);
clear_bit(que_id, ha->req_qid_map);
mutex_unlock(&ha->mq_lock);
goto que_failed;
if (startqp) {
ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_fatal, base_vha, 0x00df,
"%s failed.\n", __func__);
mutex_lock(&ha->mq_lock);
clear_bit(que_id, ha->req_qid_map);
mutex_unlock(&ha->mq_lock);
goto que_failed;
}
}
return req->id;
......@@ -765,7 +767,7 @@ static void qla_do_work(struct work_struct *work)
/* create response queue */
int
qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
uint8_t vp_idx, uint16_t rid, struct qla_qpair *qpair)
uint8_t vp_idx, uint16_t rid, struct qla_qpair *qpair, bool startqp)
{
int ret = 0;
struct rsp_que *rsp = NULL;
......@@ -843,14 +845,16 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
if (ret)
goto que_failed;
ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_fatal, base_vha, 0x00e7,
"%s failed.\n", __func__);
mutex_lock(&ha->mq_lock);
clear_bit(que_id, ha->rsp_qid_map);
mutex_unlock(&ha->mq_lock);
goto que_failed;
if (startqp) {
ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_fatal, base_vha, 0x00e7,
"%s failed.\n", __func__);
mutex_lock(&ha->mq_lock);
clear_bit(que_id, ha->rsp_qid_map);
mutex_unlock(&ha->mq_lock);
goto que_failed;
}
}
rsp->req = NULL;
......
......@@ -389,6 +389,13 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
ha->base_qpair->rsp = rsp;
}
rsp->qpair = ha->base_qpair;
rsp->req = req;
ha->base_qpair->vha = vha;
ha->base_qpair->qp_lock_ptr = &ha->hardware_lock;
ha->queue_pair_map[0] = ha->base_qpair;
set_bit(0, ha->qpair_qid_map);
/*
* Make sure we record at least the request and response queue zero in
* case we need to free them if part of the probe fails.
......@@ -399,9 +406,10 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
set_bit(0, ha->req_qid_map);
return 1;
fail_base_qpair:
kfree(ha->queue_pair_map);
fail_qpair_map:
kfree(ha->base_qpair);
ha->base_qpair = NULL;
fail_base_qpair:
kfree(ha->rsp_q_map);
ha->rsp_q_map = NULL;
fail_rsp_map:
......@@ -451,6 +459,15 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
int cnt;
unsigned long flags;
if (ha->queue_pair_map) {
kfree(ha->queue_pair_map);
ha->queue_pair_map = NULL;
}
if (ha->base_qpair) {
kfree(ha->base_qpair);
ha->base_qpair = NULL;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
if (!test_bit(cnt, ha->req_qid_map))
......@@ -3113,7 +3130,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Create start of day qpairs for Block MQ */
if (shost_use_blk_mq(host)) {
for (i = 0; i < ha->max_qpairs; i++)
qla2xxx_create_qpair(base_vha, 5, 0);
qla2xxx_create_qpair(base_vha, 5, 0, true);
}
}
......
This diff is collapsed.
......@@ -73,7 +73,7 @@
#define QLA_TGT_NULL_HANDLE 0
#define QLA_TGT_HANDLE_MASK 0xF0000000
#define QLA_QPID_HANDLE_MASK 0x000F0000 /* qpair id mask */
#define QLA_QPID_HANDLE_MASK 0x00FF0000 /* qpair id mask */
#define QLA_CMD_HANDLE_MASK 0x0000FFFF
#define QLA_TGT_SKIP_HANDLE (0xFFFFFFFF & ~QLA_TGT_HANDLE_MASK)
......@@ -837,6 +837,7 @@ struct qla_tgt_sess_op {
struct work_struct work;
struct list_head cmd_list;
bool aborted;
struct rsp_que *rsp;
};
enum trace_flags {
......@@ -871,6 +872,7 @@ struct qla_tgt_cmd {
uint8_t pad[7];
struct se_cmd se_cmd;
struct fc_port *sess;
struct qla_qpair *qpair;
int state;
struct work_struct work;
/* Sense buffer that will be mapped into outgoing status */
......@@ -948,6 +950,7 @@ struct qla_tgt_mgmt_cmd {
uint16_t tmr_func;
uint8_t fc_tm_rsp;
struct fc_port *sess;
struct qla_qpair *qpair;
struct se_cmd se_cmd;
struct work_struct free_work;
unsigned int flags;
......@@ -1049,7 +1052,8 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, struct rsp_que *,
response_t *);
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
......@@ -1082,7 +1086,7 @@ extern int qlt_stop_phase1(struct qla_tgt *);
extern void qlt_stop_phase2(struct qla_tgt *);
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
extern int qlt_free_qfull_cmds(struct qla_qpair *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
......
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