Commit c90b6544df8afbf9194b3dc7f363e907dcb7300e
1 parent
348d476956
Exists in
smarc_8mm_imx_4.14.98_2.0.0_ga
and in
4 other branches
MLK-21443: dmaengine: fsl-edma-v3: clear pending irq before request irq
edma interrupt maybe happened during reboot or watchdog reset, meanwhile gic never power down on i.mx8QM/QXP, thus the unexpect irq will come in once edma driver request irq at probe phase. Unfortunately, at that time that edma channel's power domain which power-up by customer driver such as audio/uart driver may not be ready, so kernel panic triggered once touch such edma registers which still not power up in interrupt handler. Move request irq from probe to alloc dma channel so that edma channel's power domain has already been powered, besides, clear meaningless interrupt before request irq. Signed-off-by: Robin Gong <yibin.gong@nxp.com> Acked-by: Fugang Duan <fugang.duan@nxp.com> (cherry picked from commit 0a0d8f8b944094342fda18f23f3ac13b8a73871d)
Showing 1 changed file with 22 additions and 12 deletions Side-by-side Diff
drivers/dma/fsl-edma-v3.c
... | ... | @@ -165,7 +165,8 @@ |
165 | 165 | int is_dfifo; |
166 | 166 | struct dma_pool *tcd_pool; |
167 | 167 | u32 chn_real_count; |
168 | - char txirq_name[32]; | |
168 | + char txirq_name[32]; | |
169 | + struct platform_device *pdev; | |
169 | 170 | }; |
170 | 171 | |
171 | 172 | struct fsl_edma3_desc { |
... | ... | @@ -183,6 +184,7 @@ |
183 | 184 | |
184 | 185 | struct fsl_edma3_engine { |
185 | 186 | struct dma_device dma_dev; |
187 | + unsigned long irqflag; | |
186 | 188 | struct mutex fsl_edma3_mutex; |
187 | 189 | u32 n_chans; |
188 | 190 | int errirq; |
189 | 191 | |
... | ... | @@ -791,10 +793,23 @@ |
791 | 793 | static int fsl_edma3_alloc_chan_resources(struct dma_chan *chan) |
792 | 794 | { |
793 | 795 | struct fsl_edma3_chan *fsl_chan = to_fsl_edma3_chan(chan); |
796 | + struct platform_device *pdev = fsl_chan->pdev; | |
797 | + int ret; | |
794 | 798 | |
795 | 799 | fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev, |
796 | 800 | sizeof(struct fsl_edma3_hw_tcd), |
797 | 801 | 32, 0); |
802 | + /* clear meaningless pending irq anyway */ | |
803 | + writel(1, fsl_chan->membase + EDMA_CH_INT); | |
804 | + ret = devm_request_irq(&pdev->dev, fsl_chan->txirq, | |
805 | + fsl_edma3_tx_handler, fsl_chan->edma3->irqflag, | |
806 | + fsl_chan->txirq_name, fsl_chan); | |
807 | + if (ret) { | |
808 | + dev_err(&pdev->dev, "Can't register %s IRQ.\n", | |
809 | + fsl_chan->txirq_name); | |
810 | + return ret; | |
811 | + } | |
812 | + | |
798 | 813 | return 0; |
799 | 814 | } |
800 | 815 | |
... | ... | @@ -804,6 +819,8 @@ |
804 | 819 | unsigned long flags; |
805 | 820 | LIST_HEAD(head); |
806 | 821 | |
822 | + devm_free_irq(&fsl_chan->pdev->dev, fsl_chan->txirq, fsl_chan); | |
823 | + | |
807 | 824 | spin_lock_irqsave(&fsl_chan->vchan.lock, flags); |
808 | 825 | fsl_edma3_disable_request(fsl_chan); |
809 | 826 | fsl_chan->edesc = NULL; |
... | ... | @@ -831,7 +848,6 @@ |
831 | 848 | struct resource *res; |
832 | 849 | int len, chans; |
833 | 850 | int ret, i; |
834 | - unsigned long irqflag = 0; | |
835 | 851 | |
836 | 852 | ret = of_property_read_u32(np, "dma-channels", &chans); |
837 | 853 | if (ret) { |
... | ... | @@ -846,7 +862,7 @@ |
846 | 862 | |
847 | 863 | /* Audio edma rx/tx channel shared interrupt */ |
848 | 864 | if (of_property_read_bool(np, "shared-interrupt")) |
849 | - irqflag = IRQF_SHARED; | |
865 | + fsl_edma3->irqflag = IRQF_SHARED; | |
850 | 866 | |
851 | 867 | fsl_edma3->swap = false; |
852 | 868 | fsl_edma3->n_chans = chans; |
853 | 869 | |
... | ... | @@ -866,12 +882,13 @@ |
866 | 882 | INIT_LIST_HEAD(&fsl_edma3->dma_dev.channels); |
867 | 883 | for (i = 0; i < fsl_edma3->n_chans; i++) { |
868 | 884 | struct fsl_edma3_chan *fsl_chan = &fsl_edma3->chans[i]; |
869 | - const char *txirq_name = fsl_chan->txirq_name; | |
885 | + const char *txirq_name; | |
870 | 886 | char chanid[3], id_len = 0; |
871 | 887 | char *p = chanid; |
872 | 888 | unsigned long val; |
873 | 889 | |
874 | 890 | fsl_chan->edma3 = fsl_edma3; |
891 | + fsl_chan->pdev = pdev; | |
875 | 892 | fsl_chan->pm_state = RUNNING; |
876 | 893 | fsl_chan->idle = true; |
877 | 894 | /* Get per channel membase */ |
... | ... | @@ -917,14 +934,7 @@ |
917 | 934 | return fsl_chan->txirq; |
918 | 935 | } |
919 | 936 | |
920 | - ret = devm_request_irq(&pdev->dev, fsl_chan->txirq, | |
921 | - fsl_edma3_tx_handler, irqflag, txirq_name, | |
922 | - fsl_chan); | |
923 | - if (ret) { | |
924 | - dev_err(&pdev->dev, "Can't register %s IRQ.\n", | |
925 | - txirq_name); | |
926 | - return ret; | |
927 | - } | |
937 | + memcpy(fsl_chan->txirq_name, txirq_name, strlen(txirq_name)); | |
928 | 938 | |
929 | 939 | fsl_chan->vchan.desc_free = fsl_edma3_free_desc; |
930 | 940 | vchan_init(&fsl_chan->vchan, &fsl_edma3->dma_dev); |