Skip to content

Commit d611284

Browse files
jancoowcarlescufi
authored andcommitted
drivers: ethernet: w5500: Check W5500 int pin after processing interrupt
Check if W5500 int pin is still active after processing the interrupt. If not doing correctly, the W5500 driver can deadlock because it is not receiving any more interrupts. Signed-off-by: Janco Kock <[email protected]>
1 parent 9488727 commit d611284

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

drivers/ethernet/eth_w5500.c

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ static int w5500_tx(const struct device *dev, struct net_pkt *pkt)
208208

209209
static void w5500_rx(const struct device *dev)
210210
{
211-
uint8_t mask = 0;
212211
uint8_t header[2];
213212
uint8_t tmp[2];
214213
uint16_t off;
@@ -221,8 +220,6 @@ static void w5500_rx(const struct device *dev)
221220
struct w5500_runtime *ctx = dev->data;
222221
const struct w5500_config *config = dev->config;
223222

224-
/* disable interrupt */
225-
w5500_spi_write(dev, W5500_SIMR, &mask, 1);
226223
w5500_spi_read(dev, W5500_S0_RX_RSR, tmp, 2);
227224
rx_buf_len = sys_get_be16(tmp);
228225

@@ -280,34 +277,36 @@ static void w5500_rx(const struct device *dev)
280277
w5500_command(dev, S0_CR_RECV);
281278
}
282279

283-
static void w5500_isr(const struct device *dev)
280+
static void w5500_thread(const struct device *dev)
284281
{
285282
uint8_t ir;
286-
uint8_t mask = 0;
287283
struct w5500_runtime *ctx = dev->data;
284+
const struct w5500_config *config = dev->config;
288285

289286
while (true) {
290287
k_sem_take(&ctx->int_sem, K_FOREVER);
291288

292-
w5500_spi_read(dev, W5500_S0_IR, &ir, 1);
293-
if (!ir) {
294-
goto done;
295-
}
289+
while (gpio_pin_get_dt(&(config->interrupt))) {
290+
/* Read interrupt */
291+
w5500_spi_read(dev, W5500_S0_IR, &ir, 1);
296292

297-
w5500_spi_write(dev, W5500_S0_IR, &ir, 1);
293+
if (ir) {
294+
/* Clear interrupt */
295+
w5500_spi_write(dev, W5500_S0_IR, &ir, 1);
298296

299-
if (ir & S0_IR_SENDOK) {
300-
k_sem_give(&ctx->tx_sem);
301-
LOG_DBG("TX Done");
302-
}
297+
LOG_DBG("IR received");
303298

304-
if (ir & S0_IR_RECV) {
305-
w5500_rx(dev);
299+
if (ir & S0_IR_SENDOK) {
300+
k_sem_give(&ctx->tx_sem);
301+
LOG_DBG("TX Done");
302+
}
303+
304+
if (ir & S0_IR_RECV) {
305+
w5500_rx(dev);
306+
LOG_DBG("RX Done");
307+
}
308+
}
306309
}
307-
done:
308-
/* enable interrupt */
309-
mask = IR_S0;
310-
w5500_spi_write(dev, W5500_SIMR, &mask, 1);
311310
}
312311
}
313312

@@ -530,7 +529,7 @@ static int w5500_init(const struct device *dev)
530529

531530
k_thread_create(&ctx->thread, ctx->thread_stack,
532531
CONFIG_ETH_W5500_RX_THREAD_STACK_SIZE,
533-
(k_thread_entry_t)w5500_isr,
532+
(k_thread_entry_t)w5500_thread,
534533
(void *)dev, NULL, NULL,
535534
K_PRIO_COOP(CONFIG_ETH_W5500_RX_THREAD_PRIO),
536535
0, K_NO_WAIT);

0 commit comments

Comments
 (0)