Skip to content

Commit 85b85c8

Browse files
tlendackydavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 45a2005 commit 85b85c8

File tree

6 files changed

+115
-17
lines changed

6 files changed

+115
-17
lines changed

drivers/net/ethernet/amd/xgbe/xgbe-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@
959959
#define XP_DRIVER_INT_RO 0x0064
960960
#define XP_DRIVER_SCRATCH_0 0x0068
961961
#define XP_DRIVER_SCRATCH_1 0x006c
962+
#define XP_INT_REISSUE_EN 0x0074
962963
#define XP_INT_EN 0x0078
963964
#define XP_I2C_MUTEX 0x0080
964965
#define XP_MDIO_MUTEX 0x0084

drivers/net/ethernet/amd/xgbe/xgbe-drv.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period,
382382
return false;
383383
}
384384

385-
static irqreturn_t xgbe_ecc_isr(int irq, void *data)
385+
static void xgbe_ecc_isr_task(unsigned long data)
386386
{
387-
struct xgbe_prv_data *pdata = data;
387+
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
388388
unsigned int ecc_isr;
389389
bool stop = false;
390390

@@ -435,12 +435,26 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data)
435435
/* Clear all ECC interrupts */
436436
XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
437437

438-
return IRQ_HANDLED;
438+
/* Reissue interrupt if status is not clear */
439+
if (pdata->vdata->irq_reissue_support)
440+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 1);
439441
}
440442

441-
static irqreturn_t xgbe_isr(int irq, void *data)
443+
static irqreturn_t xgbe_ecc_isr(int irq, void *data)
442444
{
443445
struct xgbe_prv_data *pdata = data;
446+
447+
if (pdata->isr_as_tasklet)
448+
tasklet_schedule(&pdata->tasklet_ecc);
449+
else
450+
xgbe_ecc_isr_task((unsigned long)pdata);
451+
452+
return IRQ_HANDLED;
453+
}
454+
455+
static void xgbe_isr_task(unsigned long data)
456+
{
457+
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
444458
struct xgbe_hw_if *hw_if = &pdata->hw_if;
445459
struct xgbe_channel *channel;
446460
unsigned int dma_isr, dma_ch_isr;
@@ -543,15 +557,36 @@ static irqreturn_t xgbe_isr(int irq, void *data)
543557
isr_done:
544558
/* If there is not a separate AN irq, handle it here */
545559
if (pdata->dev_irq == pdata->an_irq)
546-
pdata->phy_if.an_isr(irq, pdata);
560+
pdata->phy_if.an_isr(pdata);
547561

548562
/* If there is not a separate ECC irq, handle it here */
549563
if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq))
550-
xgbe_ecc_isr(irq, pdata);
564+
xgbe_ecc_isr_task((unsigned long)pdata);
551565

552566
/* If there is not a separate I2C irq, handle it here */
553567
if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
554-
pdata->i2c_if.i2c_isr(irq, pdata);
568+
pdata->i2c_if.i2c_isr(pdata);
569+
570+
/* Reissue interrupt if status is not clear */
571+
if (pdata->vdata->irq_reissue_support) {
572+
unsigned int reissue_mask;
573+
574+
reissue_mask = 1 << 0;
575+
if (!pdata->per_channel_irq)
576+
reissue_mask |= 0xffff < 4;
577+
578+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask);
579+
}
580+
}
581+
582+
static irqreturn_t xgbe_isr(int irq, void *data)
583+
{
584+
struct xgbe_prv_data *pdata = data;
585+
586+
if (pdata->isr_as_tasklet)
587+
tasklet_schedule(&pdata->tasklet_dev);
588+
else
589+
xgbe_isr_task((unsigned long)pdata);
555590

556591
return IRQ_HANDLED;
557592
}
@@ -826,6 +861,10 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
826861
unsigned int i;
827862
int ret;
828863

864+
tasklet_init(&pdata->tasklet_dev, xgbe_isr_task, (unsigned long)pdata);
865+
tasklet_init(&pdata->tasklet_ecc, xgbe_ecc_isr_task,
866+
(unsigned long)pdata);
867+
829868
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
830869
netdev->name, pdata);
831870
if (ret) {

drivers/net/ethernet/amd/xgbe/xgbe-i2c.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,16 @@ static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata,
274274
XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
275275
}
276276

