diff mbox

[v2,06/11] qla2xxx: Add support for Private link statistics counters.

Message ID 1453914218-380-7-git-send-email-himanshu.madhani@qlogic.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Himanshu Madhani Jan. 27, 2016, 5:03 p.m. UTC
From: Harish Zunjarrao <harish.zunjarrao@qlogic.com>

Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_attr.c |    6 ++-
 drivers/scsi/qla2xxx/qla_bsg.c  |   61 +++++++++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_bsg.h  |    1 +
 drivers/scsi/qla2xxx/qla_dbg.c  |    2 +-
 drivers/scsi/qla2xxx/qla_def.h  |   32 +++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_mbx.c  |    3 +-
 6 files changed, 99 insertions(+), 6 deletions(-)

Comments

Johannes Thumshirn Jan. 28, 2016, 8:59 a.m. UTC | #1
On Wed, Jan 27, 2016 at 12:03:33PM -0500, Himanshu Madhani wrote:
> From: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
> 
> Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
> ---
>  drivers/scsi/qla2xxx/qla_attr.c |    6 ++-
>  drivers/scsi/qla2xxx/qla_bsg.c  |   61 +++++++++++++++++++++++++++++++++++++++
>  drivers/scsi/qla2xxx/qla_bsg.h  |    1 +
>  drivers/scsi/qla2xxx/qla_dbg.c  |    2 +-
>  drivers/scsi/qla2xxx/qla_def.h  |   32 +++++++++++++++++++-
>  drivers/scsi/qla2xxx/qla_mbx.c  |    3 +-
>  6 files changed, 99 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> index fef659a..fadce04 100644
> --- a/drivers/scsi/qla2xxx/qla_attr.c
> +++ b/drivers/scsi/qla2xxx/qla_attr.c
> @@ -1917,7 +1917,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
>  	if (qla2x00_reset_active(vha))
>  		goto done;
>  
> -	stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
> +	stats = dma_alloc_coherent(&ha->pdev->dev,
> +	    sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
>  	if (stats == NULL) {
>  		ql_log(ql_log_warn, vha, 0x707d,
>  		    "Failed to allocate memory for stats.\n");
> @@ -1965,7 +1966,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
>  	do_div(pfc_host_stat->seconds_since_last_reset, HZ);
>  
>  done_free:
> -        dma_pool_free(ha->s_dma_pool, stats, stats_dma);
> +	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
> +	    stats, stats_dma);
>  done:
>  	return pfc_host_stat;
>  }
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index d135d6a..913fef2 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -2233,6 +2233,64 @@ qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job)
>  }
>  
>  static int
> +qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job)
> +{
> +	struct Scsi_Host *host = bsg_job->shost;
> +	scsi_qla_host_t *vha = shost_priv(host);
> +	struct qla_hw_data *ha = vha->hw;
> +	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
> +	struct link_statistics *stats = NULL;
> +	dma_addr_t stats_dma;
> +	int rval = QLA_FUNCTION_FAILED;
> +
> +	if (test_bit(UNLOADING, &vha->dpc_flags))
> +		goto done;
> +
> +	if (unlikely(pci_channel_offline(ha->pdev)))
> +		goto done;
> +
> +	if (qla2x00_reset_active(vha))
> +		goto done;
> +
> +	if (!IS_FWI2_CAPABLE(ha))
> +		goto done;
> +
> +	stats = dma_alloc_coherent(&ha->pdev->dev,
> +		sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
> +	if (!stats) {
> +		ql_log(ql_log_warn, vha, 0x70e2,
> +		"Failed to allocate memory for stats.\n");
> +		goto done;
> +	}
> +
> +	memset(stats, 0, sizeof(struct link_statistics));
> +
> +	rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
> +
> +	if (rval != QLA_SUCCESS)
> +		goto done_free;
> +
> +	ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
> +	    (uint8_t *)stats, sizeof(struct link_statistics));
> +
> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +	bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics));
> +	bsg_job->reply->reply_payload_rcv_len = sizeof(struct link_statistics);
> +
> +	bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +
> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
> +	bsg_job->reply->result = DID_OK << 16;
> +	bsg_job->job_done(bsg_job);
> +
> +done_free:
> +	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
> +		stats, stats_dma);
> +done:
> +	return rval;
> +}
> +
> +static int
>  qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
>  {
>  	switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
> @@ -2296,6 +2354,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
>  	case QL_VND_GET_BBCR_DATA:
>  		return qla27xx_get_bbcr_data(bsg_job);
>  
> +	case QL_VND_GET_PRIV_STATS:
> +		return qla2x00_get_priv_stats(bsg_job);
> +
>  	default:
>  		return -ENOSYS;
>  	}
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> index 4275177..c40dd8b 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.h
> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> @@ -28,6 +28,7 @@
>  #define QL_VND_GET_FLASH_UPDATE_CAPS    0x15
>  #define QL_VND_SET_FLASH_UPDATE_CAPS    0x16
>  #define QL_VND_GET_BBCR_DATA    0x17
> +#define QL_VND_GET_PRIV_STATS	0x18
>  
>  /* BSG Vendor specific subcode returns */
>  #define EXT_STATUS_OK			0
> diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
> index 493a3ea81..aa6694b 100644
> --- a/drivers/scsi/qla2xxx/qla_dbg.c
> +++ b/drivers/scsi/qla2xxx/qla_dbg.c
> @@ -32,7 +32,7 @@
>   * |                              |                    | 0x503d,0x5044  |
>   * |                              |                    | 0x507b,0x505f	|
>   * | Timer Routines               |       0x6012       |                |
> - * | User Space Interactions      |       0x70e65      | 0x7018,0x702e  |
> + * | User Space Interactions      |       0x70e3       | 0x7018,0x702e  |
>   * |				  |		       | 0x7020,0x7024  |
>   * |                              |                    | 0x7039,0x7045  |
>   * |                              |                    | 0x7073-0x7075  |
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index c4bd62a..ceb452d 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -1254,13 +1254,41 @@ struct link_statistics {
>  	uint32_t inval_xmit_word_cnt;
>  	uint32_t inval_crc_cnt;
>  	uint32_t lip_cnt;
> -	uint32_t unused1[0x1a];
> +	uint32_t link_up_cnt;
> +	uint32_t link_down_loop_init_tmo;
> +	uint32_t link_down_los;
> +	uint32_t link_down_loss_rcv_clk;
> +	uint32_t reserved0[5];
> +	uint32_t port_cfg_chg;
> +	uint32_t reserved1[11];
> +	uint32_t rsp_q_full;
> +	uint32_t atio_q_full;
> +	uint32_t drop_ae;
> +	uint32_t els_proto_err;
> +	uint32_t reserved2;
>  	uint32_t tx_frames;
>  	uint32_t rx_frames;
>  	uint32_t discarded_frames;
>  	uint32_t dropped_frames;
> -	uint32_t unused2[1];
> +	uint32_t reserved3;
>  	uint32_t nos_rcvd;
> +	uint32_t reserved4[4];
> +	uint32_t tx_prjt;
> +	uint32_t rcv_exfail;
> +	uint32_t rcv_abts;
> +	uint32_t seq_frm_miss;
> +	uint32_t corr_err;
> +	uint32_t mb_rqst;
> +	uint32_t nport_full;
> +	uint32_t eofa;
> +	uint32_t reserved5;
> +	uint32_t fpm_recv_word_cnt_lo;
> +	uint32_t fpm_recv_word_cnt_hi;
> +	uint32_t fpm_disc_word_cnt_lo;
> +	uint32_t fpm_disc_word_cnt_hi;
> +	uint32_t fpm_xmit_word_cnt_lo;
> +	uint32_t fpm_xmit_word_cnt_hi;
> +	uint32_t reserved6[70];
>  };
>  
>  /*
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index 4433cfb..3dd3398 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -2799,7 +2799,8 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
>  			/* Copy over data -- firmware data is LE. */
>  			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
>  			    "Done %s.\n", __func__);
> -			dwords = offsetof(struct link_statistics, unused1) / 4;
> +			dwords = offsetof(struct link_statistics,
> +					link_up_cnt) / 4;
>  			siter = diter = &stats->link_fail_cnt;
>  			while (dwords--)
>  				*diter++ = le32_to_cpu(*siter++);
> -- 
> 1.7.7
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Seriously, be more verbose on commit messages.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Himanshu Madhani Jan. 28, 2016, 5:34 p.m. UTC | #2
Hi Johannes,




