cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ql4_bsg.c (24579B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * QLogic iSCSI HBA Driver
      4 * Copyright (c) 2011-2013 QLogic Corporation
      5 */
      6
      7#include "ql4_def.h"
      8#include "ql4_glbl.h"
      9#include "ql4_bsg.h"
     10
     11static int
     12qla4xxx_read_flash(struct bsg_job *bsg_job)
     13{
     14	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
     15	struct scsi_qla_host *ha = to_qla_host(host);
     16	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
     17	struct iscsi_bsg_request *bsg_req = bsg_job->request;
     18	uint32_t offset = 0;
     19	uint32_t length = 0;
     20	dma_addr_t flash_dma;
     21	uint8_t *flash = NULL;
     22	int rval = -EINVAL;
     23
     24	bsg_reply->reply_payload_rcv_len = 0;
     25
     26	if (unlikely(pci_channel_offline(ha->pdev)))
     27		goto leave;
     28
     29	if (ql4xxx_reset_active(ha)) {
     30		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
     31		rval = -EBUSY;
     32		goto leave;
     33	}
     34
     35	if (ha->flash_state != QLFLASH_WAITING) {
     36		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
     37			   "active\n", __func__);
     38		rval = -EBUSY;
     39		goto leave;
     40	}
     41
     42	ha->flash_state = QLFLASH_READING;
     43	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
     44	length = bsg_job->reply_payload.payload_len;
     45
     46	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
     47				   GFP_KERNEL);
     48	if (!flash) {
     49		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
     50			   "data\n", __func__);
     51		rval = -ENOMEM;
     52		goto leave;
     53	}
     54
     55	rval = qla4xxx_get_flash(ha, flash_dma, offset, length);
     56	if (rval) {
     57		ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__);
     58		bsg_reply->result = DID_ERROR << 16;
     59		rval = -EIO;
     60	} else {
     61		bsg_reply->reply_payload_rcv_len =
     62			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
     63					    bsg_job->reply_payload.sg_cnt,
     64					    flash, length);
     65		bsg_reply->result = DID_OK << 16;
     66	}
     67
     68	bsg_job_done(bsg_job, bsg_reply->result,
     69		     bsg_reply->reply_payload_rcv_len);
     70	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
     71leave:
     72	ha->flash_state = QLFLASH_WAITING;
     73	return rval;
     74}
     75
     76static int
     77qla4xxx_update_flash(struct bsg_job *bsg_job)
     78{
     79	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
     80	struct scsi_qla_host *ha = to_qla_host(host);
     81	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
     82	struct iscsi_bsg_request *bsg_req = bsg_job->request;
     83	uint32_t length = 0;
     84	uint32_t offset = 0;
     85	uint32_t options = 0;
     86	dma_addr_t flash_dma;
     87	uint8_t *flash = NULL;
     88	int rval = -EINVAL;
     89
     90	bsg_reply->reply_payload_rcv_len = 0;
     91
     92	if (unlikely(pci_channel_offline(ha->pdev)))
     93		goto leave;
     94
     95	if (ql4xxx_reset_active(ha)) {
     96		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
     97		rval = -EBUSY;
     98		goto leave;
     99	}
    100
    101	if (ha->flash_state != QLFLASH_WAITING) {
    102		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
    103			   "active\n", __func__);
    104		rval = -EBUSY;
    105		goto leave;
    106	}
    107
    108	ha->flash_state = QLFLASH_WRITING;
    109	length = bsg_job->request_payload.payload_len;
    110	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    111	options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
    112
    113	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
    114				   GFP_KERNEL);
    115	if (!flash) {
    116		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
    117			   "data\n", __func__);
    118		rval = -ENOMEM;
    119		goto leave;
    120	}
    121
    122	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
    123			  bsg_job->request_payload.sg_cnt, flash, length);
    124
    125	rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options);
    126	if (rval) {
    127		ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__);
    128		bsg_reply->result = DID_ERROR << 16;
    129		rval = -EIO;
    130	} else
    131		bsg_reply->result = DID_OK << 16;
    132
    133	bsg_job_done(bsg_job, bsg_reply->result,
    134		     bsg_reply->reply_payload_rcv_len);
    135	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
    136leave:
    137	ha->flash_state = QLFLASH_WAITING;
    138	return rval;
    139}
    140
    141static int
    142qla4xxx_get_acb_state(struct bsg_job *bsg_job)
    143{
    144	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    145	struct scsi_qla_host *ha = to_qla_host(host);
    146	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    147	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    148	uint32_t status[MBOX_REG_COUNT];
    149	uint32_t acb_idx;
    150	uint32_t ip_idx;
    151	int rval = -EINVAL;
    152
    153	bsg_reply->reply_payload_rcv_len = 0;
    154
    155	if (unlikely(pci_channel_offline(ha->pdev)))
    156		goto leave;
    157
    158	/* Only 4022 and above adapters are supported */
    159	if (is_qla4010(ha))
    160		goto leave;
    161
    162	if (ql4xxx_reset_active(ha)) {
    163		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
    164		rval = -EBUSY;
    165		goto leave;
    166	}
    167
    168	if (bsg_job->reply_payload.payload_len < sizeof(status)) {
    169		ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n",
    170			   __func__, bsg_job->reply_payload.payload_len);
    171		rval = -EINVAL;
    172		goto leave;
    173	}
    174
    175	acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    176	ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
    177
    178	rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status);
    179	if (rval) {
    180		ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n",
    181			   __func__);
    182		bsg_reply->result = DID_ERROR << 16;
    183		rval = -EIO;
    184	} else {
    185		bsg_reply->reply_payload_rcv_len =
    186			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
    187					    bsg_job->reply_payload.sg_cnt,
    188					    status, sizeof(status));
    189		bsg_reply->result = DID_OK << 16;
    190	}
    191
    192	bsg_job_done(bsg_job, bsg_reply->result,
    193		     bsg_reply->reply_payload_rcv_len);
    194leave:
    195	return rval;
    196}
    197
    198static int
    199qla4xxx_read_nvram(struct bsg_job *bsg_job)
    200{
    201	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    202	struct scsi_qla_host *ha = to_qla_host(host);
    203	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    204	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    205	uint32_t offset = 0;
    206	uint32_t len = 0;
    207	uint32_t total_len = 0;
    208	dma_addr_t nvram_dma;
    209	uint8_t *nvram = NULL;
    210	int rval = -EINVAL;
    211
    212	bsg_reply->reply_payload_rcv_len = 0;
    213
    214	if (unlikely(pci_channel_offline(ha->pdev)))
    215		goto leave;
    216
    217	/* Only 40xx adapters are supported */
    218	if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
    219		goto leave;
    220
    221	if (ql4xxx_reset_active(ha)) {
    222		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
    223		rval = -EBUSY;
    224		goto leave;
    225	}
    226
    227	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    228	len = bsg_job->reply_payload.payload_len;
    229	total_len = offset + len;
    230
    231	/* total len should not be greater than max NVRAM size */
    232	if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
    233	    ((is_qla4022(ha) || is_qla4032(ha)) &&
    234	     total_len > QL40X2_NVRAM_SIZE)) {
    235		ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
    236			   " nvram size, offset=%d len=%d\n",
    237			   __func__, offset, len);
    238		goto leave;
    239	}
    240
    241	nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
    242				   GFP_KERNEL);
    243	if (!nvram) {
    244		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram "
    245			   "data\n", __func__);
    246		rval = -ENOMEM;
    247		goto leave;
    248	}
    249
    250	rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len);
    251	if (rval) {
    252		ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__);
    253		bsg_reply->result = DID_ERROR << 16;
    254		rval = -EIO;
    255	} else {
    256		bsg_reply->reply_payload_rcv_len =
    257			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
    258					    bsg_job->reply_payload.sg_cnt,
    259					    nvram, len);
    260		bsg_reply->result = DID_OK << 16;
    261	}
    262
    263	bsg_job_done(bsg_job, bsg_reply->result,
    264		     bsg_reply->reply_payload_rcv_len);
    265	dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
    266leave:
    267	return rval;
    268}
    269
    270static int
    271qla4xxx_update_nvram(struct bsg_job *bsg_job)
    272{
    273	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    274	struct scsi_qla_host *ha = to_qla_host(host);
    275	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    276	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    277	uint32_t offset = 0;
    278	uint32_t len = 0;
    279	uint32_t total_len = 0;
    280	dma_addr_t nvram_dma;
    281	uint8_t *nvram = NULL;
    282	int rval = -EINVAL;
    283
    284	bsg_reply->reply_payload_rcv_len = 0;
    285
    286	if (unlikely(pci_channel_offline(ha->pdev)))
    287		goto leave;
    288
    289	if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
    290		goto leave;
    291
    292	if (ql4xxx_reset_active(ha)) {
    293		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
    294		rval = -EBUSY;
    295		goto leave;
    296	}
    297
    298	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    299	len = bsg_job->request_payload.payload_len;
    300	total_len = offset + len;
    301
    302	/* total len should not be greater than max NVRAM size */
    303	if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
    304	    ((is_qla4022(ha) || is_qla4032(ha)) &&
    305	     total_len > QL40X2_NVRAM_SIZE)) {
    306		ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
    307			   " nvram size, offset=%d len=%d\n",
    308			   __func__, offset, len);
    309		goto leave;
    310	}
    311
    312	nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
    313				   GFP_KERNEL);
    314	if (!nvram) {
    315		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
    316			   "data\n", __func__);
    317		rval = -ENOMEM;
    318		goto leave;
    319	}
    320
    321	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
    322			  bsg_job->request_payload.sg_cnt, nvram, len);
    323
    324	rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len);
    325	if (rval) {
    326		ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
    327		bsg_reply->result = DID_ERROR << 16;
    328		rval = -EIO;
    329	} else
    330		bsg_reply->result = DID_OK << 16;
    331
    332	bsg_job_done(bsg_job, bsg_reply->result,
    333		     bsg_reply->reply_payload_rcv_len);
    334	dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
    335leave:
    336	return rval;
    337}
    338
    339static int
    340qla4xxx_restore_defaults(struct bsg_job *bsg_job)
    341{
    342	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    343	struct scsi_qla_host *ha = to_qla_host(host);
    344	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    345	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    346	uint32_t region = 0;
    347	uint32_t field0 = 0;
    348	uint32_t field1 = 0;
    349	int rval = -EINVAL;
    350
    351	bsg_reply->reply_payload_rcv_len = 0;
    352
    353	if (unlikely(pci_channel_offline(ha->pdev)))
    354		goto leave;
    355
    356	if (is_qla4010(ha))
    357		goto leave;
    358
    359	if (ql4xxx_reset_active(ha)) {
    360		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
    361		rval = -EBUSY;
    362		goto leave;
    363	}
    364
    365	region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    366	field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
    367	field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
    368
    369	rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1);
    370	if (rval) {
    371		ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
    372		bsg_reply->result = DID_ERROR << 16;
    373		rval = -EIO;
    374	} else
    375		bsg_reply->result = DID_OK << 16;
    376
    377	bsg_job_done(bsg_job, bsg_reply->result,
    378		     bsg_reply->reply_payload_rcv_len);
    379leave:
    380	return rval;
    381}
    382
    383static int
    384qla4xxx_bsg_get_acb(struct bsg_job *bsg_job)
    385{
    386	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    387	struct scsi_qla_host *ha = to_qla_host(host);
    388	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    389	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    390	uint32_t acb_type = 0;
    391	uint32_t len = 0;
    392	dma_addr_t acb_dma;
    393	uint8_t *acb = NULL;
    394	int rval = -EINVAL;
    395
    396	bsg_reply->reply_payload_rcv_len = 0;
    397
    398	if (unlikely(pci_channel_offline(ha->pdev)))
    399		goto leave;
    400
    401	/* Only 4022 and above adapters are supported */
    402	if (is_qla4010(ha))
    403		goto leave;
    404
    405	if (ql4xxx_reset_active(ha)) {
    406		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
    407		rval = -EBUSY;
    408		goto leave;
    409	}
    410
    411	acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    412	len = bsg_job->reply_payload.payload_len;
    413	if (len < sizeof(struct addr_ctrl_blk)) {
    414		ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n",
    415			   __func__, len);
    416		rval = -EINVAL;
    417		goto leave;
    418	}
    419
    420	acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL);
    421	if (!acb) {
    422		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb "
    423			   "data\n", __func__);
    424		rval = -ENOMEM;
    425		goto leave;
    426	}
    427
    428	rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len);
    429	if (rval) {
    430		ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__);
    431		bsg_reply->result = DID_ERROR << 16;
    432		rval = -EIO;
    433	} else {
    434		bsg_reply->reply_payload_rcv_len =
    435			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
    436					    bsg_job->reply_payload.sg_cnt,
    437					    acb, len);
    438		bsg_reply->result = DID_OK << 16;
    439	}
    440
    441	bsg_job_done(bsg_job, bsg_reply->result,
    442		     bsg_reply->reply_payload_rcv_len);
    443	dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma);
    444leave:
    445	return rval;
    446}
    447
    448static void ql4xxx_execute_diag_cmd(struct bsg_job *bsg_job)
    449{
    450	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    451	struct scsi_qla_host *ha = to_qla_host(host);
    452	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    453	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    454	uint8_t *rsp_ptr = NULL;
    455	uint32_t mbox_cmd[MBOX_REG_COUNT];
    456	uint32_t mbox_sts[MBOX_REG_COUNT];
    457	int status = QLA_ERROR;
    458
    459	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__));
    460
    461	if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
    462		ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n",
    463			   __func__);
    464		bsg_reply->result = DID_ERROR << 16;
    465		goto exit_diag_mem_test;
    466	}
    467
    468	bsg_reply->reply_payload_rcv_len = 0;
    469	memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1],
    470	       sizeof(uint32_t) * MBOX_REG_COUNT);
    471
    472	DEBUG2(ql4_printk(KERN_INFO, ha,
    473			  "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n",
    474			  __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2],
    475			  mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6],
    476			  mbox_cmd[7]));
    477
    478	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
    479					 &mbox_sts[0]);
    480
    481	DEBUG2(ql4_printk(KERN_INFO, ha,
    482			  "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n",
    483			  __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2],
    484			  mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6],
    485			  mbox_sts[7]));
    486
    487	if (status == QLA_SUCCESS)
    488		bsg_reply->result = DID_OK << 16;
    489	else
    490		bsg_reply->result = DID_ERROR << 16;
    491
    492	/* Send mbox_sts to application */
    493	bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts);
    494	rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply);
    495	memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts));
    496
    497exit_diag_mem_test:
    498	DEBUG2(ql4_printk(KERN_INFO, ha,
    499			  "%s: bsg_reply->result = x%x, status = %s\n",
    500			  __func__, bsg_reply->result, STATUS(status)));
    501
    502	bsg_job_done(bsg_job, bsg_reply->result,
    503		     bsg_reply->reply_payload_rcv_len);
    504}
    505
    506static int qla4_83xx_wait_for_loopback_config_comp(struct scsi_qla_host *ha,
    507						   int wait_for_link)
    508{
    509	int status = QLA_SUCCESS;
    510
    511	if (!wait_for_completion_timeout(&ha->idc_comp, (IDC_COMP_TOV * HZ))) {
    512		ql4_printk(KERN_INFO, ha, "%s: IDC Complete notification not received, Waiting for another %d timeout",
    513			   __func__, ha->idc_extend_tmo);
    514		if (ha->idc_extend_tmo) {
    515			if (!wait_for_completion_timeout(&ha->idc_comp,
    516						(ha->idc_extend_tmo * HZ))) {
    517				ha->notify_idc_comp = 0;
    518				ha->notify_link_up_comp = 0;
    519				ql4_printk(KERN_WARNING, ha, "%s: Aborting: IDC Complete notification not received",
    520					   __func__);
    521				status = QLA_ERROR;
    522				goto exit_wait;
    523			} else {
    524				DEBUG2(ql4_printk(KERN_INFO, ha,
    525						  "%s: IDC Complete notification received\n",
    526						  __func__));
    527			}
    528		}
    529	} else {
    530		DEBUG2(ql4_printk(KERN_INFO, ha,
    531				  "%s: IDC Complete notification received\n",
    532				  __func__));
    533	}
    534	ha->notify_idc_comp = 0;
    535
    536	if (wait_for_link) {
    537		if (!wait_for_completion_timeout(&ha->link_up_comp,
    538						 (IDC_COMP_TOV * HZ))) {
    539			ha->notify_link_up_comp = 0;
    540			ql4_printk(KERN_WARNING, ha, "%s: Aborting: LINK UP notification not received",
    541				   __func__);
    542			status = QLA_ERROR;
    543			goto exit_wait;
    544		} else {
    545			DEBUG2(ql4_printk(KERN_INFO, ha,
    546					  "%s: LINK UP notification received\n",
    547					  __func__));
    548		}
    549		ha->notify_link_up_comp = 0;
    550	}
    551
    552exit_wait:
    553	return status;
    554}
    555
    556static int qla4_83xx_pre_loopback_config(struct scsi_qla_host *ha,
    557					 uint32_t *mbox_cmd)
    558{
    559	uint32_t config = 0;
    560	int status = QLA_SUCCESS;
    561
    562	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__));
    563
    564	status = qla4_83xx_get_port_config(ha, &config);
    565	if (status != QLA_SUCCESS)
    566		goto exit_pre_loopback_config;
    567
    568	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Default port config=%08X\n",
    569			  __func__, config));
    570
    571	if ((config & ENABLE_INTERNAL_LOOPBACK) ||
    572	    (config & ENABLE_EXTERNAL_LOOPBACK)) {
    573		ql4_printk(KERN_INFO, ha, "%s: Loopback diagnostics already in progress. Invalid request\n",
    574			   __func__);
    575		goto exit_pre_loopback_config;
    576	}
    577
    578	if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK)
    579		config |= ENABLE_INTERNAL_LOOPBACK;
    580
    581	if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK)
    582		config |= ENABLE_EXTERNAL_LOOPBACK;
    583
    584	config &= ~ENABLE_DCBX;
    585
    586	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: New port config=%08X\n",
    587			  __func__, config));
    588
    589	ha->notify_idc_comp = 1;
    590	ha->notify_link_up_comp = 1;
    591
    592	/* get the link state */
    593	qla4xxx_get_firmware_state(ha);
    594
    595	status = qla4_83xx_set_port_config(ha, &config);
    596	if (status != QLA_SUCCESS) {
    597		ha->notify_idc_comp = 0;
    598		ha->notify_link_up_comp = 0;
    599		goto exit_pre_loopback_config;
    600	}
    601exit_pre_loopback_config:
    602	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__,
    603			  STATUS(status)));
    604	return status;
    605}
    606
    607static int qla4_83xx_post_loopback_config(struct scsi_qla_host *ha,
    608					  uint32_t *mbox_cmd)
    609{
    610	int status = QLA_SUCCESS;
    611	uint32_t config = 0;
    612
    613	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__));
    614
    615	status = qla4_83xx_get_port_config(ha, &config);
    616	if (status != QLA_SUCCESS)
    617		goto exit_post_loopback_config;
    618
    619	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: port config=%08X\n", __func__,
    620			  config));
    621
    622	if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK)
    623		config &= ~ENABLE_INTERNAL_LOOPBACK;
    624	else if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK)
    625		config &= ~ENABLE_EXTERNAL_LOOPBACK;
    626
    627	config |= ENABLE_DCBX;
    628
    629	DEBUG2(ql4_printk(KERN_INFO, ha,
    630			  "%s: Restore default port config=%08X\n", __func__,
    631			  config));
    632
    633	ha->notify_idc_comp = 1;
    634	if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP)
    635		ha->notify_link_up_comp = 1;
    636
    637	status = qla4_83xx_set_port_config(ha, &config);
    638	if (status != QLA_SUCCESS) {
    639		ql4_printk(KERN_INFO, ha, "%s: Scheduling adapter reset\n",
    640			   __func__);
    641		set_bit(DPC_RESET_HA, &ha->dpc_flags);
    642		clear_bit(AF_LOOPBACK, &ha->flags);
    643		goto exit_post_loopback_config;
    644	}
    645
    646exit_post_loopback_config:
    647	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__,
    648			  STATUS(status)));
    649	return status;
    650}
    651
    652static void qla4xxx_execute_diag_loopback_cmd(struct bsg_job *bsg_job)
    653{
    654	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    655	struct scsi_qla_host *ha = to_qla_host(host);
    656	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    657	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    658	uint8_t *rsp_ptr = NULL;
    659	uint32_t mbox_cmd[MBOX_REG_COUNT];
    660	uint32_t mbox_sts[MBOX_REG_COUNT];
    661	int wait_for_link = 1;
    662	int status = QLA_ERROR;
    663
    664	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__));
    665
    666	bsg_reply->reply_payload_rcv_len = 0;
    667
    668	if (test_bit(AF_LOOPBACK, &ha->flags)) {
    669		ql4_printk(KERN_INFO, ha, "%s: Loopback Diagnostics already in progress. Invalid Request\n",
    670			   __func__);
    671		bsg_reply->result = DID_ERROR << 16;
    672		goto exit_loopback_cmd;
    673	}
    674
    675	if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
    676		ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n",
    677			   __func__);
    678		bsg_reply->result = DID_ERROR << 16;
    679		goto exit_loopback_cmd;
    680	}
    681
    682	memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1],
    683	       sizeof(uint32_t) * MBOX_REG_COUNT);
    684
    685	if (is_qla8032(ha) || is_qla8042(ha)) {
    686		status = qla4_83xx_pre_loopback_config(ha, mbox_cmd);
    687		if (status != QLA_SUCCESS) {
    688			bsg_reply->result = DID_ERROR << 16;
    689			goto exit_loopback_cmd;
    690		}
    691
    692		status = qla4_83xx_wait_for_loopback_config_comp(ha,
    693								 wait_for_link);
    694		if (status != QLA_SUCCESS) {
    695			bsg_reply->result = DID_TIME_OUT << 16;
    696			goto restore;
    697		}
    698	}
    699
    700	DEBUG2(ql4_printk(KERN_INFO, ha,
    701			  "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n",
    702			  __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2],
    703			  mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6],
    704			  mbox_cmd[7]));
    705
    706	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
    707				&mbox_sts[0]);
    708
    709	if (status == QLA_SUCCESS)
    710		bsg_reply->result = DID_OK << 16;
    711	else
    712		bsg_reply->result = DID_ERROR << 16;
    713
    714	DEBUG2(ql4_printk(KERN_INFO, ha,
    715			  "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n",
    716			  __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2],
    717			  mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6],
    718			  mbox_sts[7]));
    719
    720	/* Send mbox_sts to application */
    721	bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts);
    722	rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply);
    723	memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts));
    724restore:
    725	if (is_qla8032(ha) || is_qla8042(ha)) {
    726		status = qla4_83xx_post_loopback_config(ha, mbox_cmd);
    727		if (status != QLA_SUCCESS) {
    728			bsg_reply->result = DID_ERROR << 16;
    729			goto exit_loopback_cmd;
    730		}
    731
    732		/* for pre_loopback_config() wait for LINK UP only
    733		 * if PHY LINK is UP */
    734		if (!(ha->addl_fw_state & FW_ADDSTATE_LINK_UP))
    735			wait_for_link = 0;
    736
    737		status = qla4_83xx_wait_for_loopback_config_comp(ha,
    738								 wait_for_link);
    739		if (status != QLA_SUCCESS) {
    740			bsg_reply->result = DID_TIME_OUT << 16;
    741			goto exit_loopback_cmd;
    742		}
    743	}
    744exit_loopback_cmd:
    745	DEBUG2(ql4_printk(KERN_INFO, ha,
    746			  "%s: bsg_reply->result = x%x, status = %s\n",
    747			  __func__, bsg_reply->result, STATUS(status)));
    748	bsg_job_done(bsg_job, bsg_reply->result,
    749		     bsg_reply->reply_payload_rcv_len);
    750}
    751
    752static int qla4xxx_execute_diag_test(struct bsg_job *bsg_job)
    753{
    754	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    755	struct scsi_qla_host *ha = to_qla_host(host);
    756	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    757	uint32_t diag_cmd;
    758	int rval = -EINVAL;
    759
    760	DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__));
    761
    762	diag_cmd = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
    763	if (diag_cmd == MBOX_CMD_DIAG_TEST) {
    764		switch (bsg_req->rqst_data.h_vendor.vendor_cmd[2]) {
    765		case QL_DIAG_CMD_TEST_DDR_SIZE:
    766		case QL_DIAG_CMD_TEST_DDR_RW:
    767		case QL_DIAG_CMD_TEST_ONCHIP_MEM_RW:
    768		case QL_DIAG_CMD_TEST_NVRAM:
    769		case QL_DIAG_CMD_TEST_FLASH_ROM:
    770		case QL_DIAG_CMD_TEST_DMA_XFER:
    771		case QL_DIAG_CMD_SELF_DDR_RW:
    772		case QL_DIAG_CMD_SELF_ONCHIP_MEM_RW:
    773			/* Execute diag test for adapter RAM/FLASH */
    774			ql4xxx_execute_diag_cmd(bsg_job);
    775			/* Always return success as we want to sent bsg_reply
    776			 * to Application */
    777			rval = QLA_SUCCESS;
    778			break;
    779
    780		case QL_DIAG_CMD_TEST_INT_LOOPBACK:
    781		case QL_DIAG_CMD_TEST_EXT_LOOPBACK:
    782			/* Execute diag test for Network */
    783			qla4xxx_execute_diag_loopback_cmd(bsg_job);
    784			/* Always return success as we want to sent bsg_reply
    785			 * to Application */
    786			rval = QLA_SUCCESS;
    787			break;
    788		default:
    789			ql4_printk(KERN_ERR, ha, "%s: Invalid diag test: 0x%x\n",
    790				   __func__,
    791				   bsg_req->rqst_data.h_vendor.vendor_cmd[2]);
    792		}
    793	} else if ((diag_cmd == MBOX_CMD_SET_LED_CONFIG) ||
    794		   (diag_cmd == MBOX_CMD_GET_LED_CONFIG)) {
    795		ql4xxx_execute_diag_cmd(bsg_job);
    796		rval = QLA_SUCCESS;
    797	} else {
    798		ql4_printk(KERN_ERR, ha, "%s: Invalid diag cmd: 0x%x\n",
    799			   __func__, diag_cmd);
    800	}
    801
    802	return rval;
    803}
    804
    805/**
    806 * qla4xxx_process_vendor_specific - handle vendor specific bsg request
    807 * @bsg_job: iscsi_bsg_job to handle
    808 **/
    809int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
    810{
    811	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
    812	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    813	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    814	struct scsi_qla_host *ha = to_qla_host(host);
    815
    816	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
    817	case QLISCSI_VND_READ_FLASH:
    818		return qla4xxx_read_flash(bsg_job);
    819
    820	case QLISCSI_VND_UPDATE_FLASH:
    821		return qla4xxx_update_flash(bsg_job);
    822
    823	case QLISCSI_VND_GET_ACB_STATE:
    824		return qla4xxx_get_acb_state(bsg_job);
    825
    826	case QLISCSI_VND_READ_NVRAM:
    827		return qla4xxx_read_nvram(bsg_job);
    828
    829	case QLISCSI_VND_UPDATE_NVRAM:
    830		return qla4xxx_update_nvram(bsg_job);
    831
    832	case QLISCSI_VND_RESTORE_DEFAULTS:
    833		return qla4xxx_restore_defaults(bsg_job);
    834
    835	case QLISCSI_VND_GET_ACB:
    836		return qla4xxx_bsg_get_acb(bsg_job);
    837
    838	case QLISCSI_VND_DIAG_TEST:
    839		return qla4xxx_execute_diag_test(bsg_job);
    840
    841	default:
    842		ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
    843			   "0x%x\n", __func__, bsg_req->msgcode);
    844		bsg_reply->result = (DID_ERROR << 16);
    845		bsg_reply->reply_payload_rcv_len = 0;
    846		bsg_job_done(bsg_job, bsg_reply->result,
    847			     bsg_reply->reply_payload_rcv_len);
    848		return -ENOSYS;
    849	}
    850}
    851
    852/**
    853 * qla4xxx_bsg_request - handle bsg request from ISCSI transport
    854 * @bsg_job: iscsi_bsg_job to handle
    855 */
    856int qla4xxx_bsg_request(struct bsg_job *bsg_job)
    857{
    858	struct iscsi_bsg_request *bsg_req = bsg_job->request;
    859	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
    860	struct scsi_qla_host *ha = to_qla_host(host);
    861
    862	switch (bsg_req->msgcode) {
    863	case ISCSI_BSG_HST_VENDOR:
    864		return qla4xxx_process_vendor_specific(bsg_job);
    865
    866	default:
    867		ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
    868			   __func__, bsg_req->msgcode);
    869	}
    870
    871	return -ENOSYS;
    872}