Message ID | 20170703084920.142A9508094@solo.franken.de (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
On 03.07.2017 10:38, Thomas Bogendoerfer wrote: > 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. > > Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> I didn't had parport_pc enabled on my c3000 so I never saw it crashing. After enabling parport_pc it crashes the same way as you describe. I tested with kernel 4.9.35. Thanks! Acked-by: Helge Deller <deller@gmx.de> > --- > arch/parisc/include/asm/dma-mapping.h | 11 +++++++---- > drivers/parisc/ccio-dma.c | 12 ++++++++++++ > drivers/parisc/dino.c | 5 ++++- > drivers/parisc/lba_pci.c | 6 ++++-- > 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 5404c6a..9a2a895 100644 > --- a/arch/parisc/include/asm/dma-mapping.h > +++ b/arch/parisc/include/asm/dma-mapping.h > @@ -20,6 +20,8 @@ > ** flush/purge and allocate "regular" cacheable pages for everything. > */ > > +#define DMA_ERROR_CODE (~(dma_addr_t)0) > + > #ifdef CONFIG_PA11 > extern const struct dma_map_ops pcxl_dma_ops; > extern const struct dma_map_ops pcx_dma_ops; > @@ -54,12 +56,13 @@ parisc_walk_tree(struct device *dev) > break; > } > } > - BUG_ON(!dev->platform_data); > return dev->platform_data; > } > - > -#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu) > - > + > +#define GET_IOC(dev) ({ \ > + void *__pdata = parisc_walk_tree(dev); \ > + __pdata ? HBA_DATA(__pdata)->iommu : NULL; \ > +}) > > #ifdef CONFIG_IOMMU_CCIO > struct parisc_device; > diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c > index e32ca2e..56c93f0 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, > > BUG_ON(!dev); > ioc = GET_IOC(dev); > + if (!ioc) > + return DMA_ERROR_CODE; > > BUG_ON(size <= 0); > > @@ -814,6 +816,10 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, > > BUG_ON(!dev); > ioc = GET_IOC(dev); > + if (!ioc) { > + WARN_ON(!ioc); > + return; > + } > > DBG_RUN("%s() iovp 0x%lx/%x\n", > __func__, (long)iova, size); > @@ -918,6 +924,8 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, > > BUG_ON(!dev); > ioc = GET_IOC(dev); > + if (!ioc) > + return 0; > > DBG_RUN_SG("%s() START %d entries\n", __func__, nents); > > @@ -990,6 +998,10 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, > > BUG_ON(!dev); > ioc = GET_IOC(dev); > + if (!ioc) { > + WARN_ON(!ioc); > + return; > + } > > DBG_RUN_SG("%s() START %d entries, %p,%x\n", > __func__, nents, sg_virt(sglist), sglist->length); > diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c > index 1133b5c..5c63b92 100644 > --- a/drivers/parisc/dino.c > +++ b/drivers/parisc/dino.c > @@ -154,7 +154,10 @@ struct dino_device > }; > > /* Looks nice and keeps the compiler happy */ > -#define DINO_DEV(d) ((struct dino_device *) d) > +#define DINO_DEV(d) ({ \ > + void *__pdata = d; \ > + BUG_ON(!__pdata); \ > + (struct dino_device *)__pdata; }) > > > /* > diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c > index 2ec2aef..bc286cb 100644 > --- a/drivers/parisc/lba_pci.c > +++ b/drivers/parisc/lba_pci.c > @@ -111,8 +111,10 @@ static u32 lba_t32; > > > /* Looks nice and keeps the compiler happy */ > -#define LBA_DEV(d) ((struct lba_device *) (d)) > - > +#define LBA_DEV(d) ({ \ > + void *__pdata = d; \ > + BUG_ON(!__pdata); \ > + (struct lba_device *)__pdata; }) > > /* > ** Only allow 8 subsidiary busses per LBA > diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c > index 33385e5..87ad5fd 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) > return 0; > > ioc = GET_IOC(dev); > + if (!ioc) > + return 0; > > /* > * 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, > int pide; > > ioc = GET_IOC(dev); > + if (!ioc) > + return DMA_ERROR_CODE; > > /* save offset bits */ > 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, > DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); > > ioc = GET_IOC(dev); > + if (!ioc) { > + WARN_ON(!ioc); > + return; > + } > offset = iova & ~IOVP_MASK; > iova ^= offset; /* clear offset bits */ > size += offset; > @@ -952,6 +960,8 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, > DBG_RUN_SG("%s() START %d entries\n", __func__, nents); > > ioc = GET_IOC(dev); > + if (!ioc) > + return 0; > > /* Fast path single entry scatterlists. */ > if (nents == 1) { > @@ -1037,6 +1047,10 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, > __func__, nents, sg_virt(sglist), sglist->length); > > ioc = GET_IOC(dev); > + if (!ioc) { > + WARN_ON(!ioc); > + return; > + } > > #ifdef SBA_COLLECT_STATS > ioc->usg_calls++; > -- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 5404c6a..9a2a895 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -20,6 +20,8 @@ ** flush/purge and allocate "regular" cacheable pages for everything. */ +#define DMA_ERROR_CODE (~(dma_addr_t)0) + #ifdef CONFIG_PA11 extern const struct dma_map_ops pcxl_dma_ops; extern const struct dma_map_ops pcx_dma_ops; @@ -54,12 +56,13 @@ parisc_walk_tree(struct device *dev) break; } } - BUG_ON(!dev->platform_data); return dev->platform_data; } - -#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu) - + +#define GET_IOC(dev) ({ \ + void *__pdata = parisc_walk_tree(dev); \ + __pdata ? HBA_DATA(__pdata)->iommu : NULL; \ +}) #ifdef CONFIG_IOMMU_CCIO struct parisc_device; diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index e32ca2e..56c93f0 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, BUG_ON(!dev); ioc = GET_IOC(dev); + if (!ioc) + return DMA_ERROR_CODE; BUG_ON(size <= 0); @@ -814,6 +816,10 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, BUG_ON(!dev); ioc = GET_IOC(dev); + if (!ioc) { + WARN_ON(!ioc); + return; + } DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long)iova, size); @@ -918,6 +924,8 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(!dev); ioc = GET_IOC(dev); + if (!ioc) + return 0; DBG_RUN_SG("%s() START %d entries\n", __func__, nents); @@ -990,6 +998,10 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(!dev); ioc = GET_IOC(dev); + if (!ioc) { + WARN_ON(!ioc); + return; + } DBG_RUN_SG("%s() START %d entries, %p,%x\n", __func__, nents, sg_virt(sglist), sglist->length); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 1133b5c..5c63b92 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -154,7 +154,10 @@ struct dino_device }; /* Looks nice and keeps the compiler happy */ -#define DINO_DEV(d) ((struct dino_device *) d) +#define DINO_DEV(d) ({ \ + void *__pdata = d; \ + BUG_ON(!__pdata); \ + (struct dino_device *)__pdata; }) /* diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 2ec2aef..bc286cb 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -111,8 +111,10 @@ static u32 lba_t32; /* Looks nice and keeps the compiler happy */ -#define LBA_DEV(d) ((struct lba_device *) (d)) - +#define LBA_DEV(d) ({ \ + void *__pdata = d; \ + BUG_ON(!__pdata); \ + (struct lba_device *)__pdata; }) /* ** Only allow 8 subsidiary busses per LBA diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 33385e5..87ad5fd 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) return 0; ioc = GET_IOC(dev); + if (!ioc) + return 0; /* * 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, int pide; ioc = GET_IOC(dev); + if (!ioc) + return DMA_ERROR_CODE; /* save offset bits */ 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, DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); ioc = GET_IOC(dev); + if (!ioc) { + WARN_ON(!ioc); + return; + } offset = iova & ~IOVP_MASK; iova ^= offset; /* clear offset bits */ size += offset; @@ -952,6 +960,8 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, DBG_RUN_SG("%s() START %d entries\n", __func__, nents); ioc = GET_IOC(dev); + if (!ioc) + return 0; /* Fast path single entry scatterlists. */ if (nents == 1) { @@ -1037,6 +1047,10 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, __func__, nents, sg_virt(sglist), sglist->length); ioc = GET_IOC(dev); + if (!ioc) { + WARN_ON(!ioc); + return; + } #ifdef SBA_COLLECT_STATS ioc->usg_calls++;
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. Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> --- arch/parisc/include/asm/dma-mapping.h | 11 +++++++---- drivers/parisc/ccio-dma.c | 12 ++++++++++++ drivers/parisc/dino.c | 5 ++++- drivers/parisc/lba_pci.c | 6 ++++-- drivers/parisc/sba_iommu.c | 14 ++++++++++++++ 5 files changed, 41 insertions(+), 7 deletions(-)