diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_init.c')
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 79 | 
1 files changed, 54 insertions, 25 deletions
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e90c89f1d480..666bf5af06e2 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,  {  	int i;  	spin_lock_init(&pm8001_ha->lock); +	spin_lock_init(&pm8001_ha->bitmap_lock);  	PM8001_INIT_DBG(pm8001_ha,  		pm8001_printk("pm8001_alloc: PHY:%x\n",  				pm8001_ha->chip->n_phy)); @@ -621,6 +622,8 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)  	DECLARE_COMPLETION_ONSTACK(completion);  	struct pm8001_ioctl_payload payload;  	u16 deviceid; +	int rc; +  	pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);  	pm8001_ha->nvmd_completion = &completion; @@ -638,7 +641,16 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)  	}  	payload.offset = 0;  	payload.func_specific = kzalloc(payload.length, GFP_KERNEL); -	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); +	if (!payload.func_specific) { +		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n")); +		return; +	} +	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); +	if (rc) { +		kfree(payload.func_specific); +		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); +		return; +	}  	wait_for_completion(&completion);  	for (i = 0, j = 0; i <= 7; i++, j++) { @@ -661,6 +673,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)  			pm8001_printk("phy %d sas_addr = %016llx\n", i,  			pm8001_ha->phy[i].dev_sas_addr));  	} +	kfree(payload.func_specific);  #else  	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {  		pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL; @@ -684,6 +697,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)  	/*OPTION ROM FLASH read for the SPC cards */  	DECLARE_COMPLETION_ONSTACK(completion);  	struct pm8001_ioctl_payload payload; +	int rc;  	pm8001_ha->nvmd_completion = &completion;  	/* SAS ADDRESS read from flash / EEPROM */ @@ -694,7 +708,12 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)  	if (!payload.func_specific)  		return -ENOMEM;  	/* Read phy setting values from flash */ -	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); +	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); +	if (rc) { +		kfree(payload.func_specific); +		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); +		return -ENOMEM; +	}  	wait_for_completion(&completion);  	pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);  	kfree(payload.func_specific); @@ -729,33 +748,35 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)  		sizeof(pm8001_ha->msix_entries[0]);  	for (i = 0; i < max_entry ; i++)  		pm8001_ha->msix_entries[i].entry = i; -	rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, +	rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries,  		number_of_intr);  	pm8001_ha->number_of_intr = number_of_intr; -	if (!rc) { -		PM8001_INIT_DBG(pm8001_ha, pm8001_printk( -			"pci_enable_msix request ret:%d no of intr %d\n", -					rc, pm8001_ha->number_of_intr)); - - -		for (i = 0; i < number_of_intr; i++) { -			snprintf(intr_drvname[i], sizeof(intr_drvname[0]), -					DRV_NAME"%d", i); -			pm8001_ha->irq_vector[i].irq_id = i; -			pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; - -			if (request_irq(pm8001_ha->msix_entries[i].vector, -				pm8001_interrupt_handler_msix, flag, -				intr_drvname[i], &(pm8001_ha->irq_vector[i]))) { -				for (j = 0; j < i; j++) -					free_irq( -					pm8001_ha->msix_entries[j].vector, +	if (rc) +		return rc; + +	PM8001_INIT_DBG(pm8001_ha, pm8001_printk( +		"pci_enable_msix_exact request ret:%d no of intr %d\n", +				rc, pm8001_ha->number_of_intr)); + +	for (i = 0; i < number_of_intr; i++) { +		snprintf(intr_drvname[i], sizeof(intr_drvname[0]), +				DRV_NAME"%d", i); +		pm8001_ha->irq_vector[i].irq_id = i; +		pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; + +		rc = request_irq(pm8001_ha->msix_entries[i].vector, +			pm8001_interrupt_handler_msix, flag, +			intr_drvname[i], &(pm8001_ha->irq_vector[i])); +		if (rc) { +			for (j = 0; j < i; j++) { +				free_irq(pm8001_ha->msix_entries[j].vector,  					&(pm8001_ha->irq_vector[i])); -				pci_disable_msix(pm8001_ha->pdev); -				break;  			} +			pci_disable_msix(pm8001_ha->pdev); +			break;  		}  	} +  	return rc;  }  #endif @@ -964,6 +985,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)  	int  i, j;  	u32 device_state;  	pm8001_ha = sha->lldd_ha; +	sas_suspend_ha(sha);  	flush_workqueue(pm8001_wq);  	scsi_block_requests(pm8001_ha->shost);  	if (!pdev->pm_cap) { @@ -1013,6 +1035,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)  	int rc;  	u8 i = 0, j;  	u32 device_state; +	DECLARE_COMPLETION_ONSTACK(completion);  	pm8001_ha = sha->lldd_ha;  	device_state = pdev->current_state; @@ -1033,7 +1056,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)  	rc = pci_go_44(pdev);  	if (rc)  		goto err_out_disable; - +	sas_prep_resume_ha(sha);  	/* chip soft rst only for spc */  	if (pm8001_ha->chip_id == chip_8001) {  		PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); @@ -1065,7 +1088,13 @@ static int pm8001_pci_resume(struct pci_dev *pdev)  		for (i = 1; i < pm8001_ha->number_of_intr; i++)  			PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);  	} -	scsi_unblock_requests(pm8001_ha->shost); +	pm8001_ha->flags = PM8001F_RUN_TIME; +	for (i = 0; i < pm8001_ha->chip->n_phy; i++) { +		pm8001_ha->phy[i].enable_completion = &completion; +		PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); +		wait_for_completion(&completion); +	} +	sas_resume_ha(sha);  	return 0;  err_out_disable:  |