Skip to content

Commit fec7fa0

Browse files
Sebastian Andrzej Siewiorkuba-moo
authored andcommitted
chelsio: cxgb: Replace the workqueue with threaded interrupt
The external interrupt (F_PL_INTR_EXT) needs to be handled in a process context and this is accomplished by utilizing a workqueue. The process context can also be provided by a threaded interrupt instead of a workqueue. The threaded interrupt can be used later for other interrupt related processing which require non-atomic context without using yet another workqueue. free_irq() also ensures that the thread is done which is currently missing (the worker could continue after the module has been removed). Save pending flags in pending_thread_intr. Use the same mechanism to disable F_PL_INTR_EXT as interrupt source like it is used before the worker is scheduled. Enable the interrupt again once t1_elmer0_ext_intr_handler() is done. Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 462e99a commit fec7fa0

File tree

5 files changed

+55
-54
lines changed

5 files changed

+55
-54
lines changed

drivers/net/ethernet/chelsio/cxgb/common.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ struct adapter {
238238
int msg_enable;
239239
u32 mmio_len;
240240

241-
struct work_struct ext_intr_handler_task;
242241
struct adapter_params params;
243242

244243
/* Terminator modules. */
@@ -257,6 +256,7 @@ struct adapter {
257256

258257
/* guards async operations */
259258
spinlock_t async_lock ____cacheline_aligned;
259+
u32 pending_thread_intr;
260260
u32 slow_intr_mask;
261261
int t1powersave;
262262
};
@@ -334,8 +334,7 @@ void t1_interrupts_enable(adapter_t *adapter);
334334
void t1_interrupts_disable(adapter_t *adapter);
335335
void t1_interrupts_clear(adapter_t *adapter);
336336
int t1_elmer0_ext_intr_handler(adapter_t *adapter);
337-
void t1_elmer0_ext_intr(adapter_t *adapter);
338-
int t1_slow_intr_handler(adapter_t *adapter);
337+
irqreturn_t t1_slow_intr_handler(adapter_t *adapter);
339338

340339
int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
341340
const struct board_info *t1_get_board_info(unsigned int board_id);

drivers/net/ethernet/chelsio/cxgb/cxgb2.c

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,10 @@ static int cxgb_up(struct adapter *adapter)
211211
t1_interrupts_clear(adapter);
212212

213213
adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
214-
err = request_irq(adapter->pdev->irq, t1_interrupt,
215-
adapter->params.has_msi ? 0 : IRQF_SHARED,
216-
adapter->name, adapter);
214+
err = request_threaded_irq(adapter->pdev->irq, t1_interrupt,
215+
t1_interrupt_thread,
216+
adapter->params.has_msi ? 0 : IRQF_SHARED,
217+
adapter->name, adapter);
217218
if (err) {
218219
if (adapter->params.has_msi)
219220
pci_disable_msi(adapter->pdev);
@@ -916,41 +917,6 @@ static void mac_stats_task(struct work_struct *work)
916917
spin_unlock(&adapter->work_lock);
917918
}
918919

919-
/*
920-
* Processes elmer0 external interrupts in process context.
921-
*/
922-
static void ext_intr_task(struct work_struct *work)
923-
{
924-
struct adapter *adapter =
925-
container_of(work, struct adapter, ext_intr_handler_task);
926-
927-
t1_elmer0_ext_intr_handler(adapter);
928-
929-
/* Now reenable external interrupts */
930-
spin_lock_irq(&adapter->async_lock);
931-
adapter->slow_intr_mask |= F_PL_INTR_EXT;
932-
writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
933-
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
934-
adapter->regs + A_PL_ENABLE);
935-
spin_unlock_irq(&adapter->async_lock);
936-
}
937-
938-
/*
939-
* Interrupt-context handler for elmer0 external interrupts.
940-
*/
941-
void t1_elmer0_ext_intr(struct adapter *adapter)
942-
{
943-
/*
944-
* Schedule a task to handle external interrupts as we require
945-
* a process context. We disable EXT interrupts in the interim
946-
* and let the task reenable them when it's done.
947-
*/
948-
adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
949-
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
950-
adapter->regs + A_PL_ENABLE);
951-
schedule_work(&adapter->ext_intr_handler_task);
952-
}
953-
954920
void t1_fatal_err(struct adapter *adapter)
955921
{
956922
if (adapter->flags & FULL_INIT_DONE) {
@@ -1062,8 +1028,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
10621028
spin_lock_init(&adapter->async_lock);
10631029
spin_lock_init(&adapter->mac_lock);
10641030

1065-
INIT_WORK(&adapter->ext_intr_handler_task,
1066-
ext_intr_task);
10671031
INIT_DELAYED_WORK(&adapter->stats_update_task,
10681032
mac_stats_task);
10691033

drivers/net/ethernet/chelsio/cxgb/sge.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,11 +1619,38 @@ int t1_poll(struct napi_struct *napi, int budget)
16191619
return work_done;
16201620
}
16211621

1622+
irqreturn_t t1_interrupt_thread(int irq, void *data)
1623+
{
1624+
struct adapter *adapter = data;
1625+
u32 pending_thread_intr;
1626+
1627+
spin_lock_irq(&adapter->async_lock);
1628+
pending_thread_intr = adapter->pending_thread_intr;
1629+
adapter->pending_thread_intr = 0;
1630+
spin_unlock_irq(&adapter->async_lock);
1631+
1632+
if (!pending_thread_intr)
1633+
return IRQ_NONE;
1634+
1635+
if (pending_thread_intr & F_PL_INTR_EXT)
1636+
t1_elmer0_ext_intr_handler(adapter);
1637+
1638+
spin_lock_irq(&adapter->async_lock);
1639+
adapter->slow_intr_mask |= F_PL_INTR_EXT;
1640+
1641+
writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
1642+
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
1643+
adapter->regs + A_PL_ENABLE);
1644+
spin_unlock_irq(&adapter->async_lock);
1645+
1646+
return IRQ_HANDLED;
1647+
}
1648+
16221649
irqreturn_t t1_interrupt(int irq, void *data)
16231650
{
16241651
struct adapter *adapter = data;
16251652
struct sge *sge = adapter->sge;
1626-
int handled;
1653+
irqreturn_t handled;
16271654

16281655
if (likely(responses_pending(adapter))) {
16291656
writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
@@ -1645,10 +1672,10 @@ irqreturn_t t1_interrupt(int irq, void *data)
16451672
handled = t1_slow_intr_handler(adapter);
16461673
spin_unlock(&adapter->async_lock);
16471674

1648-
if (!handled)
1675+
if (handled == IRQ_NONE)
16491676
sge->stats.unhandled_irqs++;
16501677

1651-
return IRQ_RETVAL(handled != 0);
1678+
return handled;
16521679
}
16531680

16541681
/*

drivers/net/ethernet/chelsio/cxgb/sge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params *);
7474
int t1_sge_configure(struct sge *, struct sge_params *);
7575
int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
7676
void t1_sge_destroy(struct sge *);
77+
irqreturn_t t1_interrupt_thread(int irq, void *data);
7778
irqreturn_t t1_interrupt(int irq, void *cookie);
7879
int t1_poll(struct napi_struct *, int);
7980

drivers/net/ethernet/chelsio/cxgb/subr.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static int fpga_phy_intr_handler(adapter_t *adapter)
210210
/*
211211
* Slow path interrupt handler for FPGAs.
212212
*/
213-
static int fpga_slow_intr(adapter_t *adapter)
213+
static irqreturn_t fpga_slow_intr(adapter_t *adapter)
214214
{
215215
u32 cause = readl(adapter->regs + A_PL_CAUSE);
216216

@@ -238,7 +238,7 @@ static int fpga_slow_intr(adapter_t *adapter)
238238
if (cause)
239239
writel(cause, adapter->regs + A_PL_CAUSE);
240240

241-
return cause != 0;
241+
return cause == 0 ? IRQ_NONE : IRQ_HANDLED;
242242
}
243243
#endif
244244

@@ -842,13 +842,14 @@ void t1_interrupts_clear(adapter_t* adapter)
842842
/*
843843
* Slow path interrupt handler for ASICs.
844844
*/
845-
static int asic_slow_intr(adapter_t *adapter)
845+
static irqreturn_t asic_slow_intr(adapter_t *adapter)
846846
{
847847
u32 cause = readl(adapter->regs + A_PL_CAUSE);
848+
irqreturn_t ret = IRQ_HANDLED;
848849

849850
cause &= adapter->slow_intr_mask;
850851
if (!cause)
851-
return 0;
852+
return IRQ_NONE;
852853
if (cause & F_PL_INTR_SGE_ERR)
853854
t1_sge_intr_error_handler(adapter->sge);
854855
if (cause & F_PL_INTR_TP)
@@ -857,16 +858,25 @@ static int asic_slow_intr(adapter_t *adapter)
857858
t1_espi_intr_handler(adapter->espi);
858859
if (cause & F_PL_INTR_PCIX)
859860
t1_pci_intr_handler(adapter);
860-
if (cause & F_PL_INTR_EXT)
861-
t1_elmer0_ext_intr(adapter);
861+
if (cause & F_PL_INTR_EXT) {
862+
/* Wake the threaded interrupt to handle external interrupts as
863+
* we require a process context. We disable EXT interrupts in
864+
* the interim and let the thread reenable them when it's done.
865+
*/
866+
adapter->pending_thread_intr |= F_PL_INTR_EXT;
867+
adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
868+
writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
869+
adapter->regs + A_PL_ENABLE);
870+
ret = IRQ_WAKE_THREAD;
871+
}
862872

863873
/* Clear the interrupts just processed. */
864874
writel(cause, adapter->regs + A_PL_CAUSE);
865875
readl(adapter->regs + A_PL_CAUSE); /* flush writes */
866-
return 1;
876+
return ret;
867877
}
868878

869-
int t1_slow_intr_handler(adapter_t *adapter)
879+
irqreturn_t t1_slow_intr_handler(adapter_t *adapter)
870880
{
871881
#ifdef CONFIG_CHELSIO_T1_1G
872882
if (!t1_is_asic(adapter))

0 commit comments

Comments
 (0)