Commit abf94132 authored by Paul Mundt's avatar Paul Mundt Committed by Linus Torvalds

[PATCH] sh: consistent API cleanup

This gets rid of the hardcoded workarounds for the Dreamcast in the
dma-mapping code, and now wraps into the common consistent_alloc() and
consistent_free() routines if the ones in the machvec aren't interested in
handling it.
Signed-off-by: default avatarPaul Mundt <paul.mundt@nokia.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 83da6494
/* /*
* arch/sh/boards/dreamcast/setup.c * arch/sh/boards/dreamcast/setup.c
* *
* Hardware support for the Sega Dreamcast. * Hardware support for the Sega Dreamcast.
* *
* Copyright (c) 2001, 2002 M. R. Brown <mrbrown@linuxdc.org> * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@linuxdc.org>
* Copyright (c) 2002, 2003 Paul Mundt <lethal@linux-sh.org> * Copyright (c) 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
* *
* This file is part of the LinuxDC project (www.linuxdc.org) * This file is part of the LinuxDC project (www.linuxdc.org)
* *
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
* *
* This file originally bore the message (with enclosed-$): * This file originally bore the message (with enclosed-$):
* Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp
* SEGA Dreamcast support * SEGA Dreamcast support
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -34,6 +35,10 @@ extern void (*board_time_init)(void); ...@@ -34,6 +35,10 @@ extern void (*board_time_init)(void);
extern void aica_time_init(void); extern void aica_time_init(void);
extern int gapspci_init(void); extern int gapspci_init(void);
extern int systemasic_irq_demux(int); extern int systemasic_irq_demux(int);
void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
const char *get_system_type(void) const char *get_system_type(void)
{ {
return "Sega Dreamcast"; return "Sega Dreamcast";
...@@ -43,6 +48,11 @@ struct sh_machine_vector mv_dreamcast __initmv = { ...@@ -43,6 +48,11 @@ struct sh_machine_vector mv_dreamcast __initmv = {
.mv_nr_irqs = NR_IRQS, .mv_nr_irqs = NR_IRQS,
.mv_irq_demux = systemasic_irq_demux, .mv_irq_demux = systemasic_irq_demux,
#ifdef CONFIG_PCI
.mv_consistent_alloc = dreamcast_consistent_alloc,
.mv_consistent_free = dreamcast_consistent_free,
#endif
}; };
ALIAS_MV(dreamcast) ALIAS_MV(dreamcast)
......
...@@ -24,7 +24,7 @@ extern void *rts7751r2d_ioremap(unsigned long, unsigned long); ...@@ -24,7 +24,7 @@ extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
extern int rts7751r2d_irq_demux(int irq); extern int rts7751r2d_irq_demux(int irq);
extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int); extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
extern void voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t); extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
/* /*
* The Machine Vector * The Machine Vector
...@@ -62,7 +62,9 @@ struct sh_machine_vector mv_rts7751r2d __initmv = { ...@@ -62,7 +62,9 @@ struct sh_machine_vector mv_rts7751r2d __initmv = {
#endif #endif
.mv_irq_demux = rts7751r2d_irq_demux, .mv_irq_demux = rts7751r2d_irq_demux,
#ifdef CONFIG_USB_OHCI_HCD
.mv_consistent_alloc = voyagergx_consistent_alloc, .mv_consistent_alloc = voyagergx_consistent_alloc,
.mv_consistent_free = voyagergx_consistent_free, .mv_consistent_free = voyagergx_consistent_free,
#endif
}; };
ALIAS_MV(rts7751r2d) ALIAS_MV(rts7751r2d)
...@@ -49,13 +49,13 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size, ...@@ -49,13 +49,13 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size,
if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
(dev->bus == &sh_bus_types[SH_BUS_VIRT] && (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
shdev->dev_id != SH_DEV_ID_USB_OHCI)) shdev->dev_id != SH_DEV_ID_USB_OHCI))
return consistent_alloc(flag, size, handle); return NULL;
start = OHCI_SRAM_START + OHCI_HCCA_SIZE; start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC); entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
if (!entry) if (!entry)
return NULL; return ERR_PTR(-ENOMEM);
entry->len = (size + 15) & ~15; entry->len = (size + 15) & ~15;
...@@ -91,11 +91,11 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size, ...@@ -91,11 +91,11 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size,
kfree(entry); kfree(entry);
spin_unlock_irqrestore(&voya_list_lock, flags); spin_unlock_irqrestore(&voya_list_lock, flags);
return NULL; return ERR_PTR(-EINVAL);
} }
void voyagergx_consistent_free(struct device *dev, size_t size, int voyagergx_consistent_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t handle) void *vaddr, dma_addr_t handle)
{ {
struct voya_alloc_entry *entry; struct voya_alloc_entry *entry;
struct sh_dev *shdev = to_sh_dev(dev); struct sh_dev *shdev = to_sh_dev(dev);
...@@ -103,10 +103,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size, ...@@ -103,10 +103,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size,
if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
(dev->bus == &sh_bus_types[SH_BUS_VIRT] && (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
shdev->dev_id != SH_DEV_ID_USB_OHCI)) { shdev->dev_id != SH_DEV_ID_USB_OHCI))
consistent_free(vaddr, size); return -EINVAL;
return;
}
spin_lock_irqsave(&voya_list_lock, flags); spin_lock_irqsave(&voya_list_lock, flags);
list_for_each_entry(entry, &voya_alloc_list, list) { list_for_each_entry(entry, &voya_alloc_list, list) {
...@@ -119,6 +117,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size, ...@@ -119,6 +117,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size,
break; break;
} }
spin_unlock_irqrestore(&voya_list_lock, flags); spin_unlock_irqrestore(&voya_list_lock, flags);
return 0;
} }
EXPORT_SYMBOL(voyagergx_consistent_alloc); EXPORT_SYMBOL(voyagergx_consistent_alloc);
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -30,18 +32,21 @@ ...@@ -30,18 +32,21 @@
static int gapspci_dma_used = 0; static int gapspci_dma_used = 0;
void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size, void *dreamcast_consistent_alloc(struct device *dev, size_t size,
dma_addr_t * dma_handle) dma_addr_t *dma_handle, int flag)
{ {
unsigned long buf; unsigned long buf;
if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) if (dev && dev->bus != &pci_bus_type)
return NULL; return NULL;
buf = GAPSPCI_DMA_BASE+gapspci_dma_used; if (gapspci_dma_used + size > GAPSPCI_DMA_SIZE)
return ERR_PTR(-EINVAL);
buf = GAPSPCI_DMA_BASE + gapspci_dma_used;
gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
*dma_handle = (dma_addr_t)buf; *dma_handle = (dma_addr_t)buf;
buf = P2SEGADDR(buf); buf = P2SEGADDR(buf);
...@@ -52,10 +57,15 @@ void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ...@@ -52,10 +57,15 @@ void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
return (void *)buf; return (void *)buf;
} }
void __pci_free_consistent(struct pci_dev *hwdev, size_t size, int dreamcast_consistent_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle) void *vaddr, dma_addr_t dma_handle)
{ {
if (dev && dev->bus != &pci_bus_type)
return -EINVAL;
/* XXX */ /* XXX */
gapspci_dma_used = 0; gapspci_dma_used = 0;
return 0;
} }
...@@ -78,4 +78,8 @@ void consistent_sync(void *vaddr, size_t size, int direction) ...@@ -78,4 +78,8 @@ void consistent_sync(void *vaddr, size_t size, int direction)
BUG(); BUG();
} }
} }
EXPORT_SYMBOL(consistent_alloc);
EXPORT_SYMBOL(consistent_free);
EXPORT_SYMBOL(consistent_sync); EXPORT_SYMBOL(consistent_sync);
...@@ -3,23 +3,17 @@ ...@@ -3,23 +3,17 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/device.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#include <asm/io.h> #include <asm/io.h>
extern struct bus_type pci_bus_type;
/* arch/sh/mm/consistent.c */ /* arch/sh/mm/consistent.c */
extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle); extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
extern void consistent_free(void *vaddr, size_t size); extern void consistent_free(void *vaddr, size_t size);
extern void consistent_sync(void *vaddr, size_t size, int direction); extern void consistent_sync(void *vaddr, size_t size, int direction);
#ifdef CONFIG_SH_DREAMCAST
struct pci_dev;
extern struct bus_type pci_bus_type;
extern void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle);
extern void __pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
#endif
#define dma_supported(dev, mask) (1) #define dma_supported(dev, mask) (1)
static inline int dma_set_mask(struct device *dev, u64 mask) static inline int dma_set_mask(struct device *dev, u64 mask)
...@@ -35,16 +29,13 @@ static inline int dma_set_mask(struct device *dev, u64 mask) ...@@ -35,16 +29,13 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
static inline void *dma_alloc_coherent(struct device *dev, size_t size, static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int flag) dma_addr_t *dma_handle, int flag)
{ {
/* if (sh_mv.mv_consistent_alloc) {
* Some platforms have special pci_alloc_consistent() implementations, void *ret;
* in these instances we can't use the generic consistent_alloc().
*/ ret = sh_mv.mv_consistent_alloc(dev, size, dma_handle, flag);
#ifdef CONFIG_SH_DREAMCAST if (ret != NULL)
if (dev && dev->bus == &pci_bus_type) return ret;
return __pci_alloc_consistent(NULL, size, dma_handle); }
#endif
if (sh_mv.mv_consistent_alloc)
return sh_mv.mv_consistent_alloc(dev, size, dma_handle, flag);
return consistent_alloc(flag, size, dma_handle); return consistent_alloc(flag, size, dma_handle);
} }
...@@ -52,19 +43,12 @@ static inline void *dma_alloc_coherent(struct device *dev, size_t size, ...@@ -52,19 +43,12 @@ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
static inline void dma_free_coherent(struct device *dev, size_t size, static inline void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle) void *vaddr, dma_addr_t dma_handle)
{ {
/*
* Same note as above applies to pci_free_consistent()..
*/
#ifdef CONFIG_SH_DREAMCAST
if (dev && dev->bus == &pci_bus_type) {
__pci_free_consistent(NULL, size, vaddr, dma_handle);
return;
}
#endif
if (sh_mv.mv_consistent_free) { if (sh_mv.mv_consistent_free) {
sh_mv.mv_consistent_free(dev, size, vaddr, dma_handle); int ret;
return;
ret = sh_mv.mv_consistent_free(dev, size, vaddr, dma_handle);
if (ret == 0)
return;
} }
consistent_free(vaddr, size); consistent_free(vaddr, size);
......
...@@ -65,7 +65,7 @@ struct sh_machine_vector ...@@ -65,7 +65,7 @@ struct sh_machine_vector
void (*mv_heartbeat)(void); void (*mv_heartbeat)(void);
void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, int); void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, int);
void (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t); int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
}; };
extern struct sh_machine_vector sh_mv; extern struct sh_machine_vector sh_mv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment