diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index cf098889ba64..6f10b4964726 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -51,7 +51,7 @@ struct at86rf230_local { | |||
51 | struct ieee802154_dev *dev; | 51 | struct ieee802154_dev *dev; |
52 | 52 | ||
53 | spinlock_t lock; | 53 | spinlock_t lock; |
54 | bool irq_disabled; | 54 | bool irq_busy; |
55 | bool is_tx; | 55 | bool is_tx; |
56 | }; | 56 | }; |
57 | 57 | ||
@@ -547,7 +547,7 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) | |||
547 | unsigned long flags; | 547 | unsigned long flags; |
548 | 548 | ||
549 | spin_lock(&lp->lock); | 549 | spin_lock(&lp->lock); |
550 | if (lp->irq_disabled) { | 550 | if (lp->irq_busy) { |
551 | spin_unlock(&lp->lock); | 551 | spin_unlock(&lp->lock); |
552 | return -EBUSY; | 552 | return -EBUSY; |
553 | } | 553 | } |
@@ -708,8 +708,16 @@ static void at86rf230_irqwork(struct work_struct *work) | |||
708 | } | 708 | } |
709 | 709 | ||
710 | spin_lock_irqsave(&lp->lock, flags); | 710 | spin_lock_irqsave(&lp->lock, flags); |
711 | lp->irq_disabled = 0; | 711 | lp->irq_busy = 0; |
712 | spin_unlock_irqrestore(&lp->lock, flags); | 712 | spin_unlock_irqrestore(&lp->lock, flags); |
713 | } | ||
714 | |||
715 | static void at86rf230_irqwork_level(struct work_struct *work) | ||
716 | { | ||
717 | struct at86rf230_local *lp = | ||
718 | container_of(work, struct at86rf230_local, irqwork); | ||
719 | |||
720 | at86rf230_irqwork(work); | ||
713 | 721 | ||
714 | enable_irq(lp->spi->irq); | 722 | enable_irq(lp->spi->irq); |
715 | } | 723 | } |
@@ -718,10 +726,8 @@ static irqreturn_t at86rf230_isr(int irq, void *data) | |||
718 | { | 726 | { |
719 | struct at86rf230_local *lp = data; | 727 | struct at86rf230_local *lp = data; |
720 | 728 | ||
721 | disable_irq_nosync(irq); | ||
722 | |||
723 | spin_lock(&lp->lock); | 729 | spin_lock(&lp->lock); |
724 | lp->irq_disabled = 1; | 730 | lp->irq_busy = 1; |
725 | spin_unlock(&lp->lock); | 731 | spin_unlock(&lp->lock); |
726 | 732 | ||
727 | schedule_work(&lp->irqwork); | 733 | schedule_work(&lp->irqwork); |
@@ -729,6 +735,13 @@ static irqreturn_t at86rf230_isr(int irq, void *data) | |||
729 | return IRQ_HANDLED; | 735 | return IRQ_HANDLED; |
730 | } | 736 | } |
731 | 737 | ||
738 | static irqreturn_t at86rf230_isr_level(int irq, void *data) | ||
739 | { | ||
740 | disable_irq_nosync(irq); | ||
741 | |||
742 | return at86rf230_isr(irq, data); | ||
743 | } | ||
744 | |||
732 | static int at86rf230_irq_polarity(struct at86rf230_local *lp, int pol) | 745 | static int at86rf230_irq_polarity(struct at86rf230_local *lp, int pol) |
733 | { | 746 | { |
734 | return at86rf230_write_subreg(lp, SR_IRQ_POLARITY, pol); | 747 | return at86rf230_write_subreg(lp, SR_IRQ_POLARITY, pol); |
@@ -766,12 +779,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) | |||
766 | if (rc) | 779 | if (rc) |
767 | return rc; | 780 | return rc; |
768 | 781 | ||
769 | rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, 0xff); /* IRQ_TRX_UR | | 782 | rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, IRQ_TRX_END); |
770 | * IRQ_CCA_ED | | ||
771 | * IRQ_TRX_END | | ||
772 | * IRQ_PLL_UNL | | ||
773 | * IRQ_PLL_LOCK | ||
774 | */ | ||
775 | if (rc) | 783 | if (rc) |
776 | return rc; | 784 | return rc; |
777 | 785 | ||
@@ -831,7 +839,9 @@ static int at86rf230_probe(struct spi_device *spi) | |||
831 | struct at86rf230_platform_data *pdata; | 839 | struct at86rf230_platform_data *pdata; |
832 | struct ieee802154_dev *dev; | 840 | struct ieee802154_dev *dev; |
833 | struct at86rf230_local *lp; | 841 | struct at86rf230_local *lp; |
834 | u8 man_id_0, man_id_1; | 842 | u8 man_id_0, man_id_1, status; |
843 | irq_handler_t irq_handler; | ||
844 | work_func_t irq_worker; | ||
835 | int rc, supported = 0; | 845 | int rc, supported = 0; |
836 | const char *chip; | 846 | const char *chip; |
837 | 847 | ||
@@ -861,8 +871,16 @@ static int at86rf230_probe(struct spi_device *spi) | |||
861 | dev->phy->channels_supported[0] = 0x7FFF800; | 871 | dev->phy->channels_supported[0] = 0x7FFF800; |
862 | dev->flags = IEEE802154_HW_OMIT_CKSUM; | 872 | dev->flags = IEEE802154_HW_OMIT_CKSUM; |
863 | 873 | ||
874 | if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { | ||
875 | irq_worker = at86rf230_irqwork; | ||
876 | irq_handler = at86rf230_isr; | ||
877 | } else { | ||
878 | irq_worker = at86rf230_irqwork_level; | ||
879 | irq_handler = at86rf230_isr_level; | ||
880 | } | ||
881 | |||
864 | mutex_init(&lp->bmux); | 882 | mutex_init(&lp->bmux); |
865 | INIT_WORK(&lp->irqwork, at86rf230_irqwork); | 883 | INIT_WORK(&lp->irqwork, irq_worker); |
866 | spin_lock_init(&lp->lock); | 884 | spin_lock_init(&lp->lock); |
867 | init_completion(&lp->tx_complete); | 885 | init_completion(&lp->tx_complete); |
868 | 886 | ||
@@ -943,12 +961,17 @@ static int at86rf230_probe(struct spi_device *spi) | |||
943 | if (rc) | 961 | if (rc) |
944 | goto err_gpio_dir; | 962 | goto err_gpio_dir; |
945 | 963 | ||
946 | rc = request_irq(spi->irq, at86rf230_isr, | 964 | rc = request_irq(spi->irq, irq_handler, |
947 | IRQF_SHARED | pdata->irq_type, | 965 | IRQF_SHARED | pdata->irq_type, |
948 | dev_name(&spi->dev), lp); | 966 | dev_name(&spi->dev), lp); |
949 | if (rc) | 967 | if (rc) |
950 | goto err_gpio_dir; | 968 | goto err_gpio_dir; |
951 | 969 | ||
970 | /* Read irq status register to reset irq line */ | ||
971 | rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status); | ||
972 | if (rc) | ||
973 | goto err_irq; | ||
974 | |||
952 | rc = ieee802154_register_device(lp->dev); | 975 | rc = ieee802154_register_device(lp->dev); |
953 | if (rc) | 976 | if (rc) |
954 | goto err_irq; | 977 | goto err_irq; |