diff options
author | Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> | 2009-06-10 00:39:08 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-15 02:47:27 -0400 |
commit | 42e27bfc4bfa42bd905e53be93d862b8e3d80a00 (patch) | |
tree | 9283cbfcb5507b184f8ab6b5920ec594919e110d /drivers/char | |
parent | 6bd57f2e5db408e0dfdb3bf052d58c4e7b18ed3c (diff) |
ps3flash: Always read chunks of 256 KiB, and cache them
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ps3flash.c | 47 |
1 files changed, 17 insertions, 30 deletions
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c index d884d31491d2..f424d394a286 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c | |||
@@ -41,10 +41,11 @@ struct ps3flash_private { | |||
41 | static struct ps3_storage_device *ps3flash_dev; | 41 | static struct ps3_storage_device *ps3flash_dev; |
42 | 42 | ||
43 | static int ps3flash_read_write_sectors(struct ps3_storage_device *dev, | 43 | static int ps3flash_read_write_sectors(struct ps3_storage_device *dev, |
44 | u64 lpar, u64 start_sector, u64 sectors, | 44 | u64 start_sector, int write) |
45 | int write) | ||
46 | { | 45 | { |
47 | u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors, | 46 | struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
47 | u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, | ||
48 | start_sector, priv->chunk_sectors, | ||
48 | write); | 49 | write); |
49 | if (res) { | 50 | if (res) { |
50 | dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__, | 51 | dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__, |
@@ -62,8 +63,7 @@ static int ps3flash_writeback(struct ps3_storage_device *dev) | |||
62 | if (!priv->dirty || priv->tag < 0) | 63 | if (!priv->dirty || priv->tag < 0) |
63 | return 0; | 64 | return 0; |
64 | 65 | ||
65 | res = ps3flash_read_write_sectors(dev, dev->bounce_lpar, priv->tag, | 66 | res = ps3flash_read_write_sectors(dev, priv->tag, 1); |
66 | priv->chunk_sectors, 1); | ||
67 | if (res) | 67 | if (res) |
68 | return res; | 68 | return res; |
69 | 69 | ||
@@ -71,17 +71,12 @@ static int ps3flash_writeback(struct ps3_storage_device *dev) | |||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector, | 74 | static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector) |
75 | u64 sectors) | ||
76 | { | 75 | { |
77 | struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); | 76 | struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
78 | unsigned int tag, offset; | ||
79 | u64 lpar; | ||
80 | int res; | 77 | int res; |
81 | 78 | ||
82 | offset = start_sector % priv->chunk_sectors; | 79 | if (start_sector == priv->tag) |
83 | tag = start_sector - offset; | ||
84 | if (tag == priv->tag) | ||
85 | return 0; | 80 | return 0; |
86 | 81 | ||
87 | res = ps3flash_writeback(dev); | 82 | res = ps3flash_writeback(dev); |
@@ -90,15 +85,11 @@ static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector, | |||
90 | 85 | ||
91 | priv->tag = -1; | 86 | priv->tag = -1; |
92 | 87 | ||
93 | lpar = dev->bounce_lpar + offset * dev->blk_size; | 88 | res = ps3flash_read_write_sectors(dev, start_sector, 0); |
94 | res = ps3flash_read_write_sectors(dev, lpar, start_sector, sectors, 0); | ||
95 | if (res) | 89 | if (res) |
96 | return res; | 90 | return res; |
97 | 91 | ||
98 | /* We don't bother caching reads smaller than the chunk size */ | 92 | priv->tag = start_sector; |
99 | if (sectors == priv->chunk_sectors) | ||
100 | priv->tag = tag; | ||
101 | |||
102 | return 0; | 93 | return 0; |
103 | } | 94 | } |
104 | 95 | ||
@@ -134,7 +125,7 @@ static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf, | |||
134 | { | 125 | { |
135 | struct ps3_storage_device *dev = ps3flash_dev; | 126 | struct ps3_storage_device *dev = ps3flash_dev; |
136 | struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); | 127 | struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
137 | u64 size, start_sector, end_sector, offset, sectors; | 128 | u64 size, sector, offset; |
138 | int res; | 129 | int res; |
139 | size_t remaining, n; | 130 | size_t remaining, n; |
140 | const void *src; | 131 | const void *src; |
@@ -154,24 +145,20 @@ static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf, | |||
154 | count = size - *pos; | 145 | count = size - *pos; |
155 | } | 146 | } |
156 | 147 | ||
157 | start_sector = *pos / dev->blk_size; | 148 | sector = *pos / dev->bounce_size * priv->chunk_sectors; |
158 | offset = *pos % dev->bounce_size; | 149 | offset = *pos % dev->bounce_size; |
159 | end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size); | ||
160 | 150 | ||
161 | remaining = count; | 151 | remaining = count; |
162 | do { | 152 | do { |
163 | sectors = min(end_sector - start_sector, | 153 | n = min_t(u64, remaining, dev->bounce_size - offset); |
164 | priv->chunk_sectors - | 154 | src = dev->bounce_buf + offset; |
165 | start_sector % priv->chunk_sectors); | ||
166 | 155 | ||
167 | mutex_lock(&priv->mutex); | 156 | mutex_lock(&priv->mutex); |
168 | 157 | ||
169 | res = ps3flash_fetch(dev, start_sector, sectors); | 158 | res = ps3flash_fetch(dev, sector); |
170 | if (res) | 159 | if (res) |
171 | goto fail; | 160 | goto fail; |
172 | 161 | ||
173 | n = min_t(u64, remaining, dev->bounce_size - offset); | ||
174 | src = dev->bounce_buf + offset; | ||
175 | dev_dbg(&dev->sbd.core, | 162 | dev_dbg(&dev->sbd.core, |
176 | "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n", | 163 | "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n", |
177 | __func__, __LINE__, n, src, userbuf, kernelbuf); | 164 | __func__, __LINE__, n, src, userbuf, kernelbuf); |
@@ -191,7 +178,7 @@ static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf, | |||
191 | 178 | ||
192 | *pos += n; | 179 | *pos += n; |
193 | remaining -= n; | 180 | remaining -= n; |
194 | start_sector += sectors; | 181 | sector += priv->chunk_sectors; |
195 | offset = 0; | 182 | offset = 0; |
196 | } while (remaining > 0); | 183 | } while (remaining > 0); |
197 | 184 | ||
@@ -233,17 +220,17 @@ static ssize_t ps3flash_write(const char __user *userbuf, | |||
233 | remaining = count; | 220 | remaining = count; |
234 | do { | 221 | do { |
235 | n = min_t(u64, remaining, dev->bounce_size - offset); | 222 | n = min_t(u64, remaining, dev->bounce_size - offset); |
223 | dst = dev->bounce_buf + offset; | ||
236 | 224 | ||
237 | mutex_lock(&priv->mutex); | 225 | mutex_lock(&priv->mutex); |
238 | 226 | ||
239 | if (n != dev->bounce_size) | 227 | if (n != dev->bounce_size) |
240 | res = ps3flash_fetch(dev, sector, priv->chunk_sectors); | 228 | res = ps3flash_fetch(dev, sector); |
241 | else if (sector != priv->tag) | 229 | else if (sector != priv->tag) |
242 | res = ps3flash_writeback(dev); | 230 | res = ps3flash_writeback(dev); |
243 | if (res) | 231 | if (res) |
244 | goto fail; | 232 | goto fail; |
245 | 233 | ||
246 | dst = dev->bounce_buf + offset; | ||
247 | dev_dbg(&dev->sbd.core, | 234 | dev_dbg(&dev->sbd.core, |
248 | "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n", | 235 | "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n", |
249 | __func__, __LINE__, n, userbuf, kernelbuf, dst); | 236 | __func__, __LINE__, n, userbuf, kernelbuf, dst); |