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

Commit 43ef0580 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Retrieve additional HBA port statistics from recent ISPs.



HBAs supporting these additional counters include ISP24xx and
ISP25xx type boards.

Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 4733fcb1
Loading
Loading
Loading
Loading
+30 −14
Original line number Original line Diff line number Diff line
@@ -967,35 +967,51 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
{
{
	scsi_qla_host_t *ha = shost_priv(shost);
	scsi_qla_host_t *ha = shost_priv(shost);
	int rval;
	int rval;
	uint16_t mb_stat[1];
	struct link_statistics *stats;
	link_stat_t stat_buf;
	dma_addr_t stats_dma;
	struct fc_host_statistics *pfc_host_stat;
	struct fc_host_statistics *pfc_host_stat;


	rval = QLA_FUNCTION_FAILED;
	pfc_host_stat = &ha->fc_host_stat;
	pfc_host_stat = &ha->fc_host_stat;
	memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
	memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));


	stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
	if (stats == NULL) {
		DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
		    __func__, ha->host_no));
		goto done;
	}
	memset(stats, 0, DMA_POOL_SIZE);

	rval = QLA_FUNCTION_FAILED;
	if (IS_FWI2_CAPABLE(ha)) {
	if (IS_FWI2_CAPABLE(ha)) {
		rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
		rval = qla24xx_get_isp_stats(ha, stats, stats_dma);
		    sizeof(stat_buf) / 4, mb_stat);
	} else if (atomic_read(&ha->loop_state) == LOOP_READY &&
	} else if (atomic_read(&ha->loop_state) == LOOP_READY &&
		    !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) &&
		    !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) &&
		    !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) &&
		    !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) &&
		    !ha->dpc_active) {
		    !ha->dpc_active) {
		/* Must be in a 'READY' state for statistics retrieval. */
		/* Must be in a 'READY' state for statistics retrieval. */
		rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
		rval = qla2x00_get_link_status(ha, ha->loop_id, stats,
		    mb_stat);
		    stats_dma);
	}
	}


	if (rval != QLA_SUCCESS)
	if (rval != QLA_SUCCESS)
		goto done;
		goto done_free;

	pfc_host_stat->link_failure_count = stats->link_fail_cnt;
	pfc_host_stat->loss_of_sync_count = stats->loss_sync_cnt;
	pfc_host_stat->loss_of_signal_count = stats->loss_sig_cnt;
	pfc_host_stat->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
	pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
	pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
	if (IS_FWI2_CAPABLE(ha)) {
		pfc_host_stat->tx_frames = stats->tx_frames;
		pfc_host_stat->rx_frames = stats->rx_frames;
		pfc_host_stat->dumped_frames = stats->dumped_frames;
		pfc_host_stat->nos_count = stats->nos_rcvd;
	}


	pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
done_free:
	pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
        dma_pool_free(ha->s_dma_pool, stats, stats_dma);
	pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt;
	pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
	pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
	pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
done:
done:
	return pfc_host_stat;
	return pfc_host_stat;
}
}
+14 −8
Original line number Original line Diff line number Diff line
@@ -862,14 +862,20 @@ typedef struct {
#define GLSO_SEND_RPS	BIT_0
#define GLSO_SEND_RPS	BIT_0
#define GLSO_USE_DID	BIT_3
#define GLSO_USE_DID	BIT_3


typedef struct {
struct link_statistics {
	uint32_t link_fail_cnt;
	uint32_t link_fail_cnt;
	uint32_t loss_sync_cnt;
	uint32_t loss_sync_cnt;
	uint32_t loss_sig_cnt;
	uint32_t loss_sig_cnt;
	uint32_t prim_seq_err_cnt;
	uint32_t prim_seq_err_cnt;
	uint32_t inval_xmit_word_cnt;
	uint32_t inval_xmit_word_cnt;
	uint32_t inval_crc_cnt;
	uint32_t inval_crc_cnt;
} link_stat_t;
	uint32_t unused1[0x1b];
	uint32_t tx_frames;
	uint32_t rx_frames;
	uint32_t dumped_frames;
	uint32_t unused2[2];
	uint32_t nos_rcvd;
};


/*
/*
 * NVRAM Command values.
 * NVRAM Command values.
+4 −3
Original line number Original line Diff line number Diff line
@@ -222,11 +222,12 @@ extern int
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);


extern int
extern int
qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *,
qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
    uint16_t *);
    dma_addr_t);


extern int
extern int
qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *);
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 *);
extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
extern int qla24xx_abort_target(fc_port_t *);
extern int qla24xx_abort_target(fc_port_t *);
+26 −73
Original line number Original line Diff line number Diff line
@@ -2042,29 +2042,20 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
 */
 */
int
int
qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
    link_stat_t *ret_buf, uint16_t *status)
    struct link_statistics *stats, dma_addr_t stats_dma)
{
{
	int rval;
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;
	mbx_cmd_t *mcp = &mc;
	link_stat_t *stat_buf;
	uint32_t *siter, *diter, dwords;
	dma_addr_t stat_buf_dma;


	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));


	stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
	if (stat_buf == NULL) {
		DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
		    __func__, ha->host_no));
		return BIT_0;
	}
	memset(stat_buf, 0, sizeof(link_stat_t));

	mcp->mb[0] = MBC_GET_LINK_STATUS;
	mcp->mb[0] = MBC_GET_LINK_STATUS;
	mcp->mb[2] = MSW(stat_buf_dma);
	mcp->mb[2] = MSW(stats_dma);
	mcp->mb[3] = LSW(stat_buf_dma);
	mcp->mb[3] = LSW(stats_dma);
	mcp->mb[6] = MSW(MSD(stat_buf_dma));
	mcp->mb[6] = MSW(MSD(stats_dma));
	mcp->mb[7] = LSW(MSD(stat_buf_dma));
	mcp->mb[7] = LSW(MSD(stats_dma));
	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
	mcp->in_mb = MBX_0;
	mcp->in_mb = MBX_0;
	if (IS_FWI2_CAPABLE(ha)) {
	if (IS_FWI2_CAPABLE(ha)) {
@@ -2089,78 +2080,43 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
			DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
			DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
			    __func__, ha->host_no, mcp->mb[0]));
			    __func__, ha->host_no, mcp->mb[0]));
			status[0] = mcp->mb[0];
			rval = QLA_FUNCTION_FAILED;
			rval = BIT_1;
		} else {
		} else {
			/* copy over data -- firmware data is LE. */
			/* Copy over data -- firmware data is LE. */
			ret_buf->link_fail_cnt =
			dwords = offsetof(struct link_statistics, unused1) / 4;
			    le32_to_cpu(stat_buf->link_fail_cnt);
			siter = diter = &stats->link_fail_cnt;
			ret_buf->loss_sync_cnt =
			while (dwords--)
			    le32_to_cpu(stat_buf->loss_sync_cnt);
				*diter++ = le32_to_cpu(*siter++);
			ret_buf->loss_sig_cnt =
			    le32_to_cpu(stat_buf->loss_sig_cnt);
			ret_buf->prim_seq_err_cnt =
			    le32_to_cpu(stat_buf->prim_seq_err_cnt);
			ret_buf->inval_xmit_word_cnt =
			    le32_to_cpu(stat_buf->inval_xmit_word_cnt);
			ret_buf->inval_crc_cnt =
			    le32_to_cpu(stat_buf->inval_crc_cnt);

			DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d "
			    "loss_sync=%d loss_sig=%d seq_err=%d "
			    "inval_xmt_word=%d inval_crc=%d.\n", __func__,
			    ha->host_no, stat_buf->link_fail_cnt,
			    stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
			    stat_buf->prim_seq_err_cnt,
			    stat_buf->inval_xmit_word_cnt,
			    stat_buf->inval_crc_cnt));
		}
		}
	} else {
	} else {
		/* Failed. */
		/* Failed. */
		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
		    ha->host_no, rval));
		    ha->host_no, rval));
		rval = BIT_1;
	}
	}


	dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma);

	return rval;
	return rval;
}
}


int
int
qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
qla24xx_get_isp_stats(scsi_qla_host_t *ha, struct link_statistics *stats,
    uint16_t *status)
    dma_addr_t stats_dma)
{
{
	int rval;
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;
	mbx_cmd_t *mcp = &mc;
	uint32_t *sbuf, *siter;
	uint32_t *siter, *diter, dwords;
	dma_addr_t sbuf_dma;


	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));


	if (dwords > (DMA_POOL_SIZE / 4)) {
		DEBUG2_3_11(printk("%s(%ld): Unabled to retrieve %d DWORDs "
		    "(max %d).\n", __func__, ha->host_no, dwords,
		    DMA_POOL_SIZE / 4));
		return BIT_0;
	}
	sbuf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &sbuf_dma);
	if (sbuf == NULL) {
		DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
		    __func__, ha->host_no));
		return BIT_0;
	}
	memset(sbuf, 0, DMA_POOL_SIZE);

	mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
	mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
	mcp->mb[2] = MSW(sbuf_dma);
	mcp->mb[2] = MSW(stats_dma);
	mcp->mb[3] = LSW(sbuf_dma);
	mcp->mb[3] = LSW(stats_dma);
	mcp->mb[6] = MSW(MSD(sbuf_dma));
	mcp->mb[6] = MSW(MSD(stats_dma));
	mcp->mb[7] = LSW(MSD(sbuf_dma));
	mcp->mb[7] = LSW(MSD(stats_dma));
	mcp->mb[8] = dwords;
	mcp->mb[8] = sizeof(struct link_statistics) / 4;
	mcp->mb[9] = ha->vp_idx;
	mcp->mb[10] = 0;
	mcp->mb[10] = 0;
	mcp->out_mb = MBX_10|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
	mcp->in_mb = MBX_2|MBX_1|MBX_0;
	mcp->in_mb = MBX_2|MBX_1|MBX_0;
	mcp->tov = 30;
	mcp->tov = 30;
	mcp->flags = IOCTL_CMD;
	mcp->flags = IOCTL_CMD;
@@ -2170,23 +2126,20 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
			DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
			DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
			    __func__, ha->host_no, mcp->mb[0]));
			    __func__, ha->host_no, mcp->mb[0]));
			status[0] = mcp->mb[0];
			rval = QLA_FUNCTION_FAILED;
			rval = BIT_1;
		} else {
		} else {
			/* Copy over data -- firmware data is LE. */
			/* Copy over data -- firmware data is LE. */
			siter = sbuf;
			dwords = sizeof(struct link_statistics) / 4;
			siter = diter = &stats->link_fail_cnt;
			while (dwords--)
			while (dwords--)
				*dwbuf++ = le32_to_cpu(*siter++);
				*diter++ = le32_to_cpu(*siter++);
		}
		}
	} else {
	} else {
		/* Failed. */
		/* Failed. */
		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
		    ha->host_no, rval));
		    ha->host_no, rval));
		rval = BIT_1;
	}
	}


	dma_pool_free(ha->s_dma_pool, sbuf, sbuf_dma);

	return rval;
	return rval;
}
}