forked from Minki/linux
[SCSI] qla4xxx: Added support for adapter and firmware reset
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
2944369144
commit
95d31262b3
@ -172,6 +172,7 @@
|
|||||||
#define RELOGIN_TOV 18
|
#define RELOGIN_TOV 18
|
||||||
#define ISNS_DEREG_TOV 5
|
#define ISNS_DEREG_TOV 5
|
||||||
#define HBA_ONLINE_TOV 30
|
#define HBA_ONLINE_TOV 30
|
||||||
|
#define DISABLE_ACB_TOV 30
|
||||||
|
|
||||||
#define MAX_RESET_HA_RETRIES 2
|
#define MAX_RESET_HA_RETRIES 2
|
||||||
|
|
||||||
@ -616,6 +617,7 @@ struct scsi_qla_host {
|
|||||||
uint16_t phy_port_cnt;
|
uint16_t phy_port_cnt;
|
||||||
uint16_t iscsi_pci_func_cnt;
|
uint16_t iscsi_pci_func_cnt;
|
||||||
uint8_t model_name[16];
|
uint8_t model_name[16];
|
||||||
|
struct completion disable_acb_comp;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ql4_task_data {
|
struct ql4_task_data {
|
||||||
|
@ -605,6 +605,9 @@ struct init_fw_ctrl_blk {
|
|||||||
/* struct addr_ctrl_blk sec;*/
|
/* struct addr_ctrl_blk sec;*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PRIMARI_ACB 0
|
||||||
|
#define SECONDARY_ACB 1
|
||||||
|
|
||||||
struct addr_ctrl_blk_def {
|
struct addr_ctrl_blk_def {
|
||||||
uint8_t reserved1[1]; /* 00 */
|
uint8_t reserved1[1]; /* 00 */
|
||||||
uint8_t control; /* 01 */
|
uint8_t control; /* 01 */
|
||||||
|
@ -619,6 +619,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||||||
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
|
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
|
||||||
(mbox_sts[2] == ACB_STATE_VALID))
|
(mbox_sts[2] == ACB_STATE_VALID))
|
||||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||||
|
else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED))
|
||||||
|
complete(&ha->disable_acb_comp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBOX_ASTS_MAC_ADDRESS_CHANGED:
|
case MBOX_ASTS_MAC_ADDRESS_CHANGED:
|
||||||
|
@ -121,6 +121,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *device);
|
|||||||
static int qla4xxx_slave_configure(struct scsi_device *device);
|
static int qla4xxx_slave_configure(struct scsi_device *device);
|
||||||
static void qla4xxx_slave_destroy(struct scsi_device *sdev);
|
static void qla4xxx_slave_destroy(struct scsi_device *sdev);
|
||||||
static mode_t ql4_attr_is_visible(int param_type, int param);
|
static mode_t ql4_attr_is_visible(int param_type, int param);
|
||||||
|
static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
|
||||||
|
|
||||||
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
|
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
|
||||||
QLA82XX_LEGACY_INTR_CONFIG;
|
QLA82XX_LEGACY_INTR_CONFIG;
|
||||||
@ -148,6 +149,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
|
|||||||
|
|
||||||
.max_sectors = 0xFFFF,
|
.max_sectors = 0xFFFF,
|
||||||
.shost_attrs = qla4xxx_host_attrs,
|
.shost_attrs = qla4xxx_host_attrs,
|
||||||
|
.host_reset = qla4xxx_host_reset,
|
||||||
.vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
|
.vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3133,6 +3135,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||||||
|
|
||||||
mutex_init(&ha->mbox_sem);
|
mutex_init(&ha->mbox_sem);
|
||||||
init_completion(&ha->mbx_intr_comp);
|
init_completion(&ha->mbx_intr_comp);
|
||||||
|
init_completion(&ha->disable_acb_comp);
|
||||||
|
|
||||||
spin_lock_init(&ha->hardware_lock);
|
spin_lock_init(&ha->hardware_lock);
|
||||||
|
|
||||||
@ -3761,6 +3764,110 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|||||||
return return_status;
|
return return_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qla4xxx_context_reset(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
uint32_t mbox_cmd[MBOX_REG_COUNT];
|
||||||
|
uint32_t mbox_sts[MBOX_REG_COUNT];
|
||||||
|
struct addr_ctrl_blk_def *acb = NULL;
|
||||||
|
uint32_t acb_len = sizeof(struct addr_ctrl_blk_def);
|
||||||
|
int rval = QLA_SUCCESS;
|
||||||
|
dma_addr_t acb_dma;
|
||||||
|
|
||||||
|
acb = dma_alloc_coherent(&ha->pdev->dev,
|
||||||
|
sizeof(struct addr_ctrl_blk_def),
|
||||||
|
&acb_dma, GFP_KERNEL);
|
||||||
|
if (!acb) {
|
||||||
|
ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
|
||||||
|
__func__);
|
||||||
|
rval = -ENOMEM;
|
||||||
|
goto exit_port_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(acb, 0, acb_len);
|
||||||
|
|
||||||
|
rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len);
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
rval = -EIO;
|
||||||
|
goto exit_free_acb;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = qla4xxx_disable_acb(ha);
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
rval = -EIO;
|
||||||
|
goto exit_free_acb;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_completion_timeout(&ha->disable_acb_comp,
|
||||||
|
DISABLE_ACB_TOV * HZ);
|
||||||
|
|
||||||
|
rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
rval = -EIO;
|
||||||
|
goto exit_free_acb;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_free_acb:
|
||||||
|
dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def),
|
||||||
|
acb, acb_dma);
|
||||||
|
exit_port_reset:
|
||||||
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__,
|
||||||
|
rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
|
||||||
|
{
|
||||||
|
struct scsi_qla_host *ha = to_qla_host(shost);
|
||||||
|
int rval = QLA_SUCCESS;
|
||||||
|
|
||||||
|
if (ql4xdontresethba) {
|
||||||
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",
|
||||||
|
__func__));
|
||||||
|
rval = -EPERM;
|
||||||
|
goto exit_host_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = qla4xxx_wait_for_hba_online(ha);
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unable to reset host "
|
||||||
|
"adapter\n", __func__));
|
||||||
|
rval = -EIO;
|
||||||
|
goto exit_host_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
|
||||||
|
goto recover_adapter;
|
||||||
|
|
||||||
|
switch (reset_type) {
|
||||||
|
case SCSI_ADAPTER_RESET:
|
||||||
|
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||||
|
break;
|
||||||
|
case SCSI_FIRMWARE_RESET:
|
||||||
|
if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||||
|
if (is_qla8022(ha))
|
||||||
|
/* set firmware context reset */
|
||||||
|
set_bit(DPC_RESET_HA_FW_CONTEXT,
|
||||||
|
&ha->dpc_flags);
|
||||||
|
else {
|
||||||
|
rval = qla4xxx_context_reset(ha);
|
||||||
|
goto exit_host_reset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
recover_adapter:
|
||||||
|
rval = qla4xxx_recover_adapter(ha);
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",
|
||||||
|
__func__));
|
||||||
|
rval = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_host_reset:
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/* PCI AER driver recovers from all correctable errors w/o
|
/* PCI AER driver recovers from all correctable errors w/o
|
||||||
* driver intervention. For uncorrectable errors PCI AER
|
* driver intervention. For uncorrectable errors PCI AER
|
||||||
* driver calls the following device driver's callbacks
|
* driver calls the following device driver's callbacks
|
||||||
|
Loading…
Reference in New Issue
Block a user