@@ -204,7 +204,7 @@ static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
if (!PM8001_CHIP_DISP->is_our_interrupt(pm8001_ha))
return IRQ_NONE;
#ifdef PM8001_USE_TASKLET
- tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
+ tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id].tasklet);
#else
ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
#endif
@@ -228,7 +228,7 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
return IRQ_NONE;
#ifdef PM8001_USE_TASKLET
- tasklet_schedule(&pm8001_ha->tasklet[0]);
+ tasklet_schedule(&pm8001_ha->tasklet[0].tasklet);
#else
ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
#endif
@@ -477,13 +477,18 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
#ifdef PM8001_USE_TASKLET
/* Tasklet for non msi-x interrupt handler */
if ((!pdev->msix_cap || !pci_msi_enabled())
- || (pm8001_ha->chip_id == chip_8001))
- tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+ || (pm8001_ha->chip_id == chip_8001)) {
+ pm8001_ha->tasklet[0].irq_id = 0;
+ tasklet_init(&pm8001_ha->tasklet[0].tasklet, pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[0]));
- else
- for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
- tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+ } else {
+ for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) {
+ pm8001_ha->tasklet[j].irq_id = j;
+ tasklet_init(&pm8001_ha->tasklet[j].tasklet,
+ pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[j]));
+ }
+ }
#endif
pm8001_ioremap(pm8001_ha);
if (!pm8001_alloc(pm8001_ha, ent))
@@ -1092,10 +1097,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
/* For non-msix and msix interrupts */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
(pm8001_ha->chip_id == chip_8001))
- tasklet_kill(&pm8001_ha->tasklet[0]);
+ tasklet_kill(&pm8001_ha->tasklet[0].tasklet);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
- tasklet_kill(&pm8001_ha->tasklet[j]);
+ tasklet_kill(&pm8001_ha->tasklet[j].tasklet);
#endif
scsi_host_put(pm8001_ha->shost);
pm8001_free(pm8001_ha);
@@ -1142,10 +1147,10 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
/* For non-msix and msix interrupts */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
(pm8001_ha->chip_id == chip_8001))
- tasklet_kill(&pm8001_ha->tasklet[0]);
+ tasklet_kill(&pm8001_ha->tasklet[0].tasklet);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
- tasklet_kill(&pm8001_ha->tasklet[j]);
+ tasklet_kill(&pm8001_ha->tasklet[j].tasklet);
#endif
device_state = pci_choose_state(pdev, state);
pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -1211,13 +1216,18 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
#ifdef PM8001_USE_TASKLET
/* Tasklet for non msi-x interrupt handler */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
- (pm8001_ha->chip_id == chip_8001))
- tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+ (pm8001_ha->chip_id == chip_8001)) {
+ pm8001_ha->tasklet[0].irq_id = 0;
+ tasklet_init(&pm8001_ha->tasklet[0].tasklet, pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[0]));
- else
- for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
- tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+ } else {
+ for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) {
+ pm8001_ha->tasklet[j].irq_id = j;
+ tasklet_init(&pm8001_ha->tasklet[j].tasklet,
+ pm8001_tasklet,
(unsigned long)&(pm8001_ha->irq_vector[j]));
+ }
+ }
#endif
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
if (pm8001_ha->chip_id != chip_8001) {
@@ -480,6 +480,10 @@ struct isr_param {
struct pm8001_hba_info *drv_inst;
u32 irq_id;
};
+struct tsk_param {
+ struct tasklet_struct tasklet;
+ u32 irq_id;
+};
struct pm8001_hba_info {
char name[PM8001_NAME_LENGTH];
struct list_head list;
@@ -532,7 +536,7 @@ struct pm8001_hba_info {
int number_of_intr;/*will be used in remove()*/
#endif
#ifdef PM8001_USE_TASKLET
- struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC];
+ struct tsk_param tasklet[PM8001_MAX_MSIX_VEC];
#endif
u32 logging_level;
u32 fw_status;
The future tasklet API will no longer allow to pass an arbitrary "unsigned long" data parameter. The tasklet data structure will need to be embedded into a data structure that will be retrieved from the tasklet handler. Currently, there are no ways from the tasklet of the handler to retrieve the parent data structure by using container_of(), mainly because we cannot know the index of the tasklet in the array of tasklets. This commits adds a intermediate data structure, that stores "irq_id", that is the index of the irq_vector and of the tasklet, so based on this index we will be able to use container_of() and retrieve the root parent structure. Signed-off-by: Romain Perier <romain.perier@gmail.com> --- drivers/scsi/pm8001/pm8001_init.c | 42 +++++++++++++++++++------------ drivers/scsi/pm8001/pm8001_sas.h | 6 ++++- 2 files changed, 31 insertions(+), 17 deletions(-)