initial import
[ps3linux_kernel_patches_317.git] / 0010-ps3stor-multiple-regions.patch
blob10d29f4eafc295d7103ff9350d33b83ab447bd3f
1 --- a/arch/powerpc/include/asm/ps3stor.h 2012-01-03 19:41:27.000000000 +0100
2 +++ b/arch/powerpc/include/asm/ps3stor.h 2012-01-05 16:38:31.006804326 +0100
3 @@ -30,6 +30,7 @@
4 unsigned int id;
5 u64 start;
6 u64 size;
7 + u64 flags;
8 };
10 struct ps3_storage_device {
11 @@ -50,7 +51,6 @@
13 unsigned int num_regions;
14 unsigned long accessible_regions;
15 - unsigned int region_idx; /* first accessible region */
16 struct ps3_storage_region regions[0]; /* Must be last */
19 @@ -62,8 +62,8 @@
20 extern int ps3stor_setup(struct ps3_storage_device *dev,
21 irq_handler_t handler);
22 extern void ps3stor_teardown(struct ps3_storage_device *dev);
23 -extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
24 - u64 start_sector, u64 sectors,
25 +extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, unsigned int region_idx,
26 + u64 start_sector, u64 sectors, u64 flags,
27 int write);
28 extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
29 u64 arg1, u64 arg2, u64 arg3, u64 arg4);
30 --- a/drivers/ps3/ps3stor_lib.c 2012-01-05 16:42:51.670823329 +0100
31 +++ b/drivers/ps3/ps3stor_lib.c 2012-01-05 16:44:22.208906179 +0100
32 @@ -101,9 +101,8 @@
33 "%s:%u: checking accessibility of region %u\n",
34 __func__, __LINE__, i);
36 - dev->region_idx = i;
37 - res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
38 - 0);
39 + res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, i, 0, 1,
40 + dev->regions[i].flags, 0);
41 if (res) {
42 dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
43 "region %u is not accessible\n", __func__,
44 @@ -115,6 +114,10 @@
45 __func__, __LINE__, i);
46 set_bit(i, &dev->accessible_regions);
48 + dev_info(&dev->sbd.core,
49 + "accessible region %u start %llu size %llu\n",
50 + i, dev->regions[i].start, dev->regions[i].size);
52 /* We can access at least one region */
53 error = 0;
55 @@ -124,14 +127,8 @@
56 n = hweight_long(dev->accessible_regions);
57 if (n > 1)
58 dev_info(&dev->sbd.core,
59 - "%s:%u: %lu accessible regions found. Only the first "
60 - "one will be used\n",
61 + "%s:%u: %lu accessible regions found\n",
62 __func__, __LINE__, n);
63 - dev->region_idx = __ffs(dev->accessible_regions);
64 - dev_info(&dev->sbd.core,
65 - "First accessible region has index %u start %llu size %llu\n",
66 - dev->region_idx, dev->regions[dev->region_idx].start,
67 - dev->regions[dev->region_idx].size);
69 return 0;
71 @@ -265,17 +262,19 @@
72 * ps3stor_read_write_sectors - read/write from/to a storage device
73 * @dev: Pointer to a struct ps3_storage_device
74 * @lpar: HV logical partition address
75 + * @region_idx: Region index
76 * @start_sector: First sector to read/write
77 * @sectors: Number of sectors to read/write
78 + * @flags: Flags
79 * @write: Flag indicating write (non-zero) or read (zero)
81 * Returns 0 for success, -1 in case of failure to submit the command, or
82 * an LV1 status value in case of other errors
84 -u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
85 - u64 start_sector, u64 sectors, int write)
86 +u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, unsigned int region_idx,
87 + u64 start_sector, u64 sectors, u64 flags, int write)
89 - unsigned int region_id = dev->regions[dev->region_idx].id;
90 + unsigned int region_id = dev->regions[region_idx].id;
91 const char *op = write ? "write" : "read";
92 int res;
94 @@ -284,10 +283,10 @@
96 init_completion(&dev->done);
97 res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
98 - start_sector, sectors, 0, lpar,
99 + start_sector, sectors, flags, lpar,
100 &dev->tag)
101 : lv1_storage_read(dev->sbd.dev_id, region_id,
102 - start_sector, sectors, 0, lpar,
103 + start_sector, sectors, flags, lpar,
104 &dev->tag);
105 if (res) {
106 dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
107 --- a/drivers/block/ps3disk.c 2013-02-14 11:22:05.716017676 +0100
108 +++ b/drivers/block/ps3disk.c 2013-02-14 11:19:47.200033102 +0100
109 @@ -32,7 +32,8 @@
111 #define BOUNCE_SIZE (64*1024)
113 -#define PS3DISK_MAX_DISKS 16
114 +#define PS3DISK_MAX_NUM_REGS 8
116 #define PS3DISK_MINORS 16
119 @@ -41,12 +42,13 @@
121 struct ps3disk_private {
122 spinlock_t lock; /* Request queue spinlock */
123 - struct request_queue *queue;
124 - struct gendisk *gendisk;
125 unsigned int blocking_factor;
126 struct request *req;
127 u64 raw_capacity;
128 unsigned char model[ATA_ID_PROD_LEN+1];
129 + struct gendisk *gendisk[PS3DISK_MAX_NUM_REGS];
130 + struct request_queue *queue[PS3DISK_MAX_NUM_REGS];
131 + int next_queue;
135 @@ -88,6 +90,13 @@
136 .owner = THIS_MODULE,
139 +static unsigned int region_flags[] =
141 + 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
143 +module_param_array(region_flags, uint, NULL, S_IRUGO);
144 +MODULE_PARM_DESC(region_flags, "Region flags");
147 static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
148 struct request *req, int gather)
149 @@ -126,7 +135,9 @@
150 int write = rq_data_dir(req), res;
151 const char *op = write ? "write" : "read";
152 u64 start_sector, sectors;
153 - unsigned int region_id = dev->regions[dev->region_idx].id;
154 + unsigned int region_idx = MINOR(disk_devt(req->rq_disk)) / PS3DISK_MINORS;
155 + unsigned int region_id = dev->regions[region_idx].id;
156 + unsigned int region_flags = dev->regions[region_idx].flags;
158 #ifdef DEBUG
159 unsigned int n = 0;
160 @@ -149,11 +160,11 @@
161 ps3disk_scatter_gather(dev, req, 1);
163 res = lv1_storage_write(dev->sbd.dev_id, region_id,
164 - start_sector, sectors, 0,
165 + start_sector, sectors, region_flags,
166 dev->bounce_lpar, &dev->tag);
167 } else {
168 res = lv1_storage_read(dev->sbd.dev_id, region_id,
169 - start_sector, sectors, 0,
170 + start_sector, sectors, region_flags,
171 dev->bounce_lpar, &dev->tag);
173 if (res) {
174 @@ -232,6 +243,8 @@
175 int res, read, error;
176 u64 tag, status;
177 const char *op;
178 + struct request_queue *q;
179 + int old_queue;
181 res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
183 @@ -279,7 +292,20 @@
184 spin_lock(&priv->lock);
185 __blk_end_request_all(req, error);
186 priv->req = NULL;
187 - ps3disk_do_request(dev, priv->queue);
188 + old_queue = priv->next_queue;
189 + do {
190 + q = priv->queue[priv->next_queue];
192 + priv->next_queue++;
193 + if (priv->next_queue >= dev->num_regions)
194 + priv->next_queue = 0;
196 + if (q) {
197 + ps3disk_do_request(dev, q);
198 + if (priv->req)
199 + break;
201 + } while (old_queue != priv->next_queue);
202 spin_unlock(&priv->lock);
204 return IRQ_HANDLED;
205 @@ -397,19 +423,17 @@
206 return 0;
209 -static unsigned long ps3disk_mask;
211 -static DEFINE_MUTEX(ps3disk_mask_mutex);
213 static int ps3disk_probe(struct ps3_system_bus_device *_dev)
215 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
216 struct ps3disk_private *priv;
217 int error;
218 - unsigned int devidx;
219 + unsigned int regidx, devidx;
220 struct request_queue *queue;
221 struct gendisk *gendisk;
223 + BUG_ON(dev->num_regions > PS3DISK_MAX_NUM_REGS);
225 if (dev->blk_size < 512) {
226 dev_err(&dev->sbd.core,
227 "%s:%u: cannot handle block size %llu\n", __func__,
228 @@ -417,18 +441,6 @@
229 return -EINVAL;
232 - BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
233 - mutex_lock(&ps3disk_mask_mutex);
234 - devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
235 - if (devidx >= PS3DISK_MAX_DISKS) {
236 - dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
237 - __LINE__);
238 - mutex_unlock(&ps3disk_mask_mutex);
239 - return -ENOSPC;
241 - __set_bit(devidx, &ps3disk_mask);
242 - mutex_unlock(&ps3disk_mask_mutex);
244 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
245 if (!priv) {
246 error = -ENOMEM;
247 @@ -445,67 +457,85 @@
248 goto fail_free_priv;
251 + for (regidx = 0; regidx < dev->num_regions; regidx++)
252 + dev->regions[regidx].flags = region_flags[regidx];
254 error = ps3stor_setup(dev, ps3disk_interrupt);
255 if (error)
256 goto fail_free_bounce;
258 ps3disk_identify(dev);
260 - queue = blk_init_queue(ps3disk_request, &priv->lock);
261 - if (!queue) {
262 - dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
263 - __func__, __LINE__);
264 - error = -ENOMEM;
265 - goto fail_teardown;
267 + for (devidx = 0; devidx < dev->num_regions; devidx++)
269 + if (test_bit(devidx, &dev->accessible_regions) == 0)
270 + continue;
272 - priv->queue = queue;
273 - queue->queuedata = dev;
274 + queue = blk_init_queue(ps3disk_request, &priv->lock);
275 + if (!queue) {
276 + dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
277 + __func__, __LINE__);
278 + error = -ENOMEM;
279 + goto fail_cleanup;
282 - blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
283 + priv->queue[devidx] = queue;
284 + queue->queuedata = dev;
286 - blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
287 - blk_queue_segment_boundary(queue, -1UL);
288 - blk_queue_dma_alignment(queue, dev->blk_size-1);
289 - blk_queue_logical_block_size(queue, dev->blk_size);
290 + blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
292 - blk_queue_flush(queue, REQ_FLUSH);
293 + blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
294 + blk_queue_segment_boundary(queue, -1UL);
295 + blk_queue_dma_alignment(queue, dev->blk_size-1);
296 + blk_queue_logical_block_size(queue, dev->blk_size);
298 + blk_queue_flush(queue, REQ_FLUSH);
300 + blk_queue_max_segments(queue, -1);
301 + blk_queue_max_segment_size(queue, dev->bounce_size);
303 + gendisk = alloc_disk(PS3DISK_MINORS);
304 + if (!gendisk) {
305 + dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
306 + __LINE__);
307 + error = -ENOMEM;
308 + goto fail_cleanup;
311 - blk_queue_max_segments(queue, -1);
312 - blk_queue_max_segment_size(queue, dev->bounce_size);
313 + priv->gendisk[devidx] = gendisk;
314 + gendisk->major = ps3disk_major;
315 + gendisk->first_minor = devidx * PS3DISK_MINORS;
316 + gendisk->fops = &ps3disk_fops;
317 + gendisk->queue = queue;
318 + gendisk->private_data = dev;
319 + gendisk->driverfs_dev = &dev->sbd.core;
320 + snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
321 + devidx+'a');
322 + priv->blocking_factor = dev->blk_size >> 9;
323 + set_capacity(gendisk,
324 + dev->regions[devidx].size*priv->blocking_factor);
326 + dev_info(&dev->sbd.core,
327 + "%s is a %s (%llu MiB total, %lu MiB region)\n",
328 + gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
329 + get_capacity(gendisk) >> 11);
331 - gendisk = alloc_disk(PS3DISK_MINORS);
332 - if (!gendisk) {
333 - dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
334 - __LINE__);
335 - error = -ENOMEM;
336 - goto fail_cleanup_queue;
337 + add_disk(gendisk);
340 - priv->gendisk = gendisk;
341 - gendisk->major = ps3disk_major;
342 - gendisk->first_minor = devidx * PS3DISK_MINORS;
343 - gendisk->fops = &ps3disk_fops;
344 - gendisk->queue = queue;
345 - gendisk->private_data = dev;
346 - gendisk->driverfs_dev = &dev->sbd.core;
347 - snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
348 - devidx+'a');
349 - priv->blocking_factor = dev->blk_size >> 9;
350 - set_capacity(gendisk,
351 - dev->regions[dev->region_idx].size*priv->blocking_factor);
353 - dev_info(&dev->sbd.core,
354 - "%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n",
355 - gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
356 - get_capacity(gendisk) >> 11);
358 - add_disk(gendisk);
359 return 0;
361 -fail_cleanup_queue:
362 - blk_cleanup_queue(queue);
363 -fail_teardown:
364 +fail_cleanup:
365 + for (devidx = 0; devidx < dev->num_regions; devidx++)
367 + if (priv->gendisk[devidx]) {
368 + del_gendisk(priv->gendisk[devidx]);
369 + put_disk(priv->gendisk[devidx]);
372 + if (priv->queue[devidx])
373 + blk_cleanup_queue(priv->queue[devidx]);
375 ps3stor_teardown(dev);
376 fail_free_bounce:
377 kfree(dev->bounce_buf);
378 @@ -513,9 +543,6 @@
379 kfree(priv);
380 ps3_system_bus_set_drvdata(_dev, NULL);
381 fail:
382 - mutex_lock(&ps3disk_mask_mutex);
383 - __clear_bit(devidx, &ps3disk_mask);
384 - mutex_unlock(&ps3disk_mask_mutex);
385 return error;
388 @@ -523,14 +550,19 @@
390 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
391 struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
392 + unsigned int devidx;
394 + for (devidx = 0; devidx < dev->num_regions; devidx++)
396 + if (priv->gendisk[devidx]) {
397 + del_gendisk(priv->gendisk[devidx]);
398 + put_disk(priv->gendisk[devidx]);
401 + if (priv->queue[devidx])
402 + blk_cleanup_queue(priv->queue[devidx]);
405 - mutex_lock(&ps3disk_mask_mutex);
406 - __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
407 - &ps3disk_mask);
408 - mutex_unlock(&ps3disk_mask_mutex);
409 - del_gendisk(priv->gendisk);
410 - blk_cleanup_queue(priv->queue);
411 - put_disk(priv->gendisk);
412 dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
413 ps3disk_sync_cache(dev);
414 ps3stor_teardown(dev);
415 --- a/drivers/scsi/ps3rom.c 2012-01-03 19:41:27.000000000 +0100
416 +++ b/drivers/scsi/ps3rom.c 2012-01-05 16:38:58.103891705 +0100
417 @@ -72,6 +72,14 @@
421 +static unsigned int region_flags[] =
423 + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
425 +module_param_array(region_flags, uint, NULL, S_IRUGO);
426 +MODULE_PARM_DESC(region_flags, "Region flags");
429 static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
431 struct ps3rom_private *priv = shost_priv(scsi_dev->host);
432 @@ -172,12 +180,13 @@
433 u32 sectors)
435 int res;
436 + unsigned int region_idx = 0;
438 dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
439 __func__, __LINE__, sectors, start_sector);
441 res = lv1_storage_read(dev->sbd.dev_id,
442 - dev->regions[dev->region_idx].id, start_sector,
443 + dev->regions[region_idx].id, start_sector,
444 sectors, 0, dev->bounce_lpar, &dev->tag);
445 if (res) {
446 dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
447 @@ -193,6 +202,7 @@
448 u32 sectors)
450 int res;
451 + unsigned int region_idx = 0;
453 dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
454 __func__, __LINE__, sectors, start_sector);
455 @@ -200,7 +210,7 @@
456 scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
458 res = lv1_storage_write(dev->sbd.dev_id,
459 - dev->regions[dev->region_idx].id, start_sector,
460 + dev->regions[region_idx].id, start_sector,
461 sectors, 0, dev->bounce_lpar, &dev->tag);
462 if (res) {
463 dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
464 @@ -362,6 +372,7 @@
466 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
467 int error;
468 + unsigned int regidx;
469 struct Scsi_Host *host;
470 struct ps3rom_private *priv;
472 @@ -377,6 +388,9 @@
473 if (!dev->bounce_buf)
474 return -ENOMEM;
476 + for (regidx = 0; regidx < dev->num_regions; regidx++)
477 + dev->regions[regidx].flags = region_flags[regidx];
479 error = ps3stor_setup(dev, ps3rom_interrupt);
480 if (error)
481 goto fail_free_bounce;