Skip to content

Commit

Permalink
[SCSI] qla2xxx: Add support for ISP2071.
Browse files Browse the repository at this point in the history
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Armen Baloyan <armen.baloyan@qlogic.com>
Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Chad Dupuis authored and James Bottomley committed Mar 15, 2014
1 parent 624f28b commit f73cb69
Show file tree
Hide file tree
Showing 20 changed files with 1,812 additions and 136 deletions.
2 changes: 1 addition & 1 deletion drivers/scsi/qla2xxx/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
qla_nx.o qla_mr.o qla_nx2.o qla_target.o
qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o

obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o
97 changes: 96 additions & 1 deletion drivers/scsi/qla2xxx/qla_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,92 @@ static struct bin_attribute sysfs_fw_dump_attr = {
.write = qla2x00_sysfs_write_fw_dump,
};

static ssize_t
qla2x00_sysfs_read_fw_dump_template(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;

if (!ha->fw_dump_template || !ha->fw_dump_template_len)
return 0;

ql_dbg(ql_dbg_user, vha, 0x70e2,
"chunk <- off=%llx count=%lx\n", off, count);
return memory_read_from_buffer(buf, count, &off,
ha->fw_dump_template, ha->fw_dump_template_len);
}

static ssize_t
qla2x00_sysfs_write_fw_dump_template(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint32_t size;

if (off == 0) {
if (ha->fw_dump)
vfree(ha->fw_dump);
if (ha->fw_dump_template)
vfree(ha->fw_dump_template);

ha->fw_dump = NULL;
ha->fw_dump_len = 0;
ha->fw_dump_template = NULL;
ha->fw_dump_template_len = 0;

size = qla27xx_fwdt_template_size(buf);
ql_dbg(ql_dbg_user, vha, 0x70d1,
"-> allocating fwdt (%x bytes)...\n", size);
ha->fw_dump_template = vmalloc(size);
if (!ha->fw_dump_template) {
ql_log(ql_log_warn, vha, 0x70d2,
"Failed allocate fwdt (%x bytes).\n", size);
return -ENOMEM;
}
ha->fw_dump_template_len = size;
}

if (off + count > ha->fw_dump_template_len) {
count = ha->fw_dump_template_len - off;
ql_dbg(ql_dbg_user, vha, 0x70d3,
"chunk -> truncating to %lx bytes.\n", count);
}

ql_dbg(ql_dbg_user, vha, 0x70d4,
"chunk -> off=%llx count=%lx\n", off, count);
memcpy(ha->fw_dump_template + off, buf, count);

if (off + count == ha->fw_dump_template_len) {
size = qla27xx_fwdt_calculate_dump_size(vha);
ql_dbg(ql_dbg_user, vha, 0x70d5,
"-> allocating fwdump (%x bytes)...\n", size);
ha->fw_dump = vmalloc(size);
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0x70d6,
"Failed allocate fwdump (%x bytes).\n", size);
return -ENOMEM;
}
ha->fw_dump_len = size;
}

return count;
}
static struct bin_attribute sysfs_fw_dump_template_attr = {
.attr = {
.name = "fw_dump_template",
.mode = S_IRUSR | S_IWUSR,
},
.size = 0,
.read = qla2x00_sysfs_read_fw_dump_template,
.write = qla2x00_sysfs_write_fw_dump_template,
};

static ssize_t
qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
Expand Down Expand Up @@ -845,6 +931,7 @@ static struct sysfs_entry {
int is4GBp_only;
} bin_file_entries[] = {
{ "fw_dump", &sysfs_fw_dump_attr, },
{ "fw_dump_template", &sysfs_fw_dump_template_attr, 0x27 },
{ "nvram", &sysfs_nvram_attr, },
{ "optrom", &sysfs_optrom_attr, },
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
Expand All @@ -870,6 +957,8 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
continue;
if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw)))
continue;
if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw))
continue;

ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
iter->attr);
Expand Down Expand Up @@ -1210,7 +1299,7 @@ qla2x00_optrom_gold_fw_version_show(struct device *dev,
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;

if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha))
if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");

