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

Commit 88729e53 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Add DMI (Diagnostics Monitoring Interface) support.

parent 8baa51a6
Loading
Loading
Loading
Loading
+53 −0
Original line number Original line Diff line number Diff line
@@ -338,6 +338,53 @@ static struct bin_attribute sysfs_vpd_attr = {
	.write = qla2x00_sysfs_write_vpd,
	.write = qla2x00_sysfs_write_vpd,
};
};


static ssize_t
qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
    size_t count)
{
	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
	    struct device, kobj)));
	uint16_t iter, addr, offset;
	int rval;

	if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
		return 0;

	addr = 0xa0;
	for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
	    iter++, offset += SFP_BLOCK_SIZE) {
		if (iter == 4) {
			/* Skip to next device address. */
			addr = 0xa2;
			offset = 0;
		}

		rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset,
		    SFP_BLOCK_SIZE);
		if (rval != QLA_SUCCESS) {
			qla_printk(KERN_WARNING, ha,
			    "Unable to read SFP data (%x/%x/%x).\n", rval,
			    addr, offset);
			count = 0;
			break;
		}
		memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
		buf += SFP_BLOCK_SIZE;
	}

	return count;
}

static struct bin_attribute sysfs_sfp_attr = {
	.attr = {
		.name = "sfp",
		.mode = S_IRUSR | S_IWUSR,
		.owner = THIS_MODULE,
	},
	.size = SFP_DEV_SIZE * 2,
	.read = qla2x00_sysfs_read_sfp,
};

void
void
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
{
{
@@ -349,6 +396,9 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
	sysfs_create_bin_file(&host->shost_gendev.kobj,
	sysfs_create_bin_file(&host->shost_gendev.kobj,
	    &sysfs_optrom_ctl_attr);
	    &sysfs_optrom_ctl_attr);
	sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
	sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
	if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
		sysfs_create_bin_file(&host->shost_gendev.kobj,
		    &sysfs_sfp_attr);
}
}


void
void
@@ -362,6 +412,9 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
	sysfs_remove_bin_file(&host->shost_gendev.kobj,
	sysfs_remove_bin_file(&host->shost_gendev.kobj,
	    &sysfs_optrom_ctl_attr);
	    &sysfs_optrom_ctl_attr);
	sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
	sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
	if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
		sysfs_remove_bin_file(&host->shost_gendev.kobj,
		    &sysfs_sfp_attr);


	if (ha->beacon_blink_led == 1)
	if (ha->beacon_blink_led == 1)
		ha->isp_ops.beacon_off(ha);
		ha->isp_ops.beacon_off(ha);
+6 −0
Original line number Original line Diff line number Diff line
@@ -610,6 +610,7 @@ typedef struct {
#define MBC_GET_TIMEOUT_PARAMS		0x22	/* Get FW timeouts. */
#define MBC_GET_TIMEOUT_PARAMS		0x22	/* Get FW timeouts. */
#define MBC_TRACE_CONTROL		0x27	/* Trace control command. */
#define MBC_TRACE_CONTROL		0x27	/* Trace control command. */
#define MBC_GEN_SYSTEM_ERROR		0x2a	/* Generate System Error. */
#define MBC_GEN_SYSTEM_ERROR		0x2a	/* Generate System Error. */
#define MBC_READ_SFP			0x31	/* Read SFP Data. */
#define MBC_SET_TIMEOUT_PARAMS		0x32	/* Set FW timeouts. */
#define MBC_SET_TIMEOUT_PARAMS		0x32	/* Set FW timeouts. */
#define MBC_MID_INITIALIZE_FIRMWARE	0x48	/* MID Initialize firmware. */
#define MBC_MID_INITIALIZE_FIRMWARE	0x48	/* MID Initialize firmware. */
#define MBC_MID_GET_VP_DATABASE		0x49	/* MID Get VP Database. */
#define MBC_MID_GET_VP_DATABASE		0x49	/* MID Get VP Database. */
@@ -2242,6 +2243,11 @@ typedef struct scsi_qla_host {
	struct sns_cmd_pkt	*sns_cmd;
	struct sns_cmd_pkt	*sns_cmd;
	dma_addr_t		sns_cmd_dma;
	dma_addr_t		sns_cmd_dma;


#define SFP_DEV_SIZE	256
#define SFP_BLOCK_SIZE	64
	void			*sfp_data;
	dma_addr_t		sfp_data_dma;

	struct task_struct	*dpc_thread;
	struct task_struct	*dpc_thread;
	uint8_t dpc_active;                  /* DPC routine is active */
	uint8_t dpc_active;                  /* DPC routine is active */


+3 −0
Original line number Original line Diff line number Diff line
@@ -210,6 +210,9 @@ qla2x00_stop_firmware(scsi_qla_host_t *);
extern int
extern int
qla2x00_trace_control(scsi_qla_host_t *, uint16_t, dma_addr_t, uint16_t);
qla2x00_trace_control(scsi_qla_host_t *, uint16_t, dma_addr_t, uint16_t);


extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);

/*
/*
 * Global Function Prototypes in qla_isr.c source file.
 * Global Function Prototypes in qla_isr.c source file.
 */
 */
+36 −0
Original line number Original line Diff line number Diff line
@@ -2503,4 +2503,40 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma,
	return rval;
	return rval;
}
}


int
qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
    uint16_t off, uint16_t count)
{
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;


	if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
		return QLA_FUNCTION_FAILED;

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

	mcp->mb[0] = MBC_READ_SFP;
	mcp->mb[1] = addr;
	mcp->mb[2] = MSW(sfp_dma);
	mcp->mb[3] = LSW(sfp_dma);
	mcp->mb[6] = MSW(MSD(sfp_dma));
	mcp->mb[7] = LSW(MSD(sfp_dma));
	mcp->mb[8] = count;
	mcp->mb[9] = off;
	mcp->mb[10] = 0;
	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
	mcp->in_mb = MBX_0;
	mcp->tov = 30;
	mcp->flags = 0;
	rval = qla2x00_mailbox_command(ha, mcp);

	if (rval != QLA_SUCCESS) {
		DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
		    ha->host_no, rval, mcp->mb[0]));
	} else {
		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
	}

	return rval;
}
+23 −0
Original line number Original line Diff line number Diff line
@@ -1979,6 +1979,26 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
				continue;
				continue;
			}
			}
			memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));
			memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));

			if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
				/*
				 * Get consistent memory allocated for SFP
				 * block.
				 */
				ha->sfp_data = dma_pool_alloc(ha->s_dma_pool,
				    GFP_KERNEL, &ha->sfp_data_dma);
				if (ha->sfp_data == NULL) {
					qla_printk(KERN_WARNING, ha,
					    "Memory Allocation failed - "
					    "sfp_data\n");

					qla2x00_mem_free(ha);
					msleep(100);

					continue;
				}
				memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
			}
		}
		}


		/* Done all allocations without any error. */
		/* Done all allocations without any error. */
@@ -2034,6 +2054,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
		dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
		    ha->ct_sns, ha->ct_sns_dma);
		    ha->ct_sns, ha->ct_sns_dma);


	if (ha->sfp_data)
		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);

	if (ha->ms_iocb)
	if (ha->ms_iocb)
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);