diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 100 | 
1 files changed, 78 insertions, 22 deletions
| diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 49bf2f70a470..ecd06d2d7e81 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -223,7 +223,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  		PM8001_EVENT_LOG_SIZE;  	pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option		= 0x01;  	pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt		= 0x01; -	for (i = 0; i < PM8001_MAX_INB_NUM; i++) { +	for (i = 0; i < pm8001_ha->max_q_num; i++) {  		pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt	=  			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);  		pm8001_ha->inbnd_q_tbl[i].upper_base_addr	= @@ -240,6 +240,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  			pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;  		pm8001_ha->inbnd_q_tbl[i].ci_virt		=  			pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr; +		pm8001_write_32(pm8001_ha->inbnd_q_tbl[i].ci_virt, 0, 0);  		offsetib = i * 0x20;  		pm8001_ha->inbnd_q_tbl[i].pi_pci_bar		=  			get_pci_bar_index(pm8001_mr32(addressib, @@ -249,7 +250,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  		pm8001_ha->inbnd_q_tbl[i].producer_idx		= 0;  		pm8001_ha->inbnd_q_tbl[i].consumer_index	= 0;  	} -	for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { +	for (i = 0; i < pm8001_ha->max_q_num; i++) {  		pm8001_ha->outbnd_q_tbl[i].element_size_cnt	=  			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);  		pm8001_ha->outbnd_q_tbl[i].upper_base_addr	= @@ -268,6 +269,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  			0 | (10 << 16) | (i << 24);  		pm8001_ha->outbnd_q_tbl[i].pi_virt		=  			pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr; +		pm8001_write_32(pm8001_ha->outbnd_q_tbl[i].pi_virt, 0, 0);  		offsetob = i * 0x24;  		pm8001_ha->outbnd_q_tbl[i].ci_pci_bar		=  			get_pci_bar_index(pm8001_mr32(addressob, @@ -643,7 +645,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)   */  static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)  { -	u8 i = 0; +	u32 i = 0;  	u16 deviceid;  	pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);  	/* 8081 controllers need BAR shift to access MPI space @@ -671,9 +673,9 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)  	read_outbnd_queue_table(pm8001_ha);  	/* update main config table ,inbound table and outbound table */  	update_main_config_table(pm8001_ha); -	for (i = 0; i < PM8001_MAX_INB_NUM; i++) +	for (i = 0; i < pm8001_ha->max_q_num; i++)  		update_inbnd_queue_table(pm8001_ha, i); -	for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) +	for (i = 0; i < pm8001_ha->max_q_num; i++)  		update_outbnd_queue_table(pm8001_ha, i);  	/* 8081 controller donot require these operations */  	if (deviceid != 0x8081 && deviceid != 0x0042) { @@ -1175,7 +1177,7 @@ void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)  #ifndef PM8001_USE_MSIX  /** - * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt + * pm8001_chip_intx_interrupt_enable - enable PM8001 chip interrupt   * @pm8001_ha: our hba card information   */  static void @@ -1248,7 +1250,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)  }  /** - * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt + * pm8001_chip_interrupt_disable - disable PM8001 chip interrupt   * @pm8001_ha: our hba card information   * @vec: unused   */ @@ -1499,12 +1501,14 @@ void pm8001_work_fn(struct work_struct *work)  	 * was cancelled. This nullification happens when the device  	 * goes away.  	 */ -	pm8001_dev = pw->data; /* Most stash device structure */ -	if ((pm8001_dev == NULL) -	 || ((pw->handler != IO_XFER_ERROR_BREAK) -	  && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) { -		kfree(pw); -		return; +	if (pw->handler != IO_FATAL_ERROR) { +		pm8001_dev = pw->data; /* Most stash device structure */ +		if ((pm8001_dev == NULL) +		 || ((pw->handler != IO_XFER_ERROR_BREAK) +			 && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) { +			kfree(pw); +			return; +		}  	}  	switch (pw->handler) { @@ -1668,6 +1672,58 @@ void pm8001_work_fn(struct work_struct *work)  		dev = pm8001_dev->sas_device;  		pm8001_I_T_nexus_reset(dev);  		break; +	case IO_FATAL_ERROR: +	{ +		struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha; +		struct pm8001_ccb_info *ccb; +		struct task_status_struct *ts; +		struct sas_task *task; +		int i; +		u32 tag, device_id; + +		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) { +			ccb = &pm8001_ha->ccb_info[i]; +			task = ccb->task; +			ts = &task->task_status; +			tag = ccb->ccb_tag; +			/* check if tag is NULL */ +			if (!tag) { +				pm8001_dbg(pm8001_ha, FAIL, +					"tag Null\n"); +				continue; +			} +			if (task != NULL) { +				dev = task->dev; +				if (!dev) { +					pm8001_dbg(pm8001_ha, FAIL, +						"dev is NULL\n"); +					continue; +				} +				/*complete sas task and update to top layer */ +				pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); +				ts->resp = SAS_TASK_COMPLETE; +				task->task_done(task); +			} else if (tag != 0xFFFFFFFF) { +				/* complete the internal commands/non-sas task */ +				pm8001_dev = ccb->device; +				if (pm8001_dev->dcompletion) { +					complete(pm8001_dev->dcompletion); +					pm8001_dev->dcompletion = NULL; +				} +				complete(pm8001_ha->nvmd_completion); +				pm8001_tag_free(pm8001_ha, tag); +			} +		} +		/* Deregister all the device ids  */ +		for (i = 0; i < PM8001_MAX_DEVICES; i++) { +			pm8001_dev = &pm8001_ha->devices[i]; +			device_id = pm8001_dev->device_id; +			if (device_id) { +				PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id); +				pm8001_free_dev(pm8001_dev); +			} +		} +	}	break;  	}  	kfree(pw);  } @@ -1826,7 +1882,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,   * that the task has been finished.   */  static void -mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) +mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)  {  	struct sas_task *t;  	struct pm8001_ccb_info *ccb; @@ -2058,7 +2114,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)  }  /*See the comments for mpi_ssp_completion */ -static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) +static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)  {  	struct sas_task *t;  	unsigned long flags; @@ -2294,9 +2350,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)  		(status != IO_UNDERFLOW)) {  		if (!((t->dev->parent) &&  			(dev_is_expander(t->dev->parent->dev_type)))) { -			for (i = 0 , j = 4; j <= 7 && i <= 3; i++ , j++) +			for (i = 0, j = 4; j <= 7 && i <= 3; i++, j++)  				sata_addr_low[i] = pm8001_ha->sas_addr[j]; -			for (i = 0 , j = 0; j <= 3 && i <= 3; i++ , j++) +			for (i = 0, j = 0; j <= 3 && i <= 3; i++, j++)  				sata_addr_hi[i] = pm8001_ha->sas_addr[j];  			memcpy(&temp_sata_addr_low, sata_addr_low,  				sizeof(sata_addr_low)); @@ -2625,7 +2681,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)  }  /*See the comments for mpi_ssp_completion */ -static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) +static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)  {  	struct sas_task *t;  	struct task_status_struct *ts; @@ -3219,7 +3275,7 @@ void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)  }  /** - * asd_get_attached_sas_addr -- extract/generate attached SAS address + * pm8001_get_attached_sas_addr - extract/generate attached SAS address   * @phy: pointer to asd_phy   * @sas_addr: pointer to buffer where the SAS address is to be written   * @@ -3546,7 +3602,7 @@ int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)  }  /** - * fw_flash_update_resp - Response from FW for flash update command. + * pm8001_mpi_fw_flash_update_resp - Response from FW for flash update command.   * @pm8001_ha: our hba card information   * @piomb: IO message buffer   */ @@ -3602,7 +3658,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,  	return 0;  } -int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb) +int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha, void *piomb)  {  	u32 status;  	int i; @@ -3685,7 +3741,7 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)   * @pm8001_ha: our hba card information   * @piomb: IO message buffer   */ -static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) +static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)  {  	unsigned long flags;  	struct hw_event_resp *pPayload = | 
