diff options
author | Aaron Wu <aaron.wu@analog.com> | 2014-08-06 23:43:49 -0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-08-19 14:53:10 -0400 |
commit | 02f8a24e7b1c253ee37edc684200c11300de23f9 (patch) | |
tree | 14298126df14c0a3ff697305884ef44d16de3810 | |
parent | bd8898db3e03147d9d7ddd48876fb3f3bcbab6c1 (diff) |
mtd: gpio_flash: handle case where offset + len exceeds the window size
Fix the bug in handling gpio flash read/write when offset + len
from MTD exceeds the window size
Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
[Brian: made some commentary edits. Also note that the BUG_ON() was
provably false for all non-negative inputs (since x % y <= x), so we
dropped it.]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r-- | drivers/mtd/maps/gpio-addr-flash.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index a4c477b9fdd6..2fb346091af2 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -99,22 +99,28 @@ static map_word gf_read(struct map_info *map, unsigned long ofs) | |||
99 | * @from: flash offset to copy from | 99 | * @from: flash offset to copy from |
100 | * @len: how much to copy | 100 | * @len: how much to copy |
101 | * | 101 | * |
102 | * We rely on the MTD layer to chunk up copies such that a single request here | 102 | * The "from" region may straddle more than one window, so toggle the GPIOs for |
103 | * will not cross a window size. This allows us to only wiggle the GPIOs once | 103 | * each window region before reading its data. |
104 | * before falling back to a normal memcpy. Reading the higher layer code shows | ||
105 | * that this is indeed the case, but add a BUG_ON() to future proof. | ||
106 | */ | 104 | */ |
107 | static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) | 105 | static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) |
108 | { | 106 | { |
109 | struct async_state *state = gf_map_info_to_state(map); | 107 | struct async_state *state = gf_map_info_to_state(map); |
110 | 108 | ||
111 | gf_set_gpios(state, from); | 109 | int this_len; |
112 | 110 | ||
113 | /* BUG if operation crosses the win_size */ | 111 | while (len) { |
114 | BUG_ON(!((from + len) % state->win_size <= (from + len))); | 112 | if ((from % state->win_size) + len > state->win_size) |
113 | this_len = state->win_size - (from % state->win_size); | ||
114 | else | ||
115 | this_len = len; | ||
115 | 116 | ||
116 | /* operation does not cross the win_size, so one shot it */ | 117 | gf_set_gpios(state, from); |
117 | memcpy_fromio(to, map->virt + (from % state->win_size), len); | 118 | memcpy_fromio(to, map->virt + (from % state->win_size), |
119 | this_len); | ||
120 | len -= this_len; | ||
121 | from += this_len; | ||
122 | to += this_len; | ||
123 | } | ||
118 | } | 124 | } |
119 | 125 | ||
120 | /** | 126 | /** |
@@ -147,13 +153,21 @@ static void gf_copy_to(struct map_info *map, unsigned long to, | |||
147 | { | 153 | { |
148 | struct async_state *state = gf_map_info_to_state(map); | 154 | struct async_state *state = gf_map_info_to_state(map); |
149 | 155 | ||
150 | gf_set_gpios(state, to); | 156 | int this_len; |
157 | |||
158 | while (len) { | ||
159 | if ((to % state->win_size) + len > state->win_size) | ||
160 | this_len = state->win_size - (to % state->win_size); | ||
161 | else | ||
162 | this_len = len; | ||
151 | 163 | ||
152 | /* BUG if operation crosses the win_size */ | 164 | gf_set_gpios(state, to); |
153 | BUG_ON(!((to + len) % state->win_size <= (to + len))); | 165 | memcpy_toio(map->virt + (to % state->win_size), from, len); |
154 | 166 | ||
155 | /* operation does not cross the win_size, so one shot it */ | 167 | len -= this_len; |
156 | memcpy_toio(map->virt + (to % state->win_size), from, len); | 168 | to += this_len; |
169 | from += this_len; | ||
170 | } | ||
157 | } | 171 | } |
158 | 172 | ||
159 | static const char * const part_probe_types[] = { | 173 | static const char * const part_probe_types[] = { |