diff options
| -rw-r--r-- | arch/openrisc/include/asm/dma-mapping.h | 59 | ||||
| -rw-r--r-- | arch/openrisc/include/asm/sigcontext.h | 7 | ||||
| -rw-r--r-- | arch/openrisc/kernel/dma.c | 28 | ||||
| -rw-r--r-- | arch/openrisc/kernel/signal.c | 29 |
4 files changed, 96 insertions, 27 deletions
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h index 052f877b52a5..60b472233900 100644 --- a/arch/openrisc/include/asm/dma-mapping.h +++ b/arch/openrisc/include/asm/dma-mapping.h | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | 31 | ||
| 32 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) | 32 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) |
| 33 | 33 | ||
| 34 | int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); | ||
| 35 | 34 | ||
| 36 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 35 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
| 37 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | 36 | #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, | |||
| 47 | void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, | 46 | void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, |
| 48 | size_t size, enum dma_data_direction dir, | 47 | size_t size, enum dma_data_direction dir, |
| 49 | struct dma_attrs *attrs); | 48 | struct dma_attrs *attrs); |
| 49 | int or1k_map_sg(struct device *dev, struct scatterlist *sg, | ||
| 50 | int nents, enum dma_data_direction dir, | ||
| 51 | struct dma_attrs *attrs); | ||
| 52 | void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
| 53 | int nents, enum dma_data_direction dir, | ||
| 54 | struct dma_attrs *attrs); | ||
| 50 | void or1k_sync_single_for_cpu(struct device *dev, | 55 | void or1k_sync_single_for_cpu(struct device *dev, |
| 51 | dma_addr_t dma_handle, size_t size, | 56 | dma_addr_t dma_handle, size_t size, |
| 52 | enum dma_data_direction dir); | 57 | enum dma_data_direction dir); |
| @@ -98,6 +103,51 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, | |||
| 98 | debug_dma_unmap_page(dev, addr, size, dir, true); | 103 | debug_dma_unmap_page(dev, addr, size, dir, true); |
| 99 | } | 104 | } |
| 100 | 105 | ||
| 106 | static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
| 107 | int nents, enum dma_data_direction dir) | ||
| 108 | { | ||
| 109 | int i, ents; | ||
| 110 | struct scatterlist *s; | ||
| 111 | |||
| 112 | for_each_sg(sg, s, nents, i) | ||
| 113 | kmemcheck_mark_initialized(sg_virt(s), s->length); | ||
| 114 | BUG_ON(!valid_dma_direction(dir)); | ||
| 115 | ents = or1k_map_sg(dev, sg, nents, dir, NULL); | ||
| 116 | debug_dma_map_sg(dev, sg, nents, ents, dir); | ||
| 117 | |||
| 118 | return ents; | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
| 122 | int nents, enum dma_data_direction dir) | ||
| 123 | { | ||
| 124 | BUG_ON(!valid_dma_direction(dir)); | ||
| 125 | debug_dma_unmap_sg(dev, sg, nents, dir); | ||
| 126 | or1k_unmap_sg(dev, sg, nents, dir, NULL); | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
| 130 | size_t offset, size_t size, | ||
| 131 | enum dma_data_direction dir) | ||
| 132 | { | ||
| 133 | dma_addr_t addr; | ||
| 134 | |||
| 135 | kmemcheck_mark_initialized(page_address(page) + offset, size); | ||
| 136 | BUG_ON(!valid_dma_direction(dir)); | ||
| 137 | addr = or1k_map_page(dev, page, offset, size, dir, NULL); | ||
| 138 | debug_dma_map_page(dev, page, offset, size, dir, addr, false); | ||
| 139 | |||
| 140 | return addr; | ||
| 141 | } | ||
| 142 | |||
| 143 | static inline void dma_unmap_page(struct device *dev, dma_addr_t addr, | ||
| 144 | size_t size, enum dma_data_direction dir) | ||
| 145 | { | ||
| 146 | BUG_ON(!valid_dma_direction(dir)); | ||
| 147 | or1k_unmap_page(dev, addr, size, dir, NULL); | ||
| 148 | debug_dma_unmap_page(dev, addr, size, dir, true); | ||
| 149 | } | ||
| 150 | |||
| 101 | static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, | 151 | static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, |
| 102 | size_t size, | 152 | size_t size, |
| 103 | enum dma_data_direction dir) | 153 | enum dma_data_direction dir) |
| @@ -119,7 +169,12 @@ static inline void dma_sync_single_for_device(struct device *dev, | |||
| 119 | static inline int dma_supported(struct device *dev, u64 dma_mask) | 169 | static inline int dma_supported(struct device *dev, u64 dma_mask) |
| 120 | { | 170 | { |
| 121 | /* Support 32 bit DMA mask exclusively */ | 171 | /* Support 32 bit DMA mask exclusively */ |
| 122 | return dma_mask == 0xffffffffULL; | 172 | return dma_mask == DMA_BIT_MASK(32); |
| 173 | } | ||
| 174 | |||
| 175 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
| 176 | { | ||
| 177 | return 0; | ||
| 123 | } | 178 | } |
| 124 | 179 | ||
| 125 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | 180 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) |
diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h index 54a5c50132e3..b79c2b19afbe 100644 --- a/arch/openrisc/include/asm/sigcontext.h +++ b/arch/openrisc/include/asm/sigcontext.h | |||
| @@ -23,16 +23,11 @@ | |||
| 23 | 23 | ||
| 24 | /* This struct is saved by setup_frame in signal.c, to keep the current | 24 | /* This struct is saved by setup_frame in signal.c, to keep the current |
| 25 | context while a signal handler is executed. It's restored by sys_sigreturn. | 25 | context while a signal handler is executed. It's restored by sys_sigreturn. |
| 26 | |||
| 27 | To keep things simple, we use pt_regs here even though normally you just | ||
| 28 | specify the list of regs to save. Then we can use copy_from_user on the | ||
| 29 | entire regs instead of a bunch of get_user's as well... | ||
| 30 | */ | 26 | */ |
| 31 | 27 | ||
| 32 | struct sigcontext { | 28 | struct sigcontext { |
| 33 | struct pt_regs regs; /* needs to be first */ | 29 | struct user_regs_struct regs; /* needs to be first */ |
| 34 | unsigned long oldmask; | 30 | unsigned long oldmask; |
| 35 | unsigned long usp; /* usp before stacking this gunk on it */ | ||
| 36 | }; | 31 | }; |
| 37 | 32 | ||
| 38 | #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ | 33 | #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ |
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c index 968d3ee477e3..f1c8ee2895d0 100644 --- a/arch/openrisc/kernel/dma.c +++ b/arch/openrisc/kernel/dma.c | |||
| @@ -154,6 +154,33 @@ void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, | |||
| 154 | /* Nothing special to do here... */ | 154 | /* Nothing special to do here... */ |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | int or1k_map_sg(struct device *dev, struct scatterlist *sg, | ||
| 158 | int nents, enum dma_data_direction dir, | ||
| 159 | struct dma_attrs *attrs) | ||
| 160 | { | ||
| 161 | struct scatterlist *s; | ||
| 162 | int i; | ||
| 163 | |||
| 164 | for_each_sg(sg, s, nents, i) { | ||
| 165 | s->dma_address = or1k_map_page(dev, sg_page(s), s->offset, | ||
| 166 | s->length, dir, NULL); | ||
| 167 | } | ||
| 168 | |||
| 169 | return nents; | ||
| 170 | } | ||
| 171 | |||
| 172 | void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
| 173 | int nents, enum dma_data_direction dir, | ||
| 174 | struct dma_attrs *attrs) | ||
| 175 | { | ||
| 176 | struct scatterlist *s; | ||
| 177 | int i; | ||
| 178 | |||
| 179 | for_each_sg(sg, s, nents, i) { | ||
| 180 | or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 157 | void or1k_sync_single_for_cpu(struct device *dev, | 184 | void or1k_sync_single_for_cpu(struct device *dev, |
| 158 | dma_addr_t dma_handle, size_t size, | 185 | dma_addr_t dma_handle, size_t size, |
| 159 | enum dma_data_direction dir) | 186 | enum dma_data_direction dir) |
| @@ -187,5 +214,4 @@ static int __init dma_init(void) | |||
| 187 | 214 | ||
| 188 | return 0; | 215 | return 0; |
| 189 | } | 216 | } |
| 190 | |||
| 191 | fs_initcall(dma_init); | 217 | fs_initcall(dma_init); |
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 5f759c76834e..95207ab0c99e 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c | |||
| @@ -52,31 +52,25 @@ struct rt_sigframe { | |||
| 52 | static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | 52 | static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) |
| 53 | { | 53 | { |
| 54 | unsigned int err = 0; | 54 | unsigned int err = 0; |
| 55 | unsigned long old_usp; | ||
| 56 | 55 | ||
| 57 | /* Alwys make any pending restarted system call return -EINTR */ | 56 | /* Alwys make any pending restarted system call return -EINTR */ |
| 58 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 57 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 59 | 58 | ||
| 60 | /* restore the regs from &sc->regs (same as sc, since regs is first) | 59 | /* |
| 60 | * Restore the regs from &sc->regs. | ||
| 61 | * (sc is already checked for VERIFY_READ since the sigframe was | 61 | * (sc is already checked for VERIFY_READ since the sigframe was |
| 62 | * checked in sys_sigreturn previously) | 62 | * checked in sys_sigreturn previously) |
| 63 | */ | 63 | */ |
| 64 | 64 | if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long))) | |
| 65 | if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) | 65 | goto badframe; |
| 66 | if (__copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long))) | ||
| 67 | goto badframe; | ||
| 68 | if (__copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long))) | ||
| 66 | goto badframe; | 69 | goto badframe; |
| 67 | 70 | ||
| 68 | /* make sure the SM-bit is cleared so user-mode cannot fool us */ | 71 | /* make sure the SM-bit is cleared so user-mode cannot fool us */ |
| 69 | regs->sr &= ~SPR_SR_SM; | 72 | regs->sr &= ~SPR_SR_SM; |
| 70 | 73 | ||
| 71 | /* restore the old USP as it was before we stacked the sc etc. | ||
| 72 | * (we cannot just pop the sigcontext since we aligned the sp and | ||
| 73 | * stuff after pushing it) | ||
| 74 | */ | ||
| 75 | |||
| 76 | err |= __get_user(old_usp, &sc->usp); | ||
| 77 | |||
| 78 | regs->sp = old_usp; | ||
| 79 | |||
| 80 | /* TODO: the other ports use regs->orig_XX to disable syscall checks | 74 | /* TODO: the other ports use regs->orig_XX to disable syscall checks |
| 81 | * after this completes, but we don't use that mechanism. maybe we can | 75 | * after this completes, but we don't use that mechanism. maybe we can |
| 82 | * use it now ? | 76 | * use it now ? |
| @@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, | |||
| 137 | unsigned long mask) | 131 | unsigned long mask) |
| 138 | { | 132 | { |
| 139 | int err = 0; | 133 | int err = 0; |
| 140 | unsigned long usp = regs->sp; | ||
| 141 | 134 | ||
| 142 | /* copy the regs. they are first in sc so we can use sc directly */ | 135 | /* copy the regs */ |
| 143 | 136 | ||
| 144 | err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); | 137 | err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); |
| 138 | err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long)); | ||
| 139 | err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); | ||
| 145 | 140 | ||
| 146 | /* then some other stuff */ | 141 | /* then some other stuff */ |
| 147 | 142 | ||
| 148 | err |= __put_user(mask, &sc->oldmask); | 143 | err |= __put_user(mask, &sc->oldmask); |
| 149 | 144 | ||
| 150 | err |= __put_user(usp, &sc->usp); | ||
| 151 | |||
| 152 | return err; | 145 | return err; |
| 153 | } | 146 | } |
| 154 | 147 | ||
