Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 942e298e authored by Jon Cooper's avatar Jon Cooper Committed by David S. Miller
Browse files

sfc: work around TRIGGER_INTERRUPT command not working on SFC9140



MC_CMD_TRIGGER_INTERRUPT does not work on the SFC9140, as used in the
sfn7x42q and sfn7x24f.
Check for this using the MCDI workaround mechanism.
The command is only used during self test.  If it's not supported, skip
the interrupt test.

Signed-off-by: default avatarEdward Cree <ecree@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent df0562c3
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -2048,14 +2048,18 @@ static irqreturn_t efx_ef10_legacy_interrupt(int irq, void *dev_id)
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


static void efx_ef10_irq_test_generate(struct efx_nic *efx)
static int efx_ef10_irq_test_generate(struct efx_nic *efx)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_TRIGGER_INTERRUPT_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_TRIGGER_INTERRUPT_IN_LEN);


	if (efx_mcdi_set_workaround(efx, MC_CMD_WORKAROUND_BUG41750, true,
				    NULL) == 0)
		return -ENOTSUPP;

	BUILD_BUG_ON(MC_CMD_TRIGGER_INTERRUPT_OUT_LEN != 0);
	BUILD_BUG_ON(MC_CMD_TRIGGER_INTERRUPT_OUT_LEN != 0);


	MCDI_SET_DWORD(inbuf, TRIGGER_INTERRUPT_IN_INTR_LEVEL, efx->irq_level);
	MCDI_SET_DWORD(inbuf, TRIGGER_INTERRUPT_IN_INTR_LEVEL, efx->irq_level);
	(void) efx_mcdi_rpc(efx, MC_CMD_TRIGGER_INTERRUPT,
	return efx_mcdi_rpc(efx, MC_CMD_TRIGGER_INTERRUPT,
			    inbuf, sizeof(inbuf), NULL, 0, NULL);
			    inbuf, sizeof(inbuf), NULL, 0, NULL);
}
}


+2 −1
Original line number Original line Diff line number Diff line
@@ -1477,9 +1477,10 @@ void efx_farch_irq_disable_master(struct efx_nic *efx)
 * Interrupt must already have been enabled, otherwise nasty things
 * Interrupt must already have been enabled, otherwise nasty things
 * may happen.
 * may happen.
 */
 */
void efx_farch_irq_test_generate(struct efx_nic *efx)
int efx_farch_irq_test_generate(struct efx_nic *efx)
{
{
	efx_farch_interrupts(efx, true, true);
	efx_farch_interrupts(efx, true, true);
	return 0;
}
}


/* Process a fatal interrupt
/* Process a fatal interrupt
+1 −1
Original line number Original line Diff line number Diff line
@@ -1275,7 +1275,7 @@ struct efx_nic_type {
	int (*mcdi_poll_reboot)(struct efx_nic *efx);
	int (*mcdi_poll_reboot)(struct efx_nic *efx);
	void (*mcdi_reboot_detected)(struct efx_nic *efx);
	void (*mcdi_reboot_detected)(struct efx_nic *efx);
	void (*irq_enable_master)(struct efx_nic *efx);
	void (*irq_enable_master)(struct efx_nic *efx);
	void (*irq_test_generate)(struct efx_nic *efx);
	int (*irq_test_generate)(struct efx_nic *efx);
	void (*irq_disable_non_ev)(struct efx_nic *efx);
	void (*irq_disable_non_ev)(struct efx_nic *efx);
	irqreturn_t (*irq_handle_msi)(int irq, void *dev_id);
	irqreturn_t (*irq_handle_msi)(int irq, void *dev_id);
	irqreturn_t (*irq_handle_legacy)(int irq, void *dev_id);
	irqreturn_t (*irq_handle_legacy)(int irq, void *dev_id);
+2 −2
Original line number Original line Diff line number Diff line
@@ -66,11 +66,11 @@ void efx_nic_event_test_start(struct efx_channel *channel)
	channel->efx->type->ev_test_generate(channel);
	channel->efx->type->ev_test_generate(channel);
}
}


void efx_nic_irq_test_start(struct efx_nic *efx)
int efx_nic_irq_test_start(struct efx_nic *efx)
{
{
	efx->last_irq_cpu = -1;
	efx->last_irq_cpu = -1;
	smp_wmb();
	smp_wmb();
	efx->type->irq_test_generate(efx);
	return efx->type->irq_test_generate(efx);
}
}


/* Hook interrupt handler(s)
/* Hook interrupt handler(s)
+2 −2
Original line number Original line Diff line number Diff line
@@ -746,12 +746,12 @@ static inline void efx_update_diff_stat(u64 *stat, u64 diff)


/* Interrupts */
/* Interrupts */
int efx_nic_init_interrupt(struct efx_nic *efx);
int efx_nic_init_interrupt(struct efx_nic *efx);
void efx_nic_irq_test_start(struct efx_nic *efx);
int efx_nic_irq_test_start(struct efx_nic *efx);
void efx_nic_fini_interrupt(struct efx_nic *efx);
void efx_nic_fini_interrupt(struct efx_nic *efx);


/* Falcon/Siena interrupts */
/* Falcon/Siena interrupts */
void efx_farch_irq_enable_master(struct efx_nic *efx);
void efx_farch_irq_enable_master(struct efx_nic *efx);
void efx_farch_irq_test_generate(struct efx_nic *efx);
int efx_farch_irq_test_generate(struct efx_nic *efx);
void efx_farch_irq_disable_master(struct efx_nic *efx);
void efx_farch_irq_disable_master(struct efx_nic *efx);
irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id);
irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id);
irqreturn_t efx_farch_legacy_interrupt(int irq, void *dev_id);
irqreturn_t efx_farch_legacy_interrupt(int irq, void *dev_id);
Loading