diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2017-07-03 04:38:05 -0400 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2017-07-03 11:00:46 -0400 |
commit | 33f9e02495d15a061f0c94ef46f5103a2d0c20f3 (patch) | |
tree | 3fcc0f6afa5e86730eec9755c2d28103cad67298 | |
parent | 247462316f85a9e0479445c1a4223950b68ffac1 (diff) |
parisc: DMA API: return error instead of BUG_ON for dma ops on non dma devs
Enabling parport pc driver on a B2600 (and probably other 64bit PARISC
systems) produced following BUG:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.12.0-rc5-30198-g1132d5e #156
task: 000000009e050000 task.stack: 000000009e04c000
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00001000000001101111111100001111 Not tainted
r00-03 000000ff0806ff0f 000000009e04c990 0000000040871b78 000000009e04cac0
r04-07 0000000040c14de0 ffffffffffffffff 000000009e07f098 000000009d82d200
r08-11 000000009d82d210 0000000000000378 0000000000000000 0000000040c345e0
r12-15 0000000000000005 0000000040c345e0 0000000000000000 0000000040c9d5e0
r16-19 0000000040c345e0 00000000f00001c4 00000000f00001bc 0000000000000061
r20-23 000000009e04ce28 0000000000000010 0000000000000010 0000000040b89e40
r24-27 0000000000000003 0000000000ffffff 000000009d82d210 0000000040c14de0
r28-31 0000000000000000 000000009e04ca90 000000009e04cb40 0000000000000000
sr00-03 0000000000000000 0000000000000000 0000000000000000 0000000000000000
sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000404aece0 00000000404aece4
IIR: 03ffe01f ISR: 0000000010340000 IOR: 000001781304cac8
CPU: 0 CR30: 000000009e04c000 CR31: 00000000e2976de2
ORIG_R28: 0000000000000200
IAOQ[0]: sba_dma_supported+0x80/0xd0
IAOQ[1]: sba_dma_supported+0x84/0xd0
RP(r2): parport_pc_probe_port+0x178/0x1200
Cause is a call to dma_coerce_mask_and_coherenet in parport_pc_probe_port,
which PARISC DMA API doesn't handle very nicely. This commit gives back
DMA_ERROR_CODE for DMA API calls, if device isn't capable of DMA
transaction.
Cc: <stable@vger.kernel.org> # v3.13+
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | arch/parisc/include/asm/dma-mapping.h | 11 | ||||
-rw-r--r-- | drivers/parisc/ccio-dma.c | 12 | ||||
-rw-r--r-- | drivers/parisc/dino.c | 5 | ||||
-rw-r--r-- | drivers/parisc/lba_pci.c | 6 | ||||
-rw-r--r-- | drivers/parisc/sba_iommu.c | 14 |
5 files changed, 41 insertions, 7 deletions
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 5404c6a726b2..9a2a8956a695 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h | |||
@@ -20,6 +20,8 @@ | |||
20 | ** flush/purge and allocate "regular" cacheable pages for everything. | 20 | ** flush/purge and allocate "regular" cacheable pages for everything. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #define DMA_ERROR_CODE (~(dma_addr_t)0) | ||
24 | |||
23 | #ifdef CONFIG_PA11 | 25 | #ifdef CONFIG_PA11 |
24 | extern const struct dma_map_ops pcxl_dma_ops; | 26 | extern const struct dma_map_ops pcxl_dma_ops; |
25 | extern const struct dma_map_ops pcx_dma_ops; | 27 | extern const struct dma_map_ops pcx_dma_ops; |
@@ -54,12 +56,13 @@ parisc_walk_tree(struct device *dev) | |||
54 | break; | 56 | break; |
55 | } | 57 | } |
56 | } | 58 | } |
57 | BUG_ON(!dev->platform_data); | ||
58 | return dev->platform_data; | 59 | return dev->platform_data; |
59 | } | 60 | } |
60 | 61 | ||
61 | #define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu) | 62 | #define GET_IOC(dev) ({ \ |
62 | 63 | void *__pdata = parisc_walk_tree(dev); \ | |
64 | __pdata ? HBA_DATA(__pdata)->iommu : NULL; \ | ||
65 | }) | ||
63 | 66 | ||
64 | #ifdef CONFIG_IOMMU_CCIO | 67 | #ifdef CONFIG_IOMMU_CCIO |
65 | struct parisc_device; | 68 | struct parisc_device; |
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index e32ca2ef9e54..56c93f096de9 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c | |||
@@ -741,6 +741,8 @@ ccio_map_single(struct device *dev, void *addr, size_t size, | |||
741 | 741 | ||
742 | BUG_ON(!dev); | 742 | BUG_ON(!dev); |
743 | ioc = GET_IOC(dev); | 743 | ioc = GET_IOC(dev); |
744 | if (!ioc) | ||
745 | return DMA_ERROR_CODE; | ||
744 | 746 | ||
745 | BUG_ON(size <= 0); | 747 | BUG_ON(size <= 0); |
746 | 748 | ||
@@ -814,6 +816,10 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, | |||
814 | 816 | ||
815 | BUG_ON(!dev); | 817 | BUG_ON(!dev); |
816 | ioc = GET_IOC(dev); | 818 | ioc = GET_IOC(dev); |
819 | if (!ioc) { | ||
820 | WARN_ON(!ioc); | ||
821 | return; | ||
822 | } | ||
817 | 823 | ||
818 | DBG_RUN("%s() iovp 0x%lx/%x\n", | 824 | DBG_RUN("%s() iovp 0x%lx/%x\n", |
819 | __func__, (long)iova, size); | 825 | __func__, (long)iova, size); |
@@ -918,6 +924,8 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
918 | 924 | ||
919 | BUG_ON(!dev); | 925 | BUG_ON(!dev); |
920 | ioc = GET_IOC(dev); | 926 | ioc = GET_IOC(dev); |
927 | if (!ioc) | ||
928 | return 0; | ||
921 | 929 | ||
922 | DBG_RUN_SG("%s() START %d entries\n", __func__, nents); | 930 | DBG_RUN_SG("%s() START %d entries\n", __func__, nents); |
923 | 931 | ||
@@ -990,6 +998,10 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
990 | 998 | ||
991 | BUG_ON(!dev); | 999 | BUG_ON(!dev); |
992 | ioc = GET_IOC(dev); | 1000 | ioc = GET_IOC(dev); |
1001 | if (!ioc) { | ||
1002 | WARN_ON(!ioc); | ||
1003 | return; | ||
1004 | } | ||
993 | 1005 | ||
994 | DBG_RUN_SG("%s() START %d entries, %p,%x\n", | 1006 | DBG_RUN_SG("%s() START %d entries, %p,%x\n", |
995 | __func__, nents, sg_virt(sglist), sglist->length); | 1007 | __func__, nents, sg_virt(sglist), sglist->length); |
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 1133b5cc88ca..5c63b920b471 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c | |||
@@ -154,7 +154,10 @@ struct dino_device | |||
154 | }; | 154 | }; |
155 | 155 | ||
156 | /* Looks nice and keeps the compiler happy */ | 156 | /* Looks nice and keeps the compiler happy */ |
157 | #define DINO_DEV(d) ((struct dino_device *) d) | 157 | #define DINO_DEV(d) ({ \ |
158 | void *__pdata = d; \ | ||
159 | BUG_ON(!__pdata); \ | ||
160 | (struct dino_device *)__pdata; }) | ||
158 | 161 | ||
159 | 162 | ||
160 | /* | 163 | /* |
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 2ec2aef4d211..bc286cbbbc9b 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
@@ -111,8 +111,10 @@ static u32 lba_t32; | |||
111 | 111 | ||
112 | 112 | ||
113 | /* Looks nice and keeps the compiler happy */ | 113 | /* Looks nice and keeps the compiler happy */ |
114 | #define LBA_DEV(d) ((struct lba_device *) (d)) | 114 | #define LBA_DEV(d) ({ \ |
115 | 115 | void *__pdata = d; \ | |
116 | BUG_ON(!__pdata); \ | ||
117 | (struct lba_device *)__pdata; }) | ||
116 | 118 | ||
117 | /* | 119 | /* |
118 | ** Only allow 8 subsidiary busses per LBA | 120 | ** Only allow 8 subsidiary busses per LBA |
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 33385e574433..87ad5fd6a7a2 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
@@ -691,6 +691,8 @@ static int sba_dma_supported( struct device *dev, u64 mask) | |||
691 | return 0; | 691 | return 0; |
692 | 692 | ||
693 | ioc = GET_IOC(dev); | 693 | ioc = GET_IOC(dev); |
694 | if (!ioc) | ||
695 | return 0; | ||
694 | 696 | ||
695 | /* | 697 | /* |
696 | * check if mask is >= than the current max IO Virt Address | 698 | * check if mask is >= than the current max IO Virt Address |
@@ -722,6 +724,8 @@ sba_map_single(struct device *dev, void *addr, size_t size, | |||
722 | int pide; | 724 | int pide; |
723 | 725 | ||
724 | ioc = GET_IOC(dev); | 726 | ioc = GET_IOC(dev); |
727 | if (!ioc) | ||
728 | return DMA_ERROR_CODE; | ||
725 | 729 | ||
726 | /* save offset bits */ | 730 | /* save offset bits */ |
727 | offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK; | 731 | offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK; |
@@ -813,6 +817,10 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size, | |||
813 | DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); | 817 | DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); |
814 | 818 | ||
815 | ioc = GET_IOC(dev); | 819 | ioc = GET_IOC(dev); |
820 | if (!ioc) { | ||
821 | WARN_ON(!ioc); | ||
822 | return; | ||
823 | } | ||
816 | offset = iova & ~IOVP_MASK; | 824 | offset = iova & ~IOVP_MASK; |
817 | iova ^= offset; /* clear offset bits */ | 825 | iova ^= offset; /* clear offset bits */ |
818 | size += offset; | 826 | size += offset; |
@@ -952,6 +960,8 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
952 | DBG_RUN_SG("%s() START %d entries\n", __func__, nents); | 960 | DBG_RUN_SG("%s() START %d entries\n", __func__, nents); |
953 | 961 | ||
954 | ioc = GET_IOC(dev); | 962 | ioc = GET_IOC(dev); |
963 | if (!ioc) | ||
964 | return 0; | ||
955 | 965 | ||
956 | /* Fast path single entry scatterlists. */ | 966 | /* Fast path single entry scatterlists. */ |
957 | if (nents == 1) { | 967 | if (nents == 1) { |
@@ -1037,6 +1047,10 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
1037 | __func__, nents, sg_virt(sglist), sglist->length); | 1047 | __func__, nents, sg_virt(sglist), sglist->length); |
1038 | 1048 | ||
1039 | ioc = GET_IOC(dev); | 1049 | ioc = GET_IOC(dev); |
1050 | if (!ioc) { | ||
1051 | WARN_ON(!ioc); | ||
1052 | return; | ||
1053 | } | ||
1040 | 1054 | ||
1041 | #ifdef SBA_COLLECT_STATS | 1055 | #ifdef SBA_COLLECT_STATS |
1042 | ioc->usg_calls++; | 1056 | ioc->usg_calls++; |