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

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

Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8baa51a6
...@@ -338,6 +338,53 @@ static struct bin_attribute sysfs_vpd_attr = { ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -610,6 +610,7 @@ typedef struct { ...@@ -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 { ...@@ -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 */
......
...@@ -210,6 +210,9 @@ qla2x00_stop_firmware(scsi_qla_host_t *); ...@@ -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.
*/ */
......
...@@ -2503,4 +2503,40 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, ...@@ -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;
}
...@@ -1979,6 +1979,26 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment