linux_dsm_epyc7002/arch/parisc/include/asm/dma-mapping.h
Thomas Bogendoerfer 33f9e02495 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>
2017-07-03 17:00:46 +02:00

90 lines
2.6 KiB
C

#ifndef _PARISC_DMA_MAPPING_H
#define _PARISC_DMA_MAPPING_H
#include <asm/cacheflush.h>
/*
** We need to support 4 different coherent dma models with one binary:
**
** I/O MMU consistent method dma_sync behavior
** ============= ====================== =======================
** a) PA-7x00LC uncachable host memory flush/purge
** b) U2/Uturn cachable host memory NOP
** c) Ike/Astro cachable host memory NOP
** d) EPIC/SAGA memory on EPIC/SAGA flush/reset DMA channel
**
** PA-7[13]00LC processors have a GSC bus interface and no I/O MMU.
**
** Systems (eg PCX-T workstations) that don't fall into the above
** categories will need to modify the needed drivers to perform
** 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;
#endif
extern const struct dma_map_ops *hppa_dma_ops;
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
{
return hppa_dma_ops;
}
static inline void
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
if (hppa_dma_ops->sync_single_for_cpu)
flush_kernel_dcache_range((unsigned long)vaddr, size);
}
static inline void *
parisc_walk_tree(struct device *dev)
{
struct device *otherdev;
if(likely(dev->platform_data != NULL))
return dev->platform_data;
/* OK, just traverse the bus to find it */
for(otherdev = dev->parent; otherdev;
otherdev = otherdev->parent) {
if(otherdev->platform_data) {
dev->platform_data = otherdev->platform_data;
break;
}
}
return dev->platform_data;
}
#define GET_IOC(dev) ({ \
void *__pdata = parisc_walk_tree(dev); \
__pdata ? HBA_DATA(__pdata)->iommu : NULL; \
})
#ifdef CONFIG_IOMMU_CCIO
struct parisc_device;
struct ioc;
void * ccio_get_iommu(const struct parisc_device *dev);
int ccio_request_resource(const struct parisc_device *dev,
struct resource *res);
int ccio_allocate_resource(const struct parisc_device *dev,
struct resource *res, unsigned long size,
unsigned long min, unsigned long max, unsigned long align);
#else /* !CONFIG_IOMMU_CCIO */
#define ccio_get_iommu(dev) NULL
#define ccio_request_resource(dev, res) insert_resource(&iomem_resource, res)
#define ccio_allocate_resource(dev, res, size, min, max, align) \
allocate_resource(&iomem_resource, res, size, min, max, \
align, NULL, NULL)
#endif /* !CONFIG_IOMMU_CCIO */
#ifdef CONFIG_IOMMU_SBA
struct parisc_device;
void * sba_get_iommu(struct parisc_device *dev);
#endif
#endif