aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_init.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c91
1 files changed, 53 insertions, 38 deletions
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 34f5f5ffef05..73a120d81b4d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -175,20 +175,16 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
175static void pm8001_tasklet(unsigned long opaque) 175static void pm8001_tasklet(unsigned long opaque)
176{ 176{
177 struct pm8001_hba_info *pm8001_ha; 177 struct pm8001_hba_info *pm8001_ha;
178 u32 vec; 178 struct isr_param *irq_vector;
179 pm8001_ha = (struct pm8001_hba_info *)opaque; 179
180 irq_vector = (struct isr_param *)opaque;
181 pm8001_ha = irq_vector->drv_inst;
180 if (unlikely(!pm8001_ha)) 182 if (unlikely(!pm8001_ha))
181 BUG_ON(1); 183 BUG_ON(1);
182 vec = pm8001_ha->int_vector; 184 PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
183 PM8001_CHIP_DISP->isr(pm8001_ha, vec);
184} 185}
185#endif 186#endif
186 187
187static struct pm8001_hba_info *outq_to_hba(u8 *outq)
188{
189 return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
190}
191
192/** 188/**
193 * pm8001_interrupt_handler_msix - main MSIX interrupt handler. 189 * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
194 * It obtains the vector number and calls the equivalent bottom 190 * It obtains the vector number and calls the equivalent bottom
@@ -198,18 +194,20 @@ static struct pm8001_hba_info *outq_to_hba(u8 *outq)
198 */ 194 */
199static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) 195static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
200{ 196{
201 struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque); 197 struct isr_param *irq_vector;
202 u8 outq = *(u8 *)opaque; 198 struct pm8001_hba_info *pm8001_ha;
203 irqreturn_t ret = IRQ_HANDLED; 199 irqreturn_t ret = IRQ_HANDLED;
200 irq_vector = (struct isr_param *)opaque;
201 pm8001_ha = irq_vector->drv_inst;
202
204 if (unlikely(!pm8001_ha)) 203 if (unlikely(!pm8001_ha))
205 return IRQ_NONE; 204 return IRQ_NONE;
206 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) 205 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
207 return IRQ_NONE; 206 return IRQ_NONE;
208 pm8001_ha->int_vector = outq;
209#ifdef PM8001_USE_TASKLET 207#ifdef PM8001_USE_TASKLET
210 tasklet_schedule(&pm8001_ha->tasklet); 208 tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
211#else 209#else
212 ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq); 210 ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
213#endif 211#endif
214 return ret; 212 return ret;
215} 213}
@@ -230,9 +228,8 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
230 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) 228 if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
231 return IRQ_NONE; 229 return IRQ_NONE;
232 230
233 pm8001_ha->int_vector = 0;
234#ifdef PM8001_USE_TASKLET 231#ifdef PM8001_USE_TASKLET
235 tasklet_schedule(&pm8001_ha->tasklet); 232 tasklet_schedule(&pm8001_ha->tasklet[0]);
236#else 233#else
237 ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0); 234 ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
238#endif 235#endif
@@ -457,7 +454,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
457{ 454{
458 struct pm8001_hba_info *pm8001_ha; 455 struct pm8001_hba_info *pm8001_ha;
459 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 456 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
460 457 int j;
461 458
462 pm8001_ha = sha->lldd_ha; 459 pm8001_ha = sha->lldd_ha;
463 if (!pm8001_ha) 460 if (!pm8001_ha)
@@ -480,12 +477,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
480 pm8001_ha->iomb_size = IOMB_SIZE_SPC; 477 pm8001_ha->iomb_size = IOMB_SIZE_SPC;
481 478
482#ifdef PM8001_USE_TASKLET 479#ifdef PM8001_USE_TASKLET
483 /** 480 /* Tasklet for non msi-x interrupt handler */
484 * default tasklet for non msi-x interrupt handler/first msi-x 481 if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
485 * interrupt handler 482 tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
486 **/ 483 (unsigned long)&(pm8001_ha->irq_vector[0]));
487 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, 484 else
488 (unsigned long)pm8001_ha); 485 for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
486 tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
487 (unsigned long)&(pm8001_ha->irq_vector[j]));
489#endif 488#endif
490 pm8001_ioremap(pm8001_ha); 489 pm8001_ioremap(pm8001_ha);
491 if (!pm8001_alloc(pm8001_ha, ent)) 490 if (!pm8001_alloc(pm8001_ha, ent))
@@ -733,19 +732,20 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
733 "pci_enable_msix request ret:%d no of intr %d\n", 732 "pci_enable_msix request ret:%d no of intr %d\n",
734 rc, pm8001_ha->number_of_intr)); 733 rc, pm8001_ha->number_of_intr));
735 734
736 for (i = 0; i < number_of_intr; i++)
737 pm8001_ha->outq[i] = i;
738 735
739 for (i = 0; i < number_of_intr; i++) { 736 for (i = 0; i < number_of_intr; i++) {
740 snprintf(intr_drvname[i], sizeof(intr_drvname[0]), 737 snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
741 DRV_NAME"%d", i); 738 DRV_NAME"%d", i);
739 pm8001_ha->irq_vector[i].irq_id = i;
740 pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
741
742 if (request_irq(pm8001_ha->msix_entries[i].vector, 742 if (request_irq(pm8001_ha->msix_entries[i].vector,
743 pm8001_interrupt_handler_msix, flag, 743 pm8001_interrupt_handler_msix, flag,
744 intr_drvname[i], &pm8001_ha->outq[i])) { 744 intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
745 for (j = 0; j < i; j++) 745 for (j = 0; j < i; j++)
746 free_irq( 746 free_irq(
747 pm8001_ha->msix_entries[j].vector, 747 pm8001_ha->msix_entries[j].vector,
748 &pm8001_ha->outq[j]); 748 &(pm8001_ha->irq_vector[i]));
749 pci_disable_msix(pm8001_ha->pdev); 749 pci_disable_msix(pm8001_ha->pdev);
750 break; 750 break;
751 } 751 }
@@ -907,7 +907,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
907{ 907{
908 struct sas_ha_struct *sha = pci_get_drvdata(pdev); 908 struct sas_ha_struct *sha = pci_get_drvdata(pdev);
909 struct pm8001_hba_info *pm8001_ha; 909 struct pm8001_hba_info *pm8001_ha;
910 int i; 910 int i, j;
911 pm8001_ha = sha->lldd_ha; 911 pm8001_ha = sha->lldd_ha;
912 sas_unregister_ha(sha); 912 sas_unregister_ha(sha);
913 sas_remove_host(pm8001_ha->shost); 913 sas_remove_host(pm8001_ha->shost);
@@ -921,13 +921,18 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
921 synchronize_irq(pm8001_ha->msix_entries[i].vector); 921 synchronize_irq(pm8001_ha->msix_entries[i].vector);
922 for (i = 0; i < pm8001_ha->number_of_intr; i++) 922 for (i = 0; i < pm8001_ha->number_of_intr; i++)
923 free_irq(pm8001_ha->msix_entries[i].vector, 923 free_irq(pm8001_ha->msix_entries[i].vector,
924 &pm8001_ha->outq[i]); 924 &(pm8001_ha->irq_vector[i]));
925 pci_disable_msix(pdev); 925 pci_disable_msix(pdev);
926#else 926#else
927 free_irq(pm8001_ha->irq, sha); 927 free_irq(pm8001_ha->irq, sha);
928#endif 928#endif
929#ifdef PM8001_USE_TASKLET 929#ifdef PM8001_USE_TASKLET
930 tasklet_kill(&pm8001_ha->tasklet); 930 /* For non-msix and msix interrupts */
931 if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
932 tasklet_kill(&pm8001_ha->tasklet[0]);
933 else
934 for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
935 tasklet_kill(&pm8001_ha->tasklet[j]);
931#endif 936#endif
932 pm8001_free(pm8001_ha); 937 pm8001_free(pm8001_ha);
933 kfree(sha->sas_phy); 938 kfree(sha->sas_phy);
@@ -948,7 +953,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
948{ 953{
949 struct sas_ha_struct *sha = pci_get_drvdata(pdev); 954 struct sas_ha_struct *sha = pci_get_drvdata(pdev);
950 struct pm8001_hba_info *pm8001_ha; 955 struct pm8001_hba_info *pm8001_ha;
951 int i; 956 int i, j;
952 u32 device_state; 957 u32 device_state;
953 pm8001_ha = sha->lldd_ha; 958 pm8001_ha = sha->lldd_ha;
954 flush_workqueue(pm8001_wq); 959 flush_workqueue(pm8001_wq);
@@ -964,13 +969,18 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
964 synchronize_irq(pm8001_ha->msix_entries[i].vector); 969 synchronize_irq(pm8001_ha->msix_entries[i].vector);
965 for (i = 0; i < pm8001_ha->number_of_intr; i++) 970 for (i = 0; i < pm8001_ha->number_of_intr; i++)
966 free_irq(pm8001_ha->msix_entries[i].vector, 971 free_irq(pm8001_ha->msix_entries[i].vector,
967 &pm8001_ha->outq[i]); 972 &(pm8001_ha->irq_vector[i]));
968 pci_disable_msix(pdev); 973 pci_disable_msix(pdev);
969#else 974#else
970 free_irq(pm8001_ha->irq, sha); 975 free_irq(pm8001_ha->irq, sha);
971#endif 976#endif
972#ifdef PM8001_USE_TASKLET 977#ifdef PM8001_USE_TASKLET
973 tasklet_kill(&pm8001_ha->tasklet); 978 /* For non-msix and msix interrupts */
979 if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
980 tasklet_kill(&pm8001_ha->tasklet[0]);
981 else
982 for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
983 tasklet_kill(&pm8001_ha->tasklet[j]);
974#endif 984#endif
975 device_state = pci_choose_state(pdev, state); 985 device_state = pci_choose_state(pdev, state);
976 pm8001_printk("pdev=0x%p, slot=%s, entering " 986 pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -993,7 +1003,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
993 struct sas_ha_struct *sha = pci_get_drvdata(pdev); 1003 struct sas_ha_struct *sha = pci_get_drvdata(pdev);
994 struct pm8001_hba_info *pm8001_ha; 1004 struct pm8001_hba_info *pm8001_ha;
995 int rc; 1005 int rc;
996 u8 i = 0; 1006 u8 i = 0, j;
997 u32 device_state; 1007 u32 device_state;
998 pm8001_ha = sha->lldd_ha; 1008 pm8001_ha = sha->lldd_ha;
999 device_state = pdev->current_state; 1009 device_state = pdev->current_state;
@@ -1033,10 +1043,14 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
1033 if (rc) 1043 if (rc)
1034 goto err_out_disable; 1044 goto err_out_disable;
1035#ifdef PM8001_USE_TASKLET 1045#ifdef PM8001_USE_TASKLET
1036 /* default tasklet for non msi-x interrupt handler/first msi-x 1046 /* Tasklet for non msi-x interrupt handler */
1037 * interrupt handler */ 1047 if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
1038 tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, 1048 tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
1039 (unsigned long)pm8001_ha); 1049 (unsigned long)&(pm8001_ha->irq_vector[0]));
1050 else
1051 for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
1052 tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
1053 (unsigned long)&(pm8001_ha->irq_vector[j]));
1040#endif 1054#endif
1041 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); 1055 PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
1042 if (pm8001_ha->chip_id != chip_8001) { 1056 if (pm8001_ha->chip_id != chip_8001) {
@@ -1169,6 +1183,7 @@ module_exit(pm8001_exit);
1169MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); 1183MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
1170MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); 1184MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
1171MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); 1185MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
1186MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
1172MODULE_DESCRIPTION( 1187MODULE_DESCRIPTION(
1173 "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 " 1188 "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 "
1174 "SAS/SATA controller driver"); 1189 "SAS/SATA controller driver");