On 1/28/16, 12:59 AM, "Johannes Thumshirn" <jthumshirn@suse.de> wrote:

>On Wed, Jan 27, 2016 at 12:03:33PM -0500, Himanshu Madhani wrote:
>> From: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
>> 
>> Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
>> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
>> ---
>>  drivers/scsi/qla2xxx/qla_attr.c |    6 ++-
>>  drivers/scsi/qla2xxx/qla_bsg.c  |   61
>>+++++++++++++++++++++++++++++++++++++++
>>  drivers/scsi/qla2xxx/qla_bsg.h  |    1 +
>>  drivers/scsi/qla2xxx/qla_dbg.c  |    2 +-
>>  drivers/scsi/qla2xxx/qla_def.h  |   32 +++++++++++++++++++-
>>  drivers/scsi/qla2xxx/qla_mbx.c  |    3 +-
>>  6 files changed, 99 insertions(+), 6 deletions(-)
>> 
>> diff --git a/drivers/scsi/qla2xxx/qla_attr.c
>>b/drivers/scsi/qla2xxx/qla_attr.c
>> index fef659a..fadce04 100644
>> --- a/drivers/scsi/qla2xxx/qla_attr.c
>> +++ b/drivers/scsi/qla2xxx/qla_attr.c
>> @@ -1917,7 +1917,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
>>  	if (qla2x00_reset_active(vha))
>>  		goto done;
>>  
>> -	stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
>> +	stats = dma_alloc_coherent(&ha->pdev->dev,
>> +	    sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
>>  	if (stats == NULL) {
>>  		ql_log(ql_log_warn, vha, 0x707d,
>>  		    "Failed to allocate memory for stats.\n");
>> @@ -1965,7 +1966,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
>>  	do_div(pfc_host_stat->seconds_since_last_reset, HZ);
>>  
>>  done_free:
>> -        dma_pool_free(ha->s_dma_pool, stats, stats_dma);
>> +	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
>> +	    stats, stats_dma);
>>  done:
>>  	return pfc_host_stat;
>>  }
>> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c
>>b/drivers/scsi/qla2xxx/qla_bsg.c
>> index d135d6a..913fef2 100644
>> --- a/drivers/scsi/qla2xxx/qla_bsg.c
>> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
>> @@ -2233,6 +2233,64 @@ qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job)
>>  }
>>  
>>  static int
>> +qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job)
>> +{
>> +	struct Scsi_Host *host = bsg_job->shost;
>> +	scsi_qla_host_t *vha = shost_priv(host);
>> +	struct qla_hw_data *ha = vha->hw;
>> +	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
>> +	struct link_statistics *stats = NULL;
>> +	dma_addr_t stats_dma;
>> +	int rval = QLA_FUNCTION_FAILED;
>> +
>> +	if (test_bit(UNLOADING, &vha->dpc_flags))
>> +		goto done;
>> +
>> +	if (unlikely(pci_channel_offline(ha->pdev)))
>> +		goto done;
>> +
>> +	if (qla2x00_reset_active(vha))
>> +		goto done;
>> +
>> +	if (!IS_FWI2_CAPABLE(ha))
>> +		goto done;
>> +
>> +	stats = dma_alloc_coherent(&ha->pdev->dev,
>> +		sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
>> +	if (!stats) {
>> +		ql_log(ql_log_warn, vha, 0x70e2,
>> +		"Failed to allocate memory for stats.\n");
>> +		goto done;
>> +	}
>> +
>> +	memset(stats, 0, sizeof(struct link_statistics));
>> +
>> +	rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
>> +
>> +	if (rval != QLA_SUCCESS)
>> +		goto done_free;
>> +
>> +	ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
>> +	    (uint8_t *)stats, sizeof(struct link_statistics));
>> +
>> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
>> +	bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics));
>> +	bsg_job->reply->reply_payload_rcv_len = sizeof(struct
>>link_statistics);
>> +
>> +	bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
>> +
>> +	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
>> +	bsg_job->reply->result = DID_OK << 16;
>> +	bsg_job->job_done(bsg_job);
>> +
>> +done_free:
>> +	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
>> +		stats, stats_dma);
>> +done:
>> +	return rval;
>> +}
>> +
>> +static int
>>  qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
>>  {
>>  	switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
>> @@ -2296,6 +2354,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job
>>*bsg_job)
>>  	case QL_VND_GET_BBCR_DATA:
>>  		return qla27xx_get_bbcr_data(bsg_job);
>>  
>> +	case QL_VND_GET_PRIV_STATS:
>> +		return qla2x00_get_priv_stats(bsg_job);
>> +
>>  	default:
>>  		return -ENOSYS;
>>  	}
>> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h
>>b/drivers/scsi/qla2xxx/qla_bsg.h
>> index 4275177..c40dd8b 100644
>> --- a/drivers/scsi/qla2xxx/qla_bsg.h
>> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
>> @@ -28,6 +28,7 @@
>>  #define QL_VND_GET_FLASH_UPDATE_CAPS    0x15
>>  #define QL_VND_SET_FLASH_UPDATE_CAPS    0x16
>>  #define QL_VND_GET_BBCR_DATA    0x17
>> +#define QL_VND_GET_PRIV_STATS	0x18
>>  
>>  /* BSG Vendor specific subcode returns */
>>  #define EXT_STATUS_OK			0
>> diff --git a/drivers/scsi/qla2xxx/qla_dbg.c
>>b/drivers/scsi/qla2xxx/qla_dbg.c
>> index 493a3ea81..aa6694b 100644
>> --- a/drivers/scsi/qla2xxx/qla_dbg.c
>> +++ b/drivers/scsi/qla2xxx/qla_dbg.c
>> @@ -32,7 +32,7 @@
>>   * |                              |                    | 0x503d,0x5044
>> |
>>   * |                              |                    |
>>0x507b,0x505f	|
>>   * | Timer Routines               |       0x6012       |
>> |
>> - * | User Space Interactions      |       0x70e65      | 0x7018,0x702e
>> |
>> + * | User Space Interactions      |       0x70e3       | 0x7018,0x702e
>> |
>>   * |				  |		       | 0x7020,0x7024  |
>>   * |                              |                    | 0x7039,0x7045
>> |
>>   * |                              |                    | 0x7073-0x7075
>> |
>> diff --git a/drivers/scsi/qla2xxx/qla_def.h
>>b/drivers/scsi/qla2xxx/qla_def.h
>> index c4bd62a..ceb452d 100644
>> --- a/drivers/scsi/qla2xxx/qla_def.h
>> +++ b/drivers/scsi/qla2xxx/qla_def.h
>> @@ -1254,13 +1254,41 @@ struct link_statistics {
>>  	uint32_t inval_xmit_word_cnt;
>>  	uint32_t inval_crc_cnt;
>>  	uint32_t lip_cnt;
>> -	uint32_t unused1[0x1a];
>> +	uint32_t link_up_cnt;
>> +	uint32_t link_down_loop_init_tmo;
>> +	uint32_t link_down_los;
>> +	uint32_t link_down_loss_rcv_clk;
>> +	uint32_t reserved0[5];
>> +	uint32_t port_cfg_chg;
>> +	uint32_t reserved1[11];
>> +	uint32_t rsp_q_full;
>> +	uint32_t atio_q_full;
>> +	uint32_t drop_ae;
>> +	uint32_t els_proto_err;
>> +	uint32_t reserved2;
>>  	uint32_t tx_frames;
>>  	uint32_t rx_frames;
>>  	uint32_t discarded_frames;
>>  	uint32_t dropped_frames;
>> -	uint32_t unused2[1];
>> +	uint32_t reserved3;
>>  	uint32_t nos_rcvd;
>> +	uint32_t reserved4[4];
>> +	uint32_t tx_prjt;
>> +	uint32_t rcv_exfail;
>> +	uint32_t rcv_abts;
>> +	uint32_t seq_frm_miss;
>> +	uint32_t corr_err;
>> +	uint32_t mb_rqst;
>> +	uint32_t nport_full;
>> +	uint32_t eofa;
>> +	uint32_t reserved5;
>> +	uint32_t fpm_recv_word_cnt_lo;
>> +	uint32_t fpm_recv_word_cnt_hi;
>> +	uint32_t fpm_disc_word_cnt_lo;
>> +	uint32_t fpm_disc_word_cnt_hi;
>> +	uint32_t fpm_xmit_word_cnt_lo;
>> +	uint32_t fpm_xmit_word_cnt_hi;
>> +	uint32_t reserved6[70];
>>  };
>>  
>>  /*
>> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c
>>b/drivers/scsi/qla2xxx/qla_mbx.c
>> index 4433cfb..3dd3398 100644
>> --- a/drivers/scsi/qla2xxx/qla_mbx.c
>> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
>> @@ -2799,7 +2799,8 @@ qla2x00_get_link_status(scsi_qla_host_t *vha,
>>uint16_t loop_id,
>>  			/* Copy over data -- firmware data is LE. */
>>  			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
>>  			    "Done %s.\n", __func__);
>> -			dwords = offsetof(struct link_statistics, unused1) / 4;
>> +			dwords = offsetof(struct link_statistics,
>> +					link_up_cnt) / 4;
>>  			siter = diter = &stats->link_fail_cnt;
>>  			while (dwords--)
>>  				*diter++ = le32_to_cpu(*siter++);
>> -- 
>> 1.7.7
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>Seriously, be more verbose on commit messages.