277-
static irqreturn_t xgbe_i2c_isr(int irq, void *data)
277+
static void xgbe_i2c_isr_task(unsigned long data)
278278
{
279279
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
280280
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
281281
unsigned int isr;
282282

283283
isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
284+
if (!isr)
285+
goto reissue_check;
286+
284287
netif_dbg(pdata, intr, pdata->netdev,
285288
"I2C interrupt received: status=%#010x\n", isr);
286289

@@ -308,6 +311,21 @@ static irqreturn_t xgbe_i2c_isr(int irq, void *data)
308311
if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
309312
complete(&pdata->i2c_complete);
310313

314+
reissue_check:
315+
/* Reissue interrupt if status is not clear */
316+
if (pdata->vdata->irq_reissue_support)
317+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2);
318+
}
319+
320+
static irqreturn_t xgbe_i2c_isr(int irq, void *data)
321+
{
322+
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
323+
324+
if (pdata->isr_as_tasklet)
325+
tasklet_schedule(&pdata->tasklet_i2c);
326+
else
327+
xgbe_i2c_isr_task((unsigned long)pdata);
328+
311329
return IRQ_HANDLED;
312330
}
313331

@@ -349,12 +367,11 @@ static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr)
349367
XI2C_IOWRITE(pdata, IC_TAR, addr);
350368
}
351369

352-
static irqreturn_t xgbe_i2c_combined_isr(int irq, struct xgbe_prv_data *pdata)
370+
static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata)
353371
{
354-
if (!XI2C_IOREAD(pdata, IC_RAW_INTR_STAT))
355-
return IRQ_HANDLED;
372+
xgbe_i2c_isr_task((unsigned long)pdata);
356373

357-
return xgbe_i2c_isr(irq, pdata);
374+
return IRQ_HANDLED;
358375
}
359376

360377
static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op)
@@ -445,6 +462,9 @@ static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
445462

446463
/* If we have a separate I2C irq, enable it */
447464
if (pdata->dev_irq != pdata->i2c_irq) {
465+
tasklet_init(&pdata->tasklet_i2c, xgbe_i2c_isr_task,
466+
(unsigned long)pdata);
467+
448468
ret = devm_request_irq(pdata->dev, pdata->i2c_irq,
449469
xgbe_i2c_isr, 0, pdata->i2c_name,
450470
pdata);

drivers/net/ethernet/amd/xgbe/xgbe-mdio.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,10 @@ static void xgbe_an37_isr(struct xgbe_prv_data *pdata)
665665
} else {
666666
/* Enable AN interrupts */
667667
xgbe_an37_enable_interrupts(pdata);
668+
669+
/* Reissue interrupt if status is not clear */
670+
if (pdata->vdata->irq_reissue_support)
671+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
668672
}
669673
}
670674

@@ -684,10 +688,14 @@ static void xgbe_an73_isr(struct xgbe_prv_data *pdata)
684688
} else {
685689
/* Enable AN interrupts */
686690
xgbe_an73_enable_interrupts(pdata);
691+
692+
/* Reissue interrupt if status is not clear */
693+
if (pdata->vdata->irq_reissue_support)
694+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
687695
}
688696
}
689697

690-
static irqreturn_t xgbe_an_isr(int irq, void *data)
698+
static void xgbe_an_isr_task(unsigned long data)
691699
{
692700
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
693701

@@ -705,13 +713,25 @@ static irqreturn_t xgbe_an_isr(int irq, void *data)
705713
default:
706714
break;
707715
}
716+
}
717+
718+
static irqreturn_t xgbe_an_isr(int irq, void *data)
719+
{
720+
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
721+
722+
if (pdata->isr_as_tasklet)
723+
tasklet_schedule(&pdata->tasklet_an);
724+
else
725+
xgbe_an_isr_task((unsigned long)pdata);
708726

709727
return IRQ_HANDLED;
710728
}
711729

712-
static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata)
730+
static irqreturn_t xgbe_an_combined_isr(struct xgbe_prv_data *pdata)
713731
{
714-
return xgbe_an_isr(irq, pdata);
732+
xgbe_an_isr_task((unsigned long)pdata);
733+
734+
return IRQ_HANDLED;
715735
}
716736

717737
static void xgbe_an_irq_work(struct work_struct *work)
@@ -915,6 +935,10 @@ static void xgbe_an_state_machine(struct work_struct *work)
915935
break;
916936
}
917937

938+
/* Reissue interrupt if status is not clear */
939+
if (pdata->vdata->irq_reissue_support)
940+
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
941+
918942
mutex_unlock(&pdata->an_mutex);
919943
}
920944

@@ -1379,6 +1403,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
13791403

13801404
/* If we have a separate AN irq, enable it */
13811405
if (pdata->dev_irq != pdata->an_irq) {
1406+
tasklet_init(&pdata->tasklet_an, xgbe_an_isr_task,
1407+
(unsigned long)pdata);
1408+
13821409
ret = devm_request_irq(pdata->dev, pdata->an_irq,
13831410
xgbe_an_isr, 0, pdata->an_name,
13841411
pdata);

drivers/net/ethernet/amd/xgbe/xgbe-pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static int xgbe_config_multi_msi(struct xgbe_prv_data *pdata)
139139
return ret;
140140
}
141141

142+
pdata->isr_as_tasklet = 1;
142143
pdata->irq_count = ret;
143144

144145
pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0);
@@ -175,6 +176,7 @@ static int xgbe_config_irqs(struct xgbe_prv_data *pdata)
175176
return ret;
176177
}
177178

179+
pdata->isr_as_tasklet = pdata->pcidev->msi_enabled ? 1 : 0;
178180
pdata->irq_count = 1;
179181
pdata->channel_irq_count = 1;
180182

@@ -445,6 +447,7 @@ static const struct xgbe_version_data xgbe_v2a = {
445447
.tx_tstamp_workaround = 1,
446448
.ecc_support = 1,
447449
.i2c_support = 1,
450+
.irq_reissue_support = 1,
448451
};
449452

450453
static const struct xgbe_version_data xgbe_v2b = {
@@ -456,6 +459,7 @@ static const struct xgbe_version_data xgbe_v2b = {
456459
.tx_tstamp_workaround = 1,
457460
.ecc_support = 1,
458461
.i2c_support = 1,
462+
.irq_reissue_support = 1,
459463
};
460464

461465
static const struct pci_device_id xgbe_pci_table[] = {

drivers/net/ethernet/amd/xgbe/xgbe.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ struct xgbe_phy_if {
837837
bool (*phy_valid_speed)(struct xgbe_prv_data *, int);
838838

839839
/* For single interrupt support */
840-
irqreturn_t (*an_isr)(int, struct xgbe_prv_data *);
840+
irqreturn_t (*an_isr)(struct xgbe_prv_data *);
841841

842842
/* PHY implementation specific services */
843843
struct xgbe_phy_impl_if phy_impl;
@@ -855,7 +855,7 @@ struct xgbe_i2c_if {
855855
int (*i2c_xfer)(struct xgbe_prv_data *, struct xgbe_i2c_op *);
856856

857857
/* For single interrupt support */
858-
irqreturn_t (*i2c_isr)(int, struct xgbe_prv_data *);
858+
irqreturn_t (*i2c_isr)(struct xgbe_prv_data *);
859859
};
860860

861861
struct xgbe_desc_if {
@@ -924,6 +924,7 @@ struct xgbe_version_data {
924924
unsigned int tx_tstamp_workaround;
925925
unsigned int ecc_support;
926926
unsigned int i2c_support;
927+
unsigned int irq_reissue_support;
927928
};
928929

929930
struct xgbe_prv_data {
@@ -1159,6 +1160,12 @@ struct xgbe_prv_data {
11591160

11601161
unsigned int lpm_ctrl; /* CTRL1 for resume */
11611162

1163+
unsigned int isr_as_tasklet;
1164+
struct tasklet_struct tasklet_dev;
1165+
struct tasklet_struct tasklet_ecc;
1166+
struct tasklet_struct tasklet_i2c;
1167+
struct tasklet_struct tasklet_an;
1168+
11621169
#ifdef CONFIG_DEBUG_FS
11631170
struct dentry *xgbe_debugfs;
11641171

0 commit comments

Comments
 (0)