aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/ps3flash.c47
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 {
41static struct ps3_storage_device *ps3flash_dev; 41static struct ps3_storage_device *ps3flash_dev;
42 42
43static int ps3flash_read_write_sectors(struct ps3_storage_device *dev, 43static 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
74static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector, 74static 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);