aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-08 15:32:19 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-08 15:32:19 -0400
commit66e358a84738ce93e192caed0e09bd44f26e48eb (patch)
treec73e32642a1f96d7e7031bce5e2ef468e6dc049d
parent8cc27d174b6502a4a9dc6186f35bf1351a6e200e (diff)
parent40afbb657352e92726c40cc4ddf3cf0be6800dba (diff)
Merge branch 'mrf24j40'
Alan Ott says: ==================== Fix race conditions in mrf24j40 interrupts After testing with the betas of this patchset, it's been rebased and is ready for inclusion. David Hauweele noticed that the mrf24j40 would hang arbitrarily after some period of heavy traffic. Two race conditions were discovered, and the driver was changed to use threaded interrupts, since the enable/disable of interrupts in the driver has recently been a lighning rod whenever issues arise related to interrupts (costing engineering time), and since threaded interrupts are the right way to do it. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ieee802154/mrf24j40.c31
1 files changed, 9 insertions, 22 deletions
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 42e6deee6db5..0632d34905c7 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -82,7 +82,6 @@ struct mrf24j40 {
82 82
83 struct mutex buffer_mutex; /* only used to protect buf */ 83 struct mutex buffer_mutex; /* only used to protect buf */
84 struct completion tx_complete; 84 struct completion tx_complete;
85 struct work_struct irqwork;
86 u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ 85 u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
87}; 86};
88 87
@@ -344,6 +343,8 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
344 if (ret) 343 if (ret)
345 goto err; 344 goto err;
346 345
346 INIT_COMPLETION(devrec->tx_complete);
347
347 /* Set TXNTRIG bit of TXNCON to send packet */ 348 /* Set TXNTRIG bit of TXNCON to send packet */
348 ret = read_short_reg(devrec, REG_TXNCON, &val); 349 ret = read_short_reg(devrec, REG_TXNCON, &val);
349 if (ret) 350 if (ret)
@@ -354,8 +355,6 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
354 val |= 0x4; 355 val |= 0x4;
355 write_short_reg(devrec, REG_TXNCON, val); 356 write_short_reg(devrec, REG_TXNCON, val);
356 357
357 INIT_COMPLETION(devrec->tx_complete);
358
359 /* Wait for the device to send the TX complete interrupt. */ 358 /* Wait for the device to send the TX complete interrupt. */
360 ret = wait_for_completion_interruptible_timeout( 359 ret = wait_for_completion_interruptible_timeout(
361 &devrec->tx_complete, 360 &devrec->tx_complete,
@@ -590,17 +589,6 @@ static struct ieee802154_ops mrf24j40_ops = {
590static irqreturn_t mrf24j40_isr(int irq, void *data) 589static irqreturn_t mrf24j40_isr(int irq, void *data)
591{ 590{
592 struct mrf24j40 *devrec = data; 591 struct mrf24j40 *devrec = data;
593
594 disable_irq_nosync(irq);
595
596 schedule_work(&devrec->irqwork);
597
598 return IRQ_HANDLED;
599}
600
601static void mrf24j40_isrwork(struct work_struct *work)
602{
603 struct mrf24j40 *devrec = container_of(work, struct mrf24j40, irqwork);
604 u8 intstat; 592 u8 intstat;
605 int ret; 593 int ret;
606 594
@@ -618,7 +606,7 @@ static void mrf24j40_isrwork(struct work_struct *work)
618 mrf24j40_handle_rx(devrec); 606 mrf24j40_handle_rx(devrec);
619 607
620out: 608out:
621 enable_irq(devrec->spi->irq); 609 return IRQ_HANDLED;
622} 610}
623 611
624static int mrf24j40_probe(struct spi_device *spi) 612static int mrf24j40_probe(struct spi_device *spi)
@@ -642,7 +630,6 @@ static int mrf24j40_probe(struct spi_device *spi)
642 630
643 mutex_init(&devrec->buffer_mutex); 631 mutex_init(&devrec->buffer_mutex);
644 init_completion(&devrec->tx_complete); 632 init_completion(&devrec->tx_complete);
645 INIT_WORK(&devrec->irqwork, mrf24j40_isrwork);
646 devrec->spi = spi; 633 devrec->spi = spi;
647 spi_set_drvdata(spi, devrec); 634 spi_set_drvdata(spi, devrec);
648 635
@@ -688,11 +675,12 @@ static int mrf24j40_probe(struct spi_device *spi)
688 val &= ~0x3; /* Clear RX mode (normal) */ 675 val &= ~0x3; /* Clear RX mode (normal) */
689 write_short_reg(devrec, REG_RXMCR, val); 676 write_short_reg(devrec, REG_RXMCR, val);
690 677
691 ret = request_irq(spi->irq, 678 ret = request_threaded_irq(spi->irq,
692 mrf24j40_isr, 679 NULL,
693 IRQF_TRIGGER_FALLING, 680 mrf24j40_isr,
694 dev_name(&spi->dev), 681 IRQF_TRIGGER_LOW|IRQF_ONESHOT,
695 devrec); 682 dev_name(&spi->dev),
683 devrec);
696 684
697 if (ret) { 685 if (ret) {
698 dev_err(printdev(devrec), "Unable to get IRQ"); 686 dev_err(printdev(devrec), "Unable to get IRQ");
@@ -721,7 +709,6 @@ static int mrf24j40_remove(struct spi_device *spi)
721 dev_dbg(printdev(devrec), "remove\n"); 709 dev_dbg(printdev(devrec), "remove\n");
722 710
723 free_irq(spi->irq, devrec); 711 free_irq(spi->irq, devrec);
724 flush_work(&devrec->irqwork); /* TODO: Is this the right call? */
725 ieee802154_unregister_device(devrec->dev); 712 ieee802154_unregister_device(devrec->dev);
726 ieee802154_free_device(devrec->dev); 713 ieee802154_free_device(devrec->dev);
727 /* TODO: Will ieee802154_free_device() wait until ->xmit() is 714 /* TODO: Will ieee802154_free_device() wait until ->xmit() is