Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2afa19a9 authored by Anirban Chakraborty's avatar Anirban Chakraborty Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Add QoS support.



Set the number of request queues to the module paramater
ql2xmaxqueues.  Each vport gets a request queue. The QoS value
set to the request queues determines priority control for queued
IOs. If QoS value is not specified, the vports use the default
queue 0.

Signed-off-by: default avatarAnirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 7640335e
Loading
Loading
Loading
Loading
+30 −17
Original line number Diff line number Diff line
@@ -1469,11 +1469,12 @@ static int
qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
{
	int	ret = 0;
	int	cnt = 0;
	uint8_t	qos = QLA_DEFAULT_QUE_QOS;
	uint8_t	qos = 0;
	scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
	scsi_qla_host_t *vha = NULL;
	struct qla_hw_data *ha = base_vha->hw;
	uint16_t options = 0;
	int	cnt;

	ret = qla24xx_vport_create_req_sanity_check(fc_vport);
	if (ret) {
@@ -1529,23 +1530,35 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)

	qla24xx_vport_disable(fc_vport, disable);

	/* Create a queue pair for the vport */
	if (ha->mqenable) {
		if (ha->npiv_info) {
			for (; cnt < ha->nvram_npiv_size; cnt++) {
				if (ha->npiv_info[cnt].port_name ==
					vha->port_name &&
					ha->npiv_info[cnt].node_name ==
					vha->node_name) {
	ret = 0;
	if (ha->cur_vport_count <= ha->flex_port_count
		|| ha->max_req_queues == 1 || !ha->npiv_info)
		goto vport_queue;
	/* Create a request queue in QoS mode for the vport */
	for (cnt = ha->flex_port_count; cnt < ha->nvram_npiv_size; cnt++) {
		if (ha->npiv_info[cnt].port_name == vha->port_name &&
			ha->npiv_info[cnt].node_name == vha->node_name) {
			qos = ha->npiv_info[cnt].q_qos;
			break;
		}
	}
		}
		qla25xx_create_queues(vha, qos);
	if (qos) {
		ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0,
			qos);
		if (!ret)
			qla_printk(KERN_WARNING, ha,
			"Can't create request queue for vp_idx:%d\n",
			vha->vp_idx);
		else
			DEBUG2(qla_printk(KERN_INFO, ha,
			"Request Que:%d created for vp_idx:%d\n",
			ret, vha->vp_idx));
	}

vport_queue:
	vha->req = ha->req_q_map[ret];
	return 0;

vport_create_failed_2:
	qla24xx_disable_vp(vha);
	qla24xx_deallocate_vp_id(vha);
@@ -1586,8 +1599,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
		    vha->host_no, vha->vp_idx, vha));
        }

	if (ha->mqenable) {
		if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
	if (vha->req->id) {
		if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
			qla_printk(KERN_WARNING, ha,
				"Queue delete failed.\n");
	}
+3 −4
Original line number Diff line number Diff line
@@ -351,7 +351,7 @@ static inline void *
qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
{
	uint32_t cnt, que_idx;
	uint8_t req_cnt, rsp_cnt, que_cnt;
	uint8_t que_cnt;
	struct qla2xxx_mq_chain *mq = ptr;
	struct device_reg_25xxmq __iomem *reg;

@@ -363,9 +363,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
	mq->type = __constant_htonl(DUMP_CHAIN_MQ);
	mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain));

	req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues);
	rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues);
	que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt;
	que_cnt = ha->max_req_queues > ha->max_rsp_queues ?
		ha->max_req_queues : ha->max_rsp_queues;
	mq->count = htonl(que_cnt);
	for (cnt = 0; cnt < que_cnt; cnt++) {
		reg = (struct device_reg_25xxmq *) ((void *)
+12 −11
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@
#define LSD(x)	((uint32_t)((uint64_t)(x)))
#define MSD(x)	((uint32_t)((((uint64_t)(x)) >> 16) >> 16))

#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y)))

/*
 * I/O register
@@ -179,6 +180,7 @@
#define REQUEST_ENTRY_CNT_24XX		2048	/* Number of request entries. */
#define RESPONSE_ENTRY_CNT_2100		64	/* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300		512	/* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_MQ		128	/* Number of response entries.*/

struct req_que;

@@ -2008,7 +2010,8 @@ typedef struct vport_params {
#define VP_RET_CODE_NOT_FOUND		6

struct qla_hw_data;

struct req_que;
struct rsp_que;
/*
 * ISP operations
 */
@@ -2030,10 +2033,9 @@ struct isp_operations {
	void (*enable_intrs) (struct qla_hw_data *);
	void (*disable_intrs) (struct qla_hw_data *);

	int (*abort_command) (struct scsi_qla_host *, srb_t *,
		struct req_que *);
	int (*target_reset) (struct fc_port *, unsigned int);
	int (*lun_reset) (struct fc_port *, unsigned int);
	int (*abort_command) (srb_t *);
	int (*target_reset) (struct fc_port *, unsigned int, int);
	int (*lun_reset) (struct fc_port *, unsigned int, int);
	int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
		uint8_t, uint8_t, uint16_t *, uint8_t);
	int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
@@ -2079,7 +2081,6 @@ struct isp_operations {
#define QLA_PCI_MSIX_CONTROL	0xa2

struct scsi_qla_host;
struct rsp_que;

struct qla_msix_entry {
	int have_irq;
@@ -2140,7 +2141,6 @@ struct qla_statistics {
#define MBC_INITIALIZE_MULTIQ 0x1f
#define QLA_QUE_PAGE 0X1000
#define QLA_MQ_SIZE 32
#define QLA_MAX_HOST_QUES 16
#define QLA_MAX_QUEUES 256
#define ISP_QUE_REG(ha, id) \
	((ha->mqenable) ? \
@@ -2170,6 +2170,7 @@ struct rsp_que {
	struct qla_hw_data *hw;
	struct qla_msix_entry *msix;
	struct req_que *req;
	srb_t *status_srb; /* status continuation entry */
};

/* Request queue data structure */
@@ -2246,7 +2247,8 @@ struct qla_hw_data {
	struct rsp_que **rsp_q_map;
	unsigned long req_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
	unsigned long rsp_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
	uint16_t 	max_queues;
	uint8_t 	max_req_queues;
	uint8_t 	max_rsp_queues;
	struct qla_npiv_entry *npiv_info;
	uint16_t	nvram_npiv_size;

@@ -2532,6 +2534,7 @@ struct qla_hw_data {
	uint16_t        num_vsans;      /* number of vsan created */
	uint16_t        max_npiv_vports;        /* 63 or 125 per topoloty */
	int             cur_vport_count;
	uint16_t	flex_port_count;

	struct qla_chip_state_84xx *cs84xx;
	struct qla_statistics qla_stats;
@@ -2591,8 +2594,6 @@ typedef struct scsi_qla_host {
#define SWITCH_FOUND		BIT_0
#define DFLG_NO_CABLE		BIT_1

	srb_t		*status_srb;	/* Status continuation entry. */

	/* ISP configuration data. */
	uint16_t	loop_id;		/* Host adapter loop id */

@@ -2648,7 +2649,7 @@ typedef struct scsi_qla_host {
#define VP_ERR_FAB_LOGOUT	4
#define VP_ERR_ADAP_NORESOURCES	5
	struct qla_hw_data *hw;
	int	req_ques[QLA_MAX_HOST_QUES];
	struct req_que *req;
} scsi_qla_host_t;

/*
+16 −11
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ extern int ql2xextended_error_logging;
extern int ql2xqfullrampup;
extern int ql2xiidmaenable;
extern int ql2xmaxqueues;
extern int ql2xmultique_tag;

extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -165,13 +166,13 @@ extern int
qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);

extern int
qla2x00_abort_command(scsi_qla_host_t *, srb_t *, struct req_que *);
qla2x00_abort_command(srb_t *);

extern int
qla2x00_abort_target(struct fc_port *, unsigned int);
qla2x00_abort_target(struct fc_port *, unsigned int, int);

extern int
qla2x00_lun_reset(struct fc_port *, unsigned int);
qla2x00_lun_reset(struct fc_port *, unsigned int, int);

extern int
qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
@@ -236,9 +237,11 @@ extern int
qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
    dma_addr_t);

extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *, struct req_que *);
extern int qla24xx_abort_target(struct fc_port *, unsigned int);
extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
extern int qla24xx_abort_command(srb_t *);
extern int
qla24xx_abort_target(struct fc_port *, unsigned int, int);
extern int
qla24xx_lun_reset(struct fc_port *, unsigned int, int);

extern int
qla2x00_system_error(scsi_qla_host_t *);
@@ -295,8 +298,8 @@ extern irqreturn_t qla2100_intr_handler(int, void *);
extern irqreturn_t qla2300_intr_handler(int, void *);
extern irqreturn_t qla24xx_intr_handler(int, void *);
extern void qla2x00_process_response_queue(struct rsp_que *);
extern void qla24xx_process_response_queue(struct rsp_que *);

extern void
qla24xx_process_response_queue(struct scsi_qla_host *, struct rsp_que *);
extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *);
extern void qla2x00_free_irqs(scsi_qla_host_t *);

@@ -401,19 +404,21 @@ extern int qla25xx_request_irq(struct rsp_que *);
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, uint8_t, uint8_t);
	uint16_t, int, uint8_t);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
	uint16_t);
	uint16_t, int);
extern int qla25xx_update_req_que(struct scsi_qla_host *, uint8_t, uint8_t);
extern void qla2x00_init_response_q_entries(struct rsp_que *);
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_queues(struct scsi_qla_host *, uint8_t);
extern int qla25xx_delete_queues(struct scsi_qla_host *, uint8_t);
extern int qla25xx_delete_queues(struct scsi_qla_host *);
extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t);
extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t);
extern void qla24xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern struct scsi_qla_host * qla25xx_get_host(struct rsp_que *);

#endif /* _QLA_GBL_H */
+14 −16
Original line number Diff line number Diff line
@@ -786,7 +786,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
		    sizeof(uint32_t);
		if (ha->mqenable)
			mq_size = sizeof(struct qla2xxx_mq_chain);

		/* Allocate memory for Fibre Channel Event Buffer. */
		if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
			goto try_eft;
@@ -850,8 +849,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
	rsp_q_size = rsp->length * sizeof(response_t);

	dump_size = offsetof(struct qla2xxx_fw_dump, isp);
	dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
	    eft_size;
	dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
	ha->chain_offset = dump_size;
	dump_size += mq_size + fce_size;

@@ -1013,12 +1011,14 @@ qla2x00_init_response_q_entries(struct rsp_que *rsp)
	uint16_t cnt;
	response_t *pkt;

	rsp->ring_ptr = rsp->ring;
	rsp->ring_index    = 0;
	rsp->status_srb = NULL;
	pkt = rsp->ring_ptr;
	for (cnt = 0; cnt < rsp->length; cnt++) {
		pkt->signature = RESPONSE_PROCESSED;
		pkt++;
	}

}

/**
@@ -1176,7 +1176,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
		if (ha->flags.msix_enabled) {
			msix = &ha->msix_entries[1];
			DEBUG2_17(printk(KERN_INFO
			"Reistering vector 0x%x for base que\n", msix->entry));
			"Registering vector 0x%x for base que\n", msix->entry));
			icb->msix = cpu_to_le16(msix->entry);
		}
		/* Use alternate PCI bus number */
@@ -1230,14 +1230,14 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
	spin_lock_irqsave(&ha->hardware_lock, flags);

	/* Clear outstanding commands array. */
	for (que = 0; que < ha->max_queues; que++) {
	for (que = 0; que < ha->max_req_queues; que++) {
		req = ha->req_q_map[que];
		if (!req)
			continue;
		for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
			req->outstanding_cmds[cnt] = NULL;

		req->current_outstanding_cmd = 0;
		req->current_outstanding_cmd = 1;

		/* Initialize firmware. */
		req->ring_ptr  = req->ring;
@@ -1245,13 +1245,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
		req->cnt      = req->length;
	}

	for (que = 0; que < ha->max_queues; que++) {
	for (que = 0; que < ha->max_rsp_queues; que++) {
		rsp = ha->rsp_q_map[que];
		if (!rsp)
			continue;
		rsp->ring_ptr = rsp->ring;
		rsp->ring_index    = 0;

		/* Initialize response queue entries */
		qla2x00_init_response_q_entries(rsp);
	}
@@ -3180,8 +3177,7 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
{
	int rval = QLA_SUCCESS;
	uint32_t wait_time;
	struct qla_hw_data *ha = vha->hw;
	struct req_que *req = ha->req_q_map[vha->req_ques[0]];
	struct req_que *req = vha->req;
	struct rsp_que *rsp = req->rsp;

	atomic_set(&vha->loop_state, LOOP_UPDATE);
@@ -3448,7 +3444,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
	int ret = -1;
	int i;

	for (i = 1; i < ha->max_queues; i++) {
	for (i = 1; i < ha->max_rsp_queues; i++) {
		rsp = ha->rsp_q_map[i];
		if (rsp) {
			rsp->options &= ~BIT_0;
@@ -3462,6 +3458,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)
					"%s Rsp que:%d inited\n", __func__,
						rsp->id));
		}
	}
	for (i = 1; i < ha->max_req_queues; i++) {
		req = ha->req_q_map[i];
		if (req) {
		/* Clear outstanding commands array. */
@@ -4165,7 +4163,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
	uint16_t mb[MAILBOX_REGISTER_COUNT];
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
	struct req_que *req = ha->req_q_map[vha->req_ques[0]];
	struct req_que *req = vha->req;
	struct rsp_que *rsp = req->rsp;

	if (!vha->vp_idx)
Loading