Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://openrisc.net/~jonas/linux
Browse files Browse the repository at this point in the history
* 'for-linus' of git://openrisc.net/~jonas/linux:
  Add missing DMA ops
  openrisc: don't use pt_regs in struct sigcontext
  • Loading branch information
Linus Torvalds committed Sep 11, 2011
2 parents d7a210f + 707b38a commit 14f69ec
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 27 deletions.
59 changes: 57 additions & 2 deletions arch/openrisc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

#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_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
Expand All @@ -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,
size_t size, enum dma_data_direction dir,
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,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
Expand Down Expand Up @@ -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);
}

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,
size_t size,
enum dma_data_direction dir)
Expand All @@ -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)
{
/* 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)
Expand Down
7 changes: 1 addition & 6 deletions arch/openrisc/include/asm/sigcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,11 @@

/* 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.
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 pt_regs regs; /* needs to be first */
struct user_regs_struct regs; /* needs to be first */
unsigned long oldmask;
unsigned long usp; /* usp before stacking this gunk on it */
};

#endif /* __ASM_OPENRISC_SIGCONTEXT_H */
28 changes: 27 additions & 1 deletion arch/openrisc/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,33 @@ void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
/* 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,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir)
Expand Down Expand Up @@ -187,5 +214,4 @@ static int __init dma_init(void)

return 0;
}

fs_initcall(dma_init);
29 changes: 11 additions & 18 deletions arch/openrisc/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,25 @@ struct rt_sigframe {
static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
unsigned int err = 0;
unsigned long old_usp;

/* Alwys make any pending restarted system call return -EINTR */
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
* checked in sys_sigreturn previously)
*/

if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
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;

/* make sure the SM-bit is cleared so user-mode cannot fool us */
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
* after this completes, but we don't use that mechanism. maybe we can
* use it now ?
Expand Down Expand Up @@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
unsigned long mask)
{
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 */

err |= __put_user(mask, &sc->oldmask);

err |= __put_user(usp, &sc->usp);

return err;
}

Expand Down

0 comments on commit 14f69ec

Please sign in to comment.