return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n",
Expand Down Expand Up @@ -1532,6 +1621,9 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
case PORT_SPEED_16GB:
speed = FC_PORTSPEED_16GBIT;
break;
case PORT_SPEED_32GB:
speed = FC_PORTSPEED_32GBIT;
break;
}
fc_host_speed(shost) = speed;
}
Expand Down Expand Up @@ -2183,6 +2275,9 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
else if (IS_QLAFX00(ha))
speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
else if (IS_QLA27XX(ha))
speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT |
FC_PORTSPEED_8GBIT;
else
speed = FC_PORTSPEED_1GBIT;
fc_host_supported_speeds(vha->host) = speed;
Expand Down
133 changes: 110 additions & 23 deletions drivers/scsi/qla2xxx/qla_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
* ----------------------------------------------------------------------
* | Level | Last Value Used | Holes |
* ----------------------------------------------------------------------
* | Module Init and Probe | 0x015b | 0x4b,0xba,0xfa |
* | | | 0x0x015a |
* | Mailbox commands | 0x1187 | 0x111a-0x111b |
* | | | 0x1155-0x1158 |
* | | | 0x1018-0x1019 |
* | Module Init and Probe | 0x017d | 0x004b,0x0141 |
* | | | 0x0144,0x0146 |
* | | | 0x015b-0x0160 |
* | | | 0x016e-0x0170 |
* | Mailbox commands | 0x1187 | 0x1018-0x1019 |
* | | | 0x10ca |
* | | | 0x1115-0x1116 |
* | | | 0x10ca |
* | | | 0x111a-0x111b |
* | | | 0x1155-0x1158 |
* | Device Discovery | 0x2095 | 0x2020-0x2022, |
* | | | 0x2011-0x2012, |
* | | | 0x2016 |
Expand All @@ -33,17 +35,15 @@
* | | | 0x5084,0x5075 |
* | | | 0x503d,0x5044 |
* | Timer Routines | 0x6012 | |
* | User Space Interactions | 0x70e1 | 0x7018,0x702e, |
* | | | 0x7020,0x7024, |
* | | | 0x7039,0x7045, |
* | | | 0x7073-0x7075, |
* | | | 0x707b,0x708c, |
* | | | 0x70a5,0x70a6, |
* | | | 0x70a8,0x70ab, |
* | | | 0x70ad-0x70ae, |
* | | | 0x70d1-0x70db, |
* | | | 0x7047,0x703b |
* | | | 0x70de-0x70df, |
* | User Space Interactions | 0x70e2 | 0x7018,0x702e |
* | | | 0x7020,0x7024 |
* | | | 0x7039,0x7045 |
* | | | 0x7073-0x7075 |
* | | | 0x70a5-0x70a6 |
* | | | 0x70a8,0x70ab |
* | | | 0x70ad-0x70ae |
* | | | 0x70d7-0x70db |
* | | | 0x70de-0x70df |
* | Task Management | 0x803d | 0x8025-0x8026 |
* | | | 0x800b,0x8039 |
* | AER/EEH | 0x9011 | |
Expand All @@ -59,7 +59,11 @@
* | | | 0xb13c-0xb140 |
* | | | 0xb149 |
* | MultiQ | 0xc00c | |
* | Misc | 0xd010 | |
* | Misc | 0xd2ff | 0xd017-0xd019 |
* | | | 0xd020 |
* | | | 0xd02e-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd212-0xd2fe |
* | Target Mode | 0xe070 | 0xe021 |
* | Target Mode Management | 0xf072 | 0xf002-0xf003 |
* | | | 0xf046-0xf049 |
Expand Down Expand Up @@ -104,7 +108,87 @@ qla2xxx_copy_queues(struct qla_hw_data *ha, void *ptr)
return ptr + (rsp->length * sizeof(response_t));
}

static int
int
qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
uint32_t ram_dwords, void **nxt)
{
int rval;
uint32_t cnt, stat, timer, dwords, idx;
uint16_t mb0, mb1;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
uint32_t *dump = (uint32_t *)ha->gid_list;

rval = QLA_SUCCESS;
mb0 = 0;

WRT_REG_WORD(&reg->mailbox0, MBC_LOAD_DUMP_MPI_RAM);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);

dwords = qla2x00_gid_list_size(ha) / 4;
for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
cnt += dwords, addr += dwords) {
if (cnt + dwords > ram_dwords)
dwords = ram_dwords - cnt;

WRT_REG_WORD(&reg->mailbox1, LSW(addr));
WRT_REG_WORD(&reg->mailbox8, MSW(addr));

WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));

WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
WRT_REG_WORD(&reg->mailbox5, LSW(dwords));

WRT_REG_WORD(&reg->mailbox9, 0);
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);

ha->flags.mbox_int = 0;
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_INT) {
stat &= 0xff;

if (stat == 0x1 || stat == 0x2 ||
stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);

mb0 = RD_REG_WORD(&reg->mailbox0);
mb1 = RD_REG_WORD(&reg->mailbox1);

WRT_REG_DWORD(&reg->hccr,
HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
break;
}

/* Clear this intr; it wasn't a mailbox intr */
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
}
udelay(5);
}
ha->flags.mbox_int = 1;

if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
for (idx = 0; idx < dwords; idx++)
ram[cnt + idx] = IS_QLA27XX(ha) ?
le32_to_cpu(dump[idx]) : swab32(dump[idx]);
} else {
rval = QLA_FUNCTION_FAILED;
}
}

*nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL;
return rval;
}

int
qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
uint32_t ram_dwords, void **nxt)
{
Expand Down Expand Up @@ -139,6 +223,7 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);

ha->flags.mbox_int = 0;
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->host_status);
Expand All @@ -164,11 +249,13 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
}
udelay(5);
}
ha->flags.mbox_int = 1;

if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
for (idx = 0; idx < dwords; idx++)
ram[cnt + idx] = swab32(dump[idx]);
ram[cnt + idx] = IS_QLA27XX(ha) ?
le32_to_cpu(dump[idx]) : swab32(dump[idx]);
} else {
rval = QLA_FUNCTION_FAILED;
}
Expand Down Expand Up @@ -208,7 +295,7 @@ qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
return buf;
}

static inline int
int
qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
{
int rval = QLA_SUCCESS;
Expand All @@ -227,7 +314,7 @@ qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
return rval;
}

static int
int
qla24xx_soft_reset(struct qla_hw_data *ha)
{
int rval = QLA_SUCCESS;
Expand Down Expand Up @@ -537,7 +624,7 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
struct qla2xxx_mq_chain *mq = ptr;
device_reg_t __iomem *reg;

if (!ha->mqenable || IS_QLA83XX(ha))
if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
return ptr;

mq = ptr;
Expand Down
7 changes: 7 additions & 0 deletions drivers/scsi/qla2xxx/qla_dbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,10 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
#define ql_dbg_tgt 0x00004000 /* Target mode */
#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */

extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
extern int qla24xx_dump_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
extern int qla24xx_pause_risc(struct device_reg_24xx __iomem *);
extern int qla24xx_soft_reset(struct qla_hw_data *);
Loading

0 comments on commit f73cb69

Please sign in to comment.