Thanks for reviews. I will make sure in future we will put more details
into commit messages.

>
>Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
>-- 
>Johannes Thumshirn                                          Storage
>jthumshirn@suse.de                                +49 911 74053 689
>SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
>GF: Felix Imendörffer, Jane Smithard, Graham Norton
>HRB 21284 (AG Nürnberg)
>Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
diff mbox

Patch

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index fef659a..fadce04 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1917,7 +1917,8 @@  qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 	if (qla2x00_reset_active(vha))
 		goto done;
 
-	stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
+	stats = dma_alloc_coherent(&ha->pdev->dev,
+	    sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
 	if (stats == NULL) {
 		ql_log(ql_log_warn, vha, 0x707d,
 		    "Failed to allocate memory for stats.\n");
@@ -1965,7 +1966,8 @@  qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 	do_div(pfc_host_stat->seconds_since_last_reset, HZ);
 
 done_free:
-        dma_pool_free(ha->s_dma_pool, stats, stats_dma);
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
+	    stats, stats_dma);
 done:
 	return pfc_host_stat;
 }
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index d135d6a..913fef2 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2233,6 +2233,64 @@  qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job)
 }
 
 static int
+qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job)
+{
+	struct Scsi_Host *host = bsg_job->shost;
+	scsi_qla_host_t *vha = shost_priv(host);
+	struct qla_hw_data *ha = vha->hw;
+	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+	struct link_statistics *stats = NULL;
+	dma_addr_t stats_dma;
+	int rval = QLA_FUNCTION_FAILED;
+
+	if (test_bit(UNLOADING, &vha->dpc_flags))
+		goto done;
+
+	if (unlikely(pci_channel_offline(ha->pdev)))
+		goto done;
+
+	if (qla2x00_reset_active(vha))
+		goto done;
+
+	if (!IS_FWI2_CAPABLE(ha))
+		goto done;
+
+	stats = dma_alloc_coherent(&ha->pdev->dev,
+		sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
+	if (!stats) {
+		ql_log(ql_log_warn, vha, 0x70e2,
+		"Failed to allocate memory for stats.\n");
+		goto done;
+	}
+
+	memset(stats, 0, sizeof(struct link_statistics));
+
+	rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
+
+	if (rval != QLA_SUCCESS)
+		goto done_free;
+
+	ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
+	    (uint8_t *)stats, sizeof(struct link_statistics));
+
+	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+	bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics));
+	bsg_job->reply->reply_payload_rcv_len = sizeof(struct link_statistics);
+
+	bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+	bsg_job->reply->result = DID_OK << 16;
+	bsg_job->job_done(bsg_job);
+
+done_free:
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
+		stats, stats_dma);
+done:
+	return rval;
+}
+
+static int
 qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 {
 	switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -2296,6 +2354,9 @@  qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 	case QL_VND_GET_BBCR_DATA:
 		return qla27xx_get_bbcr_data(bsg_job);
 
+	case QL_VND_GET_PRIV_STATS:
+		return qla2x00_get_priv_stats(bsg_job);
+
 	default:
 		return -ENOSYS;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 4275177..c40dd8b 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -28,6 +28,7 @@ 
 #define QL_VND_GET_FLASH_UPDATE_CAPS    0x15
 #define QL_VND_SET_FLASH_UPDATE_CAPS    0x16
 #define QL_VND_GET_BBCR_DATA    0x17
+#define QL_VND_GET_PRIV_STATS	0x18
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK			0
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 493a3ea81..aa6694b 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -32,7 +32,7 @@ 
  * |                              |                    | 0x503d,0x5044  |
  * |                              |                    | 0x507b,0x505f	|
  * | Timer Routines               |       0x6012       |                |
- * | User Space Interactions      |       0x70e65      | 0x7018,0x702e  |
+ * | User Space Interactions      |       0x70e3       | 0x7018,0x702e  |
  * |				  |		       | 0x7020,0x7024  |
  * |                              |                    | 0x7039,0x7045  |
  * |                              |                    | 0x7073-0x7075  |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index c4bd62a..ceb452d 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1254,13 +1254,41 @@  struct link_statistics {
 	uint32_t inval_xmit_word_cnt;
 	uint32_t inval_crc_cnt;
 	uint32_t lip_cnt;
-	uint32_t unused1[0x1a];
+	uint32_t link_up_cnt;
+	uint32_t link_down_loop_init_tmo;
+	uint32_t link_down_los;
+	uint32_t link_down_loss_rcv_clk;
+	uint32_t reserved0[5];
+	uint32_t port_cfg_chg;
+	uint32_t reserved1[11];
+	uint32_t rsp_q_full;
+	uint32_t atio_q_full;
+	uint32_t drop_ae;
+	uint32_t els_proto_err;
+	uint32_t reserved2;
 	uint32_t tx_frames;
 	uint32_t rx_frames;
 	uint32_t discarded_frames;
 	uint32_t dropped_frames;
-	uint32_t unused2[1];
+	uint32_t reserved3;
 	uint32_t nos_rcvd;
+	uint32_t reserved4[4];
+	uint32_t tx_prjt;
+	uint32_t rcv_exfail;
+	uint32_t rcv_abts;
+	uint32_t seq_frm_miss;
+	uint32_t corr_err;
+	uint32_t mb_rqst;
+	uint32_t nport_full;
+	uint32_t eofa;
+	uint32_t reserved5;
+	uint32_t fpm_recv_word_cnt_lo;
+	uint32_t fpm_recv_word_cnt_hi;
+	uint32_t fpm_disc_word_cnt_lo;
+	uint32_t fpm_disc_word_cnt_hi;
+	uint32_t fpm_xmit_word_cnt_lo;
+	uint32_t fpm_xmit_word_cnt_hi;
+	uint32_t reserved6[70];
 };
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 4433cfb..3dd3398 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2799,7 +2799,8 @@  qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
 			/* Copy over data -- firmware data is LE. */
 			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
 			    "Done %s.\n", __func__);
-			dwords = offsetof(struct link_statistics, unused1) / 4;
+			dwords = offsetof(struct link_statistics,
+					link_up_cnt) / 4;
 			siter = diter = &stats->link_fail_cnt;
 			while (dwords--)
 				*diter++ = le32_to_cpu(*siter++);