Merge branch 'for-linus' of git://openrisc.net/~jonas/linux

* 'for-linus' of git://openrisc.net/~jonas/linux:
  Add missing DMA ops
  openrisc: don't use pt_regs in struct sigcontext
This commit is contained in:
Linus Torvalds 2011-09-11 14:55:43 -07:00
commit 14f69ec706
4 changed files with 96 additions and 27 deletions

View File

@ -31,7 +31,6 @@
#define DMA_ERROR_CODE (~(dma_addr_t)0x0) #define DMA_ERROR_CODE (~(dma_addr_t)0x0)
int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
@ -47,6 +46,12 @@ dma_addr_t or1k_map_page(struct device *dev, struct page *page,
void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir, size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs); struct dma_attrs *attrs);
int or1k_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
struct dma_attrs *attrs);
void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
struct dma_attrs *attrs);
void or1k_sync_single_for_cpu(struct device *dev, void or1k_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size, dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir); enum dma_data_direction dir);
@ -98,6 +103,51 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, true); debug_dma_unmap_page(dev, addr, size, dir, true);
} }
static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
{
int i, ents;
struct scatterlist *s;
for_each_sg(sg, s, nents, i)
kmemcheck_mark_initialized(sg_virt(s), s->length);
BUG_ON(!valid_dma_direction(dir));
ents = or1k_map_sg(dev, sg, nents, dir, NULL);
debug_dma_map_sg(dev, sg, nents, ents, dir);
return ents;
}
static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
{
BUG_ON(!valid_dma_direction(dir));
debug_dma_unmap_sg(dev, sg, nents, dir);
or1k_unmap_sg(dev, sg, nents, dir, NULL);
}
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
enum dma_data_direction dir)
{
dma_addr_t addr;
kmemcheck_mark_initialized(page_address(page) + offset, size);
BUG_ON(!valid_dma_direction(dir));
addr = or1k_map_page(dev, page, offset, size, dir, NULL);
debug_dma_map_page(dev, page, offset, size, dir, addr, false);
return addr;
}
static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
{
BUG_ON(!valid_dma_direction(dir));
or1k_unmap_page(dev, addr, size, dir, NULL);
debug_dma_unmap_page(dev, addr, size, dir, true);
}
static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
size_t size, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
@ -119,7 +169,12 @@ static inline void dma_sync_single_for_device(struct device *dev,
static inline int dma_supported(struct device *dev, u64 dma_mask) static inline int dma_supported(struct device *dev, u64 dma_mask)
{ {
/* Support 32 bit DMA mask exclusively */ /* Support 32 bit DMA mask exclusively */
return dma_mask == 0xffffffffULL; return dma_mask == DMA_BIT_MASK(32);
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return 0;
} }
static inline int dma_set_mask(struct device *dev, u64 dma_mask) static inline int dma_set_mask(struct device *dev, u64 dma_mask)

View File

@ -23,16 +23,11 @@
/* This struct is saved by setup_frame in signal.c, to keep the current /* This struct is saved by setup_frame in signal.c, to keep the current
context while a signal handler is executed. It's restored by sys_sigreturn. context while a signal handler is executed. It's restored by sys_sigreturn.
To keep things simple, we use pt_regs here even though normally you just
specify the list of regs to save. Then we can use copy_from_user on the
entire regs instead of a bunch of get_user's as well...
*/ */
struct sigcontext { struct sigcontext {
struct pt_regs regs; /* needs to be first */ struct user_regs_struct regs; /* needs to be first */
unsigned long oldmask; unsigned long oldmask;
unsigned long usp; /* usp before stacking this gunk on it */
}; };
#endif /* __ASM_OPENRISC_SIGCONTEXT_H */ #endif /* __ASM_OPENRISC_SIGCONTEXT_H */

View File

@ -154,6 +154,33 @@ void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
/* Nothing special to do here... */ /* Nothing special to do here... */
} }
int or1k_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nents, i) {
s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
s->length, dir, NULL);
}
return nents;
}
void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nents, i) {
or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL);
}
}
void or1k_sync_single_for_cpu(struct device *dev, void or1k_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size, dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
@ -187,5 +214,4 @@ static int __init dma_init(void)
return 0; return 0;
} }
fs_initcall(dma_init); fs_initcall(dma_init);

View File

@ -52,31 +52,25 @@ struct rt_sigframe {
static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{ {
unsigned int err = 0; unsigned int err = 0;
unsigned long old_usp;
/* Alwys make any pending restarted system call return -EINTR */ /* Alwys make any pending restarted system call return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* restore the regs from &sc->regs (same as sc, since regs is first) /*
* Restore the regs from &sc->regs.
* (sc is already checked for VERIFY_READ since the sigframe was * (sc is already checked for VERIFY_READ since the sigframe was
* checked in sys_sigreturn previously) * checked in sys_sigreturn previously)
*/ */
if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) goto badframe;
if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)))
goto badframe;
if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
goto badframe; goto badframe;
/* make sure the SM-bit is cleared so user-mode cannot fool us */ /* make sure the SM-bit is cleared so user-mode cannot fool us */
regs->sr &= ~SPR_SR_SM; regs->sr &= ~SPR_SR_SM;
/* restore the old USP as it was before we stacked the sc etc.
* (we cannot just pop the sigcontext since we aligned the sp and
* stuff after pushing it)
*/
err |= __get_user(old_usp, &sc->usp);
regs->sp = old_usp;
/* TODO: the other ports use regs->orig_XX to disable syscall checks /* TODO: the other ports use regs->orig_XX to disable syscall checks
* after this completes, but we don't use that mechanism. maybe we can * after this completes, but we don't use that mechanism. maybe we can
* use it now ? * use it now ?
@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
unsigned long mask) unsigned long mask)
{ {
int err = 0; int err = 0;
unsigned long usp = regs->sp;
/* copy the regs. they are first in sc so we can use sc directly */ /* copy the regs */
err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
/* then some other stuff */ /* then some other stuff */
err |= __put_user(mask, &sc->oldmask); err |= __put_user(mask, &sc->oldmask);
err |= __put_user(usp, &sc->usp);
return err; return err;
} }