Commit 72a7f313 authored by Ching Huang's avatar Ching Huang Committed by Martin K. Petersen

scsi: arcmsr: simplify arcmsr_iop_init function

Simplify arcmsr_iop_init function.
Signed-off-by: default avatarChing Huang <ching2048@areca.com.tw>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 52b4dab3
...@@ -3671,6 +3671,39 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) ...@@ -3671,6 +3671,39 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb)
msleep(1000); msleep(1000);
return; return;
} }
static bool arcmsr_reset_in_progress(struct AdapterControlBlock *acb)
{
bool rtn = true;
switch(acb->adapter_type) {
case ACB_ADAPTER_TYPE_A:{
struct MessageUnit_A __iomem *reg = acb->pmuA;
rtn = ((readl(&reg->outbound_msgaddr1) &
ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) ? true : false;
}
break;
case ACB_ADAPTER_TYPE_B:{
struct MessageUnit_B *reg = acb->pmuB;
rtn = ((readl(reg->iop2drv_doorbell) &
ARCMSR_MESSAGE_FIRMWARE_OK) == 0) ? true : false;
}
break;
case ACB_ADAPTER_TYPE_C:{
struct MessageUnit_C __iomem *reg = acb->pmuC;
rtn = (readl(&reg->host_diagnostic) & 0x04) ? true : false;
}
break;
case ACB_ADAPTER_TYPE_D:{
struct MessageUnit_D *reg = acb->pmuD;
rtn = ((readl(reg->sample_at_reset) & 0x80) == 0) ?
true : false;
}
break;
}
return rtn;
}
static void arcmsr_iop_init(struct AdapterControlBlock *acb) static void arcmsr_iop_init(struct AdapterControlBlock *acb)
{ {
uint32_t intmask_org; uint32_t intmask_org;
...@@ -3725,197 +3758,55 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) ...@@ -3725,197 +3758,55 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
static int arcmsr_bus_reset(struct scsi_cmnd *cmd) static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
{ {
struct AdapterControlBlock *acb; struct AdapterControlBlock *acb;
uint32_t intmask_org, outbound_doorbell;
int retry_count = 0; int retry_count = 0;
int rtn = FAILED; int rtn = FAILED;
acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; acb = (struct AdapterControlBlock *) cmd->device->host->hostdata;
printk(KERN_ERR "arcmsr: executing bus reset eh.....num_resets = %d, num_aborts = %d \n", acb->num_resets, acb->num_aborts); pr_notice("arcmsr: executing bus reset eh.....num_resets = %d,"
" num_aborts = %d \n", acb->num_resets, acb->num_aborts);
acb->num_resets++; acb->num_resets++;
switch(acb->adapter_type){ if (acb->acb_flags & ACB_F_BUS_RESET) {
case ACB_ADAPTER_TYPE_A:{ long timeout;
if (acb->acb_flags & ACB_F_BUS_RESET){ pr_notice("arcmsr: there is an bus reset eh proceeding...\n");
long timeout; timeout = wait_event_timeout(wait_q, (acb->acb_flags
printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n"); & ACB_F_BUS_RESET) == 0, 220 * HZ);
timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ); if (timeout)
if (timeout) { return SUCCESS;
return SUCCESS; }
} acb->acb_flags |= ACB_F_BUS_RESET;
} if (!arcmsr_iop_reset(acb)) {
acb->acb_flags |= ACB_F_BUS_RESET; arcmsr_hardware_reset(acb);
if (!arcmsr_iop_reset(acb)) { acb->acb_flags &= ~ACB_F_IOP_INITED;
struct MessageUnit_A __iomem *reg; wait_reset_done:
reg = acb->pmuA; ssleep(ARCMSR_SLEEPTIME);
arcmsr_hardware_reset(acb); if (arcmsr_reset_in_progress(acb)) {
acb->acb_flags &= ~ACB_F_IOP_INITED; if (retry_count > ARCMSR_RETRYCOUNT) {
sleep_again: acb->fw_flag = FW_DEADLOCK;
ssleep(ARCMSR_SLEEPTIME); pr_notice("arcmsr%d: waiting for hw bus reset"
if ((readl(&reg->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { " return, RETRY TERMINATED!!\n",
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d\n", acb->host->host_no, retry_count); acb->host->host_no);
if (retry_count > ARCMSR_RETRYCOUNT) { return FAILED;
acb->fw_flag = FW_DEADLOCK;
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!!\n", acb->host->host_no);
return FAILED;
}
retry_count++;
goto sleep_again;
}
acb->acb_flags |= ACB_F_IOP_INITED;
/* disable all outbound interrupt */
intmask_org = arcmsr_disable_outbound_ints(acb);
arcmsr_get_firmware_spec(acb);
arcmsr_start_adapter_bgrb(acb);
/* clear Qbuffer if door bell ringed */
outbound_doorbell = readl(&reg->outbound_doorbell);
writel(outbound_doorbell, &reg->outbound_doorbell); /*clear interrupt */
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = SUCCESS;
printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n");
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
rtn = SUCCESS;
}
break;
}
case ACB_ADAPTER_TYPE_B:{
acb->acb_flags |= ACB_F_BUS_RESET;
if (!arcmsr_iop_reset(acb)) {
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = FAILED;
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
rtn = SUCCESS;
}
break;
}
case ACB_ADAPTER_TYPE_C:{
if (acb->acb_flags & ACB_F_BUS_RESET) {
long timeout;
printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n");
timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ);
if (timeout) {
return SUCCESS;
}
} }
acb->acb_flags |= ACB_F_BUS_RESET; retry_count++;
if (!arcmsr_iop_reset(acb)) { goto wait_reset_done;
struct MessageUnit_C __iomem *reg;
reg = acb->pmuC;
arcmsr_hardware_reset(acb);
acb->acb_flags &= ~ACB_F_IOP_INITED;
sleep:
ssleep(ARCMSR_SLEEPTIME);
if ((readl(&reg->host_diagnostic) & 0x04) != 0) {
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d\n", acb->host->host_no, retry_count);
if (retry_count > ARCMSR_RETRYCOUNT) {
acb->fw_flag = FW_DEADLOCK;
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!!\n", acb->host->host_no);
return FAILED;
}
retry_count++;
goto sleep;
}
acb->acb_flags |= ACB_F_IOP_INITED;
/* disable all outbound interrupt */
intmask_org = arcmsr_disable_outbound_ints(acb);
arcmsr_get_firmware_spec(acb);
arcmsr_start_adapter_bgrb(acb);
/* clear Qbuffer if door bell ringed */
arcmsr_clear_doorbell_queue_buffer(acb);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = SUCCESS;
printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n");
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
rtn = SUCCESS;
}
break;
}
case ACB_ADAPTER_TYPE_D: {
if (acb->acb_flags & ACB_F_BUS_RESET) {
long timeout;
pr_notice("arcmsr: there is an bus reset"
" eh proceeding.......\n");
timeout = wait_event_timeout(wait_q, (acb->acb_flags
& ACB_F_BUS_RESET) == 0, 220 * HZ);
if (timeout)
return SUCCESS;
}
acb->acb_flags |= ACB_F_BUS_RESET;
if (!arcmsr_iop_reset(acb)) {
struct MessageUnit_D *reg;
reg = acb->pmuD;
arcmsr_hardware_reset(acb);
acb->acb_flags &= ~ACB_F_IOP_INITED;
nap:
ssleep(ARCMSR_SLEEPTIME);
if ((readl(reg->sample_at_reset) & 0x80) != 0) {
pr_err("arcmsr%d: waiting for "
"hw bus reset return, retry=%d\n",
acb->host->host_no, retry_count);
if (retry_count > ARCMSR_RETRYCOUNT) {
acb->fw_flag = FW_DEADLOCK;
pr_err("arcmsr%d: waiting for hw bus"
" reset return, "
"RETRY TERMINATED!!\n",
acb->host->host_no);
return FAILED;
}
retry_count++;
goto nap;
}
acb->acb_flags |= ACB_F_IOP_INITED;
/* disable all outbound interrupt */
intmask_org = arcmsr_disable_outbound_ints(acb);
arcmsr_get_firmware_spec(acb);
arcmsr_start_adapter_bgrb(acb);
arcmsr_clear_doorbell_queue_buffer(acb);
arcmsr_enable_outbound_ints(acb, intmask_org);
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer,
jiffies + msecs_to_jiffies(6 * HZ));
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = SUCCESS;
pr_err("arcmsr: scsi bus reset "
"eh returns with success\n");
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer,
jiffies + msecs_to_jiffies(6 * HZ));
rtn = SUCCESS;
}
break;
} }
arcmsr_iop_init(acb);
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies +
msecs_to_jiffies(6 * HZ));
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = SUCCESS;
pr_notice("arcmsr: scsi bus reset eh returns with success\n");
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
atomic_set(&acb->rq_map_token, 16);
atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies +
msecs_to_jiffies(6 * HZ));
rtn = SUCCESS;
} }
return rtn; return rtn;
} }
......
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