Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142074
b: refs/heads/master
c: 1d2874d
h: refs/heads/master
v: v3
  • Loading branch information
Joe Carnuccio authored and James Bottomley committed Apr 3, 2009
1 parent 0ec1fae commit 319d4d1
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9978769877c6c90c8d6777df13b9ae427af40b7
refs/heads/master: 1d2874de809a14e6780246b99a18bbc0fc0a8f2a
3 changes: 2 additions & 1 deletion trunk/drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2260,7 +2260,7 @@ struct qla_hw_data {
uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
uint32_t fce_enabled :1;
uint32_t hw_event_marker_found:1;
uint32_t fac_supported :1;
} flags;

/* This spinlock is used to protect "io transactions", you must
Expand Down Expand Up @@ -2382,6 +2382,7 @@ struct qla_hw_data {
IS_QLA25XX(ha) || IS_QLA81XX(ha))
#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
(ha)->flags.msix_enabled)
#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha))

#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
Expand Down
14 changes: 14 additions & 0 deletions trunk/drivers/scsi/qla2xxx/qla_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,20 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_TIME_EXT 0x8102

#define MBC_IDC_ACK 0x101
#define MBC_FLASH_ACCESS_CTRL 0x3e /* Control flash access. */

/* Flash access control option field bit definitions */
#define FAC_OPT_FORCE_SEMAPHORE BIT_15
#define FAC_OPT_REQUESTOR_ID BIT_14
#define FAC_OPT_CMD_SUBCODE 0xff

/* Flash access control command subcodes */
#define FAC_OPT_CMD_WRITE_PROTECT 0x00
#define FAC_OPT_CMD_WRITE_ENABLE 0x01
#define FAC_OPT_CMD_ERASE_SECTOR 0x02
#define FAC_OPT_CMD_LOCK_SEMAPHORE 0x03
#define FAC_OPT_CMD_UNLOCK_SEMAPHORE 0x04
#define FAC_OPT_CMD_GET_SECTOR_SIZE 0x05

struct nvram_81xx {
/* NVRAM header. */
Expand Down
9 changes: 9 additions & 0 deletions trunk/drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,15 @@ extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);

extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);

extern int
qla81xx_fac_get_sector_size(scsi_qla_host_t *, uint32_t *);

extern int
qla81xx_fac_do_write_enable(scsi_qla_host_t *, int);

extern int
qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t);

/*
* Global Function Prototypes in qla_isr.c source file.
*/
Expand Down
15 changes: 15 additions & 0 deletions trunk/drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,21 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
uint32_t size;

rval = qla81xx_fac_get_sector_size(vha, &size);
if (rval == QLA_SUCCESS) {
ha->flags.fac_supported = 1;
ha->fdt_block_size = size << 2;
} else {
qla_printk(KERN_ERR, ha,
"Unsupported FAC firmware (%d.%02d.%02d).\n",
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version);
}
}

if (rval) {
DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
vha->host_no));
Expand Down
97 changes: 97 additions & 0 deletions trunk/drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -3228,3 +3228,100 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)

return rval;
}

int
qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;

if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;

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

mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);

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

return rval;
}

int
qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;

if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;

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

mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
FAC_OPT_CMD_WRITE_PROTECT;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);

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

return rval;
}

int
qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;

if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;

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

mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
mcp->mb[2] = LSW(start);
mcp->mb[3] = MSW(start);
mcp->mb[4] = LSW(finish);
mcp->mb[5] = MSW(finish);
mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_2|MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);

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

return rval;
}
60 changes: 47 additions & 13 deletions trunk/drivers/scsi/qla2xxx/qla_sup.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,31 +931,41 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
ha->npiv_info = NULL;
}

static void
qla24xx_unprotect_flash(struct qla_hw_data *ha)
static int
qla24xx_unprotect_flash(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

if (ha->flags.fac_supported)
return qla81xx_fac_do_write_enable(vha, 1);

/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */

if (!ha->fdt_wrt_disable)
return;
goto done;

/* Disable flash write-protection, first clear SR protection bit */
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
/* Then write zero again to clear remaining SR bits.*/
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
done:
return QLA_SUCCESS;
}

static void
qla24xx_protect_flash(struct qla_hw_data *ha)
static int
qla24xx_protect_flash(scsi_qla_host_t *vha)
{
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

if (ha->flags.fac_supported)
return qla81xx_fac_do_write_enable(vha, 0);

if (!ha->fdt_wrt_disable)
goto skip_wrt_protect;

Expand All @@ -973,6 +983,26 @@ qla24xx_protect_flash(struct qla_hw_data *ha)
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */

return QLA_SUCCESS;
}

static int
qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata)
{
struct qla_hw_data *ha = vha->hw;
uint32_t start, finish;

if (ha->flags.fac_supported) {
start = fdata >> 2;
finish = start + (ha->fdt_block_size >> 2) - 1;
return qla81xx_fac_erase_sector(vha, flash_data_addr(ha,
start), flash_data_addr(ha, finish));
}

return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
(fdata & 0xff00) | ((fdata << 16) & 0xff0000) |
((fdata >> 16) & 0xff));
}

static int
Expand All @@ -987,8 +1017,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
void *optrom = NULL;
struct qla_hw_data *ha = vha->hw;

ret = QLA_SUCCESS;

/* Prepare burst-capable write on supported ISPs. */
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) &&
dwords > OPTROM_BURST_DWORDS) {
Expand All @@ -1004,7 +1032,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
rest_addr = (ha->fdt_block_size >> 2) - 1;
sec_mask = ~rest_addr;

qla24xx_unprotect_flash(ha);
ret = qla24xx_unprotect_flash(vha);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to unprotect flash for update.\n");
goto done;
}

for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
fdata = (faddr & sec_mask) << 2;
Expand All @@ -1017,9 +1050,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ha->fdt_unprotect_sec_cmd,
(fdata & 0xff00) | ((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
(fdata & 0xff00) |((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_erase_sector(vha, fdata);
if (ret != QLA_SUCCESS) {
DEBUG9(qla_printk("Unable to erase sector: "
"address=%x.\n", faddr));
Expand Down Expand Up @@ -1073,8 +1104,11 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
0xff0000) | ((fdata >> 16) & 0xff));
}

qla24xx_protect_flash(ha);

ret = qla24xx_protect_flash(vha);
if (ret != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
"Unable to protect flash after update.\n");
done:
if (optrom)
dma_free_coherent(&ha->pdev->dev,
OPTROM_BURST_SIZE, optrom, optrom_dma);
Expand Down

0 comments on commit 319d4d1

Please sign in to comment.