* updated kollision (21.12.1 -> 21.12.2), untested
[t2-trunk.git] / architecture / powerpc64 / package / linux / 0010-ps3stor-multiple-regions.patch
blobee6f85461e2f278ac368be2cfe46dc27ded4f1cd
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # T2 SDE: architecture/powerpc64/package/*/0010-ps3stor-multiple-regions.patch
3 # Copyright (C) 2019 - 2022 The T2 SDE Project
4 #
5 # This Copyright note is generated by scripts/Create-CopyPatch,
6 # more information can be found in the files COPYING and README.
7 #
8 # This patch file is dual-licensed. It is available under the license the
9 # patched project is licensed under, as long as it is an OpenSource license
10 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
11 # of the GNU General Public License version 2 as used by the T2 SDE.
12 # --- T2-COPYRIGHT-NOTE-END ---
14 --- a/arch/powerpc/include/asm/ps3stor.h
15 +++ b/arch/powerpc/include/asm/ps3stor.h
16 @@ -18,6 +18,7 @@ struct ps3_storage_region {
17 unsigned int id;
18 u64 start;
19 u64 size;
20 + u64 flags;
23 struct ps3_storage_device {
24 @@ -38,7 +39,6 @@ struct ps3_storage_device {
26 unsigned int num_regions;
27 unsigned long accessible_regions;
28 - unsigned int region_idx; /* first accessible region */
29 struct ps3_storage_region regions[]; /* Must be last */
32 @@ -50,8 +50,8 @@ static inline struct ps3_storage_device *to_ps3_storage_device(struct device *de
33 extern int ps3stor_setup(struct ps3_storage_device *dev,
34 irq_handler_t handler);
35 extern void ps3stor_teardown(struct ps3_storage_device *dev);
36 -extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
37 - u64 start_sector, u64 sectors,
38 +extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, unsigned int region_idx,
39 + u64 start_sector, u64 sectors, u64 flags,
40 int write);
41 extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
42 u64 arg1, u64 arg2, u64 arg3, u64 arg4);
43 --- linux-5.16/drivers/block/ps3disk.c.vanilla 2022-01-17 19:32:18.187094077 +0100
44 +++ linux-5.16/drivers/block/ps3disk.c 2022-01-17 19:45:20.652134443 +0100
45 @@ -2,6 +2,7 @@
47 * PS3 Disk Storage Driver
49 + * Copyright (C) 2018-2022 René Rebe
50 * Copyright (C) 2007 Sony Computer Entertainment Inc.
51 * Copyright 2007 Sony Corp.
53 @@ -17,24 +18,24 @@
56 #define DEVICE_NAME "ps3disk"
57 +#define BOUNCE_SIZE (64*1024) /* * PS3DISK_MAX_REQS */
59 -#define BOUNCE_SIZE (64*1024)
61 -#define PS3DISK_MAX_DISKS 16
62 +#define PS3DISK_MAX_NUM_REGS 8
63 +#define PS3DISK_MAX_REQS 1 /* 16 */
64 #define PS3DISK_MINORS 16
67 #define PS3DISK_NAME "ps3d%c"
70 struct ps3disk_private {
71 spinlock_t lock; /* Request queue spinlock */
72 - struct blk_mq_tag_set tag_set;
73 - struct gendisk *gendisk;
74 unsigned int blocking_factor;
75 - struct request *req;
76 u64 raw_capacity;
77 + struct request* req[PS3DISK_MAX_REQS];
78 + unsigned req_region[PS3DISK_MAX_REQS];
79 + unsigned next_queue;
80 unsigned char model[ATA_ID_PROD_LEN+1];
81 + struct blk_mq_tag_set tag_set[PS3DISK_MAX_NUM_REGS];
82 + struct gendisk *gendisk[PS3DISK_MAX_NUM_REGS];
86 @@ -76,6 +77,13 @@
87 .owner = THIS_MODULE,
90 +static unsigned int region_flags[] =
92 + 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
93 +};
94 +module_param_array(region_flags, uint, NULL, S_IRUGO);
95 +MODULE_PARM_DESC(region_flags, "Region flags");
98 static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
99 struct request *req, int gather)
100 @@ -98,8 +106,10 @@
101 struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
102 int write = rq_data_dir(req), res;
103 const char *op = write ? "write" : "read";
104 - u64 start_sector, sectors;
105 - unsigned int region_id = dev->regions[dev->region_idx].id;
106 + u64 start_sector, sectors, tag;
107 + unsigned int region_idx = MINOR(disk_devt(req->rq_disk)) / PS3DISK_MINORS;
108 + unsigned int region_id = dev->regions[region_idx].id;
109 + unsigned int region_flags = dev->regions[region_idx].flags;
111 #ifdef DEBUG
112 unsigned int n = 0;
113 @@ -120,22 +130,27 @@
115 if (write) {
116 ps3disk_scatter_gather(dev, req, 1);
118 res = lv1_storage_write(dev->sbd.dev_id, region_id,
119 - start_sector, sectors, 0,
120 - dev->bounce_lpar, &dev->tag);
121 + start_sector, sectors, region_flags,
122 + dev->bounce_lpar, &tag);
123 } else {
124 res = lv1_storage_read(dev->sbd.dev_id, region_id,
125 - start_sector, sectors, 0,
126 - dev->bounce_lpar, &dev->tag);
127 + start_sector, sectors, region_flags,
128 + dev->bounce_lpar, &tag);
130 if (res) {
131 dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
132 __LINE__, op, res);
133 return BLK_STS_IOERR;
136 - priv->req = req;
138 + //printk("tag: %lld\n", tag);
139 + BUG_ON(tag >= PS3DISK_MAX_REQS);
140 + BUG_ON(priv->req[tag]);
142 + priv->req[tag] = req;
143 + priv->req_region[tag] = region_idx;
145 return BLK_STS_OK;
148 @@ -143,20 +158,25 @@
149 struct request *req)
151 struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
152 - u64 res;
153 + u64 res, tag;
155 dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
158 + /* TODO: actual region? */
159 res = lv1_storage_send_device_command(dev->sbd.dev_id,
160 LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
161 - 0, &dev->tag);
162 + 0, &tag);
163 if (res) {
164 dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
165 __func__, __LINE__, res);
166 return BLK_STS_IOERR;
169 - priv->req = req;
171 + //printk("tag: %lld\n", tag);
172 + BUG_ON(tag >= PS3DISK_MAX_REQS);
173 + priv->req[tag] = req;
174 + priv->req_region[tag] = 0;
176 return BLK_STS_OK;
179 @@ -183,11 +203,27 @@
180 struct request_queue *q = hctx->queue;
181 struct ps3_storage_device *dev = q->queuedata;
182 struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
183 + unsigned i;
184 blk_status_t ret;
186 - blk_mq_start_request(bd->rq);
187 + dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
189 + blk_mq_start_request(bd->rq);
191 spin_lock_irq(&priv->lock);
193 + /* find free request tag slot */
194 + for (i = 0; i < PS3DISK_MAX_REQS; ++i) {
195 + if (priv->req[i] == NULL)
196 + break;
198 + /* TODO: re-write to always try w/ HV, as we share among devices */
199 + if (i >= PS3DISK_MAX_REQS) {
200 + spin_unlock_irq(&priv->lock);
201 + blk_mq_stop_hw_queue(hctx);
202 + return BLK_STS_DEV_RESOURCE;
205 ret = ps3disk_do_request(dev, bd->rq);
206 spin_unlock_irq(&priv->lock);
208 @@ -203,26 +239,30 @@
209 blk_status_t error;
210 u64 tag, status;
211 const char *op;
213 + struct request_queue *q;
214 + unsigned last_queue;
215 + unsigned req_region;
217 + priv = ps3_system_bus_get_drvdata(&dev->sbd);
218 + spin_lock(&priv->lock);
220 res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
222 - if (tag != dev->tag)
223 - dev_err(&dev->sbd.core,
224 - "%s:%u: tag mismatch, got %llx, expected %llx\n",
225 - __func__, __LINE__, tag, dev->tag);
227 if (res) {
228 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
229 __func__, __LINE__, res, status);
230 + spin_unlock(&priv->lock);
231 return IRQ_HANDLED;
234 - priv = ps3_system_bus_get_drvdata(&dev->sbd);
235 - req = priv->req;
237 + //printk("int tag: %lld\n", tag);
238 + BUG_ON(tag >= PS3DISK_MAX_REQS);
240 + req = priv->req[tag];
241 if (!req) {
242 dev_dbg(&dev->sbd.core,
243 "%s:%u non-block layer request completed\n", __func__,
244 __LINE__);
245 + spin_unlock(&priv->lock);
246 dev->lv1_status = status;
247 complete(&dev->done);
248 return IRQ_HANDLED;
249 @@ -247,12 +287,29 @@
250 ps3disk_scatter_gather(dev, req, 0);
253 - spin_lock(&priv->lock);
254 - priv->req = NULL;
255 + req_region = priv->req_region[tag];
256 + priv->req[tag] = NULL;
257 blk_mq_end_request(req, error);
258 spin_unlock(&priv->lock);
260 - blk_mq_run_hw_queues(priv->gendisk->queue, true);
262 + blk_mq_run_hw_queues(priv->gendisk[req_region]->queue, true);
263 +#if 0
264 + /* restart other potentially stopped queues */
265 + last_queue = priv->next_queue;
266 + do {
267 + q = priv->gendisk[priv->next_queue]->queue;
269 + priv->next_queue++;
270 + if (priv->next_queue >= dev->num_regions)
271 + priv->next_queue = 0;
273 + if (q && blk_mq_queue_stopped(q)) {
274 + blk_mq_start_stopped_hw_queues(q, true);
275 + break;
277 + } while (last_queue != priv->next_queue);
278 +#endif
280 return IRQ_HANDLED;
283 @@ -368,10 +425,6 @@
284 return 0;
287 -static unsigned long ps3disk_mask;
289 -static DEFINE_MUTEX(ps3disk_mask_mutex);
291 static const struct blk_mq_ops ps3disk_mq_ops = {
292 .queue_rq = ps3disk_queue_rq,
294 @@ -381,10 +434,12 @@
295 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
296 struct ps3disk_private *priv;
297 int error;
298 - unsigned int devidx;
299 + unsigned int regidx, devidx;
300 struct request_queue *queue;
301 struct gendisk *gendisk;
303 + BUG_ON(dev->num_regions > PS3DISK_MAX_NUM_REGS);
305 if (dev->blk_size < 512) {
306 dev_err(&dev->sbd.core,
307 "%s:%u: cannot handle block size %llu\n", __func__,
308 @@ -392,18 +447,6 @@
309 return -EINVAL;
312 - BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
313 - mutex_lock(&ps3disk_mask_mutex);
314 - devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
315 - if (devidx >= PS3DISK_MAX_DISKS) {
316 - dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
317 - __LINE__);
318 - mutex_unlock(&ps3disk_mask_mutex);
319 - return -ENOSPC;
321 - __set_bit(devidx, &ps3disk_mask);
322 - mutex_unlock(&ps3disk_mask_mutex);
324 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
325 if (!priv) {
326 error = -ENOMEM;
327 @@ -420,63 +463,72 @@
328 goto fail_free_priv;
331 + for (regidx = 0; regidx < dev->num_regions; regidx++)
332 + dev->regions[regidx].flags = region_flags[regidx];
334 error = ps3stor_setup(dev, ps3disk_interrupt);
335 if (error)
336 goto fail_free_bounce;
338 ps3disk_identify(dev);
340 - error = blk_mq_alloc_sq_tag_set(&priv->tag_set, &ps3disk_mq_ops, 1,
341 - BLK_MQ_F_SHOULD_MERGE);
342 - if (error)
343 - goto fail_teardown;
345 - gendisk = blk_mq_alloc_disk(&priv->tag_set, dev);
346 - if (IS_ERR(gendisk)) {
347 - dev_err(&dev->sbd.core, "%s:%u: blk_mq_alloc_disk failed\n",
348 - __func__, __LINE__);
349 - error = PTR_ERR(gendisk);
350 - goto fail_free_tag_set;
353 - queue = gendisk->queue;
355 - blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
356 - blk_queue_dma_alignment(queue, dev->blk_size-1);
357 - blk_queue_logical_block_size(queue, dev->blk_size);
359 - blk_queue_write_cache(queue, true, false);
361 - blk_queue_max_segments(queue, -1);
362 - blk_queue_max_segment_size(queue, dev->bounce_size);
364 - priv->gendisk = gendisk;
365 - gendisk->major = ps3disk_major;
366 - gendisk->first_minor = devidx * PS3DISK_MINORS;
367 - gendisk->minors = PS3DISK_MINORS;
368 - gendisk->fops = &ps3disk_fops;
369 - gendisk->private_data = dev;
370 - snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
371 - devidx+'a');
372 - priv->blocking_factor = dev->blk_size >> 9;
373 - set_capacity(gendisk,
374 - dev->regions[dev->region_idx].size*priv->blocking_factor);
376 - dev_info(&dev->sbd.core,
377 - "%s is a %s (%llu MiB total, %llu MiB for OtherOS)\n",
378 - gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
379 - get_capacity(gendisk) >> 11);
381 - error = device_add_disk(&dev->sbd.core, gendisk, NULL);
382 - if (error)
383 - goto fail_cleanup_disk;
385 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
386 + if (test_bit(devidx, &dev->accessible_regions) == 0)
387 + continue;
389 + error = blk_mq_alloc_sq_tag_set(&priv->tag_set[devidx], &ps3disk_mq_ops,
390 + PS3DISK_MAX_REQS,
391 + BLK_MQ_F_SHOULD_MERGE);
392 + if (error)
393 + goto fail_teardown;
395 + gendisk = blk_mq_alloc_disk(&priv->tag_set[devidx], dev);
396 + if (IS_ERR(gendisk)) {
397 + dev_err(&dev->sbd.core, "%s:%u: blk_mq_alloc_disk failed\n",
398 + __func__, __LINE__);
399 + error = PTR_ERR(gendisk);
400 + goto fail_teardown;
402 + queue = gendisk->queue;
403 + priv->gendisk[devidx] = gendisk;
405 + blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
406 + blk_queue_dma_alignment(queue, dev->blk_size-1);
407 + blk_queue_logical_block_size(queue, dev->blk_size);
408 + blk_queue_write_cache(queue, true, false);
409 + blk_queue_max_segments(queue, -1);
410 + blk_queue_max_segment_size(queue, dev->bounce_size);
412 + gendisk->major = ps3disk_major;
413 + gendisk->minors = PS3DISK_MINORS;
414 + gendisk->first_minor = devidx * PS3DISK_MINORS;
415 + gendisk->fops = &ps3disk_fops;
416 + gendisk->queue = queue;
417 + gendisk->private_data = dev;
418 + snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
419 + 'a' + devidx);
420 + priv->blocking_factor = dev->blk_size >> 9;
421 + set_capacity(gendisk,
422 + dev->regions[devidx].size * priv->blocking_factor);
424 + dev_info(&dev->sbd.core,
425 + "%s is a %s (%llu MiB total, %llu MiB region)\n",
426 + gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
427 + get_capacity(gendisk) >> 11);
429 + error = device_add_disk(&dev->sbd.core, gendisk, NULL);
430 + if (error)
431 + goto fail_teardown;
433 return 0;
434 -fail_cleanup_disk:
435 - blk_cleanup_disk(gendisk);
436 -fail_free_tag_set:
437 - blk_mq_free_tag_set(&priv->tag_set);
439 fail_teardown:
440 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
441 + if (priv->gendisk[devidx]) {
442 + del_gendisk(priv->gendisk[devidx]);
443 + blk_cleanup_disk(priv->gendisk[devidx]);
446 ps3stor_teardown(dev);
447 fail_free_bounce:
448 kfree(dev->bounce_buf);
449 @@ -484,9 +536,6 @@
450 kfree(priv);
451 ps3_system_bus_set_drvdata(_dev, NULL);
452 fail:
453 - mutex_lock(&ps3disk_mask_mutex);
454 - __clear_bit(devidx, &ps3disk_mask);
455 - mutex_unlock(&ps3disk_mask_mutex);
456 return error;
459 @@ -494,14 +543,15 @@
461 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
462 struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
463 + unsigned int devidx;
465 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
466 + if (priv->gendisk[devidx]) {
467 + del_gendisk(priv->gendisk[devidx]);
468 + blk_cleanup_disk(priv->gendisk[devidx]);
472 - mutex_lock(&ps3disk_mask_mutex);
473 - __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
474 - &ps3disk_mask);
475 - mutex_unlock(&ps3disk_mask_mutex);
476 - del_gendisk(priv->gendisk);
477 - blk_cleanup_disk(priv->gendisk);
478 - blk_mq_free_tag_set(&priv->tag_set);
479 dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
480 ps3disk_sync_cache(dev);
481 ps3stor_teardown(dev);
482 --- a/drivers/char/ps3flash.c
483 +++ b/drivers/char/ps3flash.c
484 @@ -34,9 +34,10 @@
485 u64 start_sector, int write)
487 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
488 + unsigned int region_idx = 0;
489 u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
490 - start_sector, priv->chunk_sectors,
491 - write);
492 + region_idx, start_sector,
493 + priv->chunk_sectors, 0, write);
494 if (res) {
495 dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
496 __LINE__, write ? "write" : "read", res);
497 @@ -86,8 +87,9 @@
498 static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
500 struct ps3_storage_device *dev = ps3flash_dev;
501 + unsigned int region_idx = 0;
502 return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
503 - dev->regions[dev->region_idx].size*dev->blk_size);
504 + dev->regions[region_idx].size*dev->blk_size);
507 static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
508 @@ -95,6 +97,7 @@
510 struct ps3_storage_device *dev = ps3flash_dev;
511 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
512 + unsigned int region_idx = 0;
513 u64 size, sector, offset;
514 int res;
515 size_t remaining, n;
516 @@ -104,7 +107,7 @@
517 "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
518 __func__, __LINE__, count, *pos, userbuf, kernelbuf);
520 - size = dev->regions[dev->region_idx].size*dev->blk_size;
521 + size = dev->regions[region_idx].size*dev->blk_size;
522 if (*pos >= size || !count)
523 return 0;
525 @@ -164,6 +167,7 @@
527 struct ps3_storage_device *dev = ps3flash_dev;
528 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
529 + unsigned int region_idx = 0;
530 u64 size, sector, offset;
531 int res = 0;
532 size_t remaining, n;
533 @@ -173,7 +177,7 @@
534 "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
535 __func__, __LINE__, count, *pos, userbuf, kernelbuf);
537 - size = dev->regions[dev->region_idx].size*dev->blk_size;
538 + size = dev->regions[region_idx].size*dev->blk_size;
539 if (*pos >= size || !count)
540 return 0;
542 @@ -333,15 +337,16 @@
543 struct ps3flash_private *priv;
544 int error;
545 unsigned long tmp;
546 + unsigned int region_idx = 0;
548 - tmp = dev->regions[dev->region_idx].start*dev->blk_size;
549 + tmp = dev->regions[region_idx].start*dev->blk_size;
550 if (tmp % FLASH_BLOCK_SIZE) {
551 dev_err(&dev->sbd.core,
552 "%s:%u region start %lu is not aligned\n", __func__,
553 __LINE__, tmp);
554 return -EINVAL;
556 - tmp = dev->regions[dev->region_idx].size*dev->blk_size;
557 + tmp = dev->regions[region_idx].size*dev->blk_size;
558 if (tmp % FLASH_BLOCK_SIZE) {
559 dev_err(&dev->sbd.core,
560 "%s:%u region size %lu is not aligned\n", __func__,
561 --- a/drivers/ps3/ps3stor_lib.c
562 +++ b/drivers/ps3/ps3stor_lib.c
563 @@ -90,9 +90,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
564 "%s:%u: checking accessibility of region %u\n",
565 __func__, __LINE__, i);
567 - dev->region_idx = i;
568 - res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
569 - 0);
570 + res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, i, 0, 1,
571 + dev->regions[i].flags, 0);
572 if (res) {
573 dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
574 "region %u is not accessible\n", __func__,
575 @@ -104,6 +103,10 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
576 __func__, __LINE__, i);
577 set_bit(i, &dev->accessible_regions);
579 + dev_info(&dev->sbd.core,
580 + "accessible region %u start %llu size %llu\n",
581 + i, dev->regions[i].start, dev->regions[i].size);
583 /* We can access at least one region */
584 error = 0;
586 @@ -113,14 +116,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
587 n = hweight_long(dev->accessible_regions);
588 if (n > 1)
589 dev_info(&dev->sbd.core,
590 - "%s:%u: %lu accessible regions found. Only the first "
591 - "one will be used\n",
592 + "%s:%u: %lu accessible regions found\n",
593 __func__, __LINE__, n);
594 - dev->region_idx = __ffs(dev->accessible_regions);
595 - dev_info(&dev->sbd.core,
596 - "First accessible region has index %u start %llu size %llu\n",
597 - dev->region_idx, dev->regions[dev->region_idx].start,
598 - dev->regions[dev->region_idx].size);
600 return 0;
602 @@ -254,17 +251,19 @@ EXPORT_SYMBOL_GPL(ps3stor_teardown);
603 * ps3stor_read_write_sectors - read/write from/to a storage device
604 * @dev: Pointer to a struct ps3_storage_device
605 * @lpar: HV logical partition address
606 + * @region_idx: Region index
607 * @start_sector: First sector to read/write
608 * @sectors: Number of sectors to read/write
609 + * @flags: Flags
610 * @write: Flag indicating write (non-zero) or read (zero)
612 * Returns 0 for success, -1 in case of failure to submit the command, or
613 * an LV1 status value in case of other errors
615 -u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
616 - u64 start_sector, u64 sectors, int write)
617 +u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, unsigned int region_idx,
618 + u64 start_sector, u64 sectors, u64 flags, int write)
620 - unsigned int region_id = dev->regions[dev->region_idx].id;
621 + unsigned int region_id = dev->regions[region_idx].id;
622 const char *op = write ? "write" : "read";
623 int res;
625 @@ -273,10 +272,10 @@ u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
627 init_completion(&dev->done);
628 res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
629 - start_sector, sectors, 0, lpar,
630 + start_sector, sectors, flags, lpar,
631 &dev->tag)
632 : lv1_storage_read(dev->sbd.dev_id, region_id,
633 - start_sector, sectors, 0, lpar,
634 + start_sector, sectors, flags, lpar,
635 &dev->tag);
636 if (res) {
637 dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
638 --- a/drivers/scsi/ps3rom.c
639 +++ b/drivers/scsi/ps3rom.c
640 @@ -61,6 +61,14 @@ enum lv1_atapi_in_out {
644 +static unsigned int region_flags[] =
646 + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
648 +module_param_array(region_flags, uint, NULL, S_IRUGO);
649 +MODULE_PARM_DESC(region_flags, "Region flags");
652 static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
654 struct ps3rom_private *priv = shost_priv(scsi_dev->host);
655 @@ -161,12 +169,13 @@ static int ps3rom_read_request(struct ps3_storage_device *dev,
656 u32 sectors)
658 int res;
659 + unsigned int region_idx = 0;
661 dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
662 __func__, __LINE__, sectors, start_sector);
664 res = lv1_storage_read(dev->sbd.dev_id,
665 - dev->regions[dev->region_idx].id, start_sector,
666 + dev->regions[region_idx].id, start_sector,
667 sectors, 0, dev->bounce_lpar, &dev->tag);
668 if (res) {
669 dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
670 @@ -182,6 +191,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
671 u32 sectors)
673 int res;
674 + unsigned int region_idx = 0;
676 dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
677 __func__, __LINE__, sectors, start_sector);
678 @@ -189,7 +199,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
679 scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
681 res = lv1_storage_write(dev->sbd.dev_id,
682 - dev->regions[dev->region_idx].id, start_sector,
683 + dev->regions[region_idx].id, start_sector,
684 sectors, 0, dev->bounce_lpar, &dev->tag);
685 if (res) {
686 dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
687 @@ -345,6 +355,7 @@ static int ps3rom_probe(struct ps3_system_bus_device *_dev)
689 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
690 int error;
691 + unsigned int regidx;
692 struct Scsi_Host *host;
693 struct ps3rom_private *priv;
695 @@ -360,6 +371,9 @@ static int ps3rom_probe(struct ps3_system_bus_device *_dev)
696 if (!dev->bounce_buf)
697 return -ENOMEM;
699 + for (regidx = 0; regidx < dev->num_regions; regidx++)
700 + dev->regions[regidx].flags = region_flags[regidx];
702 error = ps3stor_setup(dev, ps3rom_interrupt);
703 if (error)
704 goto fail_free_bounce;