amd-xgbe: Re-issue interrupt if interrupt status not cleared
Some of the device interrupts should function as level interrupts. For some hardware configurations this requires setting some control bits so that if the interrupt status has not been cleared the interrupt should be reissued. Additionally, when using MSI or MSI-X interrupts, run the interrupt service routine as a tasklet so that the re-issuance of the interrupt is handled properly. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
45a2005e93
commit
85b85c8534
@@ -665,6 +665,10 @@ static void xgbe_an37_isr(struct xgbe_prv_data *pdata)
|
||||
} else {
|
||||
/* Enable AN interrupts */
|
||||
xgbe_an37_enable_interrupts(pdata);
|
||||
|
||||
/* Reissue interrupt if status is not clear */
|
||||
if (pdata->vdata->irq_reissue_support)
|
||||
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,10 +688,14 @@ static void xgbe_an73_isr(struct xgbe_prv_data *pdata)
|
||||
} else {
|
||||
/* Enable AN interrupts */
|
||||
xgbe_an73_enable_interrupts(pdata);
|
||||
|
||||
/* Reissue interrupt if status is not clear */
|
||||
if (pdata->vdata->irq_reissue_support)
|
||||
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t xgbe_an_isr(int irq, void *data)
|
||||
static void xgbe_an_isr_task(unsigned long data)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
|
||||
|
||||
@@ -705,13 +713,25 @@ static irqreturn_t xgbe_an_isr(int irq, void *data)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t xgbe_an_isr(int irq, void *data)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
|
||||
|
||||
if (pdata->isr_as_tasklet)
|
||||
tasklet_schedule(&pdata->tasklet_an);
|
||||
else
|
||||
xgbe_an_isr_task((unsigned long)pdata);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata)
|
||||
static irqreturn_t xgbe_an_combined_isr(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return xgbe_an_isr(irq, pdata);
|
||||
xgbe_an_isr_task((unsigned long)pdata);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void xgbe_an_irq_work(struct work_struct *work)
|
||||
@@ -915,6 +935,10 @@ static void xgbe_an_state_machine(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reissue interrupt if status is not clear */
|
||||
if (pdata->vdata->irq_reissue_support)
|
||||
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
|
||||
|
||||
mutex_unlock(&pdata->an_mutex);
|
||||
}
|
||||
|
||||
@@ -1379,6 +1403,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
|
||||
|
||||
/* If we have a separate AN irq, enable it */
|
||||
if (pdata->dev_irq != pdata->an_irq) {
|
||||
tasklet_init(&pdata->tasklet_an, xgbe_an_isr_task,
|
||||
(unsigned long)pdata);
|
||||
|
||||
ret = devm_request_irq(pdata->dev, pdata->an_irq,
|
||||
xgbe_an_isr, 0, pdata->an_name,
|
||||
pdata);
|
||||
|
Reference in New Issue
Block a user