Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+75 −184
Original line number Diff line number Diff line
@@ -3671,6 +3671,39 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb)
	msleep(1000);
	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)
{
	uint32_t intmask_org;
@@ -3725,142 +3758,16 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
{
	struct AdapterControlBlock *acb;
	uint32_t intmask_org, outbound_doorbell;
	int retry_count = 0;
	int rtn = FAILED;
	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++;

	switch(acb->adapter_type){
		case ACB_ADAPTER_TYPE_A:{
	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;
			if (!arcmsr_iop_reset(acb)) {
				struct MessageUnit_A __iomem *reg;
				reg = acb->pmuA;
				arcmsr_hardware_reset(acb);
				acb->acb_flags &= ~ACB_F_IOP_INITED;
sleep_again:
				ssleep(ARCMSR_SLEEPTIME);
				if ((readl(&reg->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 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_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;
			if (!arcmsr_iop_reset(acb)) {
				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");
		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)
@@ -3868,55 +3775,39 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
	}
	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:
wait_reset_done:
		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 (arcmsr_reset_in_progress(acb)) {
			if (retry_count > ARCMSR_RETRYCOUNT) {
				acb->fw_flag = FW_DEADLOCK;
						pr_err("arcmsr%d: waiting for hw bus"
							" reset return, "
							"RETRY TERMINATED!!\n",
				pr_notice("arcmsr%d: waiting for hw bus reset"
					" return, RETRY TERMINATED!!\n",
					acb->host->host_no);
				return FAILED;
			}
			retry_count++;
					goto nap;
			goto wait_reset_done;
		}
				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);
		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));
		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");
		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));
		mod_timer(&acb->eternal_timer, jiffies +
			msecs_to_jiffies(6 * HZ));
		rtn = SUCCESS;
	}
			break;
		}
	}
	return rtn;
}