* updated kollision (21.12.1 -> 21.12.2), untested
[t2-trunk.git] / architecture / powerpc64 / package / linux / 0030-ps3flash.patch
blob5accc19337dd15851bafed77071ae0525af84fa9
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # T2 SDE: architecture/powerpc64/package/*/0030-ps3flash.patch
3 # Copyright (C) 2019 - 2021 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 as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
14 # --- T2-COPYRIGHT-NOTE-END ---
16 --- a/arch/powerpc/include/asm/ps3.h
17 +++ b/arch/powerpc/include/asm/ps3.h
18 @@ -313,6 +313,7 @@ enum ps3_match_id {
19 PS3_MATCH_ID_SOUND = 9,
20 PS3_MATCH_ID_GPU = 10,
21 PS3_MATCH_ID_LPM = 11,
22 + PS3_MATCH_ID_STOR_NOR_FLASH = 12,
25 enum ps3_match_sub_id {
26 @@ -332,6 +333,7 @@ enum ps3_match_sub_id {
27 #define PS3_MODULE_ALIAS_GPU_FB "ps3:10:1"
28 #define PS3_MODULE_ALIAS_GPU_RAMDISK "ps3:10:2"
29 #define PS3_MODULE_ALIAS_LPM "ps3:11:0"
30 +#define PS3_MODULE_ALIAS_STOR_NOR_FLASH "ps3:12:0"
32 enum ps3_system_bus_device_type {
33 PS3_DEVICE_TYPE_IOC0 = 1,
34 --- a/arch/powerpc/platforms/ps3/platform.h
35 +++ b/arch/powerpc/platforms/ps3/platform.h
36 @@ -76,6 +76,7 @@ enum ps3_dev_type {
37 PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */
38 PS3_DEV_TYPE_SB_GPIO = 6,
39 PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */
40 + PS3_DEV_TYPE_STOR_NOR_FLASH = 254,
43 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
44 --- a/arch/powerpc/platforms/ps3/device-init.c
45 +++ b/arch/powerpc/platforms/ps3/device-init.c
46 @@ -578,6 +578,13 @@ static int ps3_setup_dynamic_device(const struct ps3_repository_device *repo)
47 __func__, __LINE__);
48 break;
50 + case PS3_DEV_TYPE_STOR_NOR_FLASH:
51 + result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_NOR_FLASH);
52 + if (result)
53 + pr_debug("%s:%u ps3_setup_storage_dev failed\n",
54 + __func__, __LINE__);
55 + break;
57 default:
58 result = 0;
59 pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
60 --- a/arch/powerpc/platforms/ps3/system-bus.c
61 +++ b/arch/powerpc/platforms/ps3/system-bus.c
62 @@ -162,6 +162,7 @@ int ps3_open_hv_device(struct ps3_system_bus_device *dev)
63 case PS3_MATCH_ID_STOR_DISK:
64 case PS3_MATCH_ID_STOR_ROM:
65 case PS3_MATCH_ID_STOR_FLASH:
66 + case PS3_MATCH_ID_STOR_NOR_FLASH:
67 return ps3_open_hv_device_sb(dev);
69 case PS3_MATCH_ID_SOUND:
70 @@ -200,6 +201,7 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev)
71 case PS3_MATCH_ID_STOR_DISK:
72 case PS3_MATCH_ID_STOR_ROM:
73 case PS3_MATCH_ID_STOR_FLASH:
74 + case PS3_MATCH_ID_STOR_NOR_FLASH:
75 return ps3_close_hv_device_sb(dev);
77 case PS3_MATCH_ID_SOUND:
78 --- a/arch/powerpc/platforms/ps3/Kconfig
79 +++ b/arch/powerpc/platforms/ps3/Kconfig
80 @@ -137,6 +137,26 @@ config PS3_FLASH
81 be disabled on the kernel command line using "ps3flash=off", to
82 not allocate this fixed buffer.
84 +config PS3_FLASH_NG
85 + tristate "PS3 Flash Storage Driver"
86 + depends on PPC_PS3 && BLOCK && PS3_FLASH!=y && PS3_FLASH!=m
87 + select PS3_STORAGE
88 + help
89 + Include support for the PS3 Flash Storage.
91 + This support is required to access the PS3 flash.
92 + In general, all users will say Y or M.
94 +config PS3_NOR_FLASH
95 + tristate "PS3 NOR Flash Storage Driver"
96 + depends on PPC_PS3 && BLOCK
97 + select PS3_STORAGE
98 + help
99 + Include support for the PS3 NOR Flash Storage.
101 + This support is required to access the PS3 NOR flash.
102 + In general, all users will say Y or M.
104 config PS3_VRAM
105 tristate "PS3 Video RAM Storage Driver"
106 depends on FB_PS3=y && BLOCK && m
107 --- a/drivers/block/Makefile
108 +++ b/drivers/block/Makefile
109 @@ -11,6 +11,8 @@ obj-$(CONFIG_BLK_DEV_SWIM) += swim_mod.o
110 obj-$(CONFIG_BLK_DEV_FD) += floppy.o
111 obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
112 obj-$(CONFIG_PS3_DISK) += ps3disk.o
113 +obj-$(CONFIG_PS3_FLASH_NG) += ps3flash.o
114 +obj-$(CONFIG_PS3_NOR_FLASH) += ps3nflash.o
115 obj-$(CONFIG_PS3_VRAM) += ps3vram.o
116 obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
117 obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
118 --- /dev/null
119 +++ b/drivers/block/ps3flash.c
120 @@ -0,0 +1,526 @@
122 + * PS3 Flash Storage Driver
124 + * Copyright (C) 2020-2021 Ren\xc3\xa9 Rebe <rene@exactcode.de>.
125 + * Copyright (C) 2019 Emmanuel Nicolet <emmanuel.nicolet@gmail.com>.
126 + * Copyright (C) 2011-2013 glevand <geoffrey.levand@mail.ru>.
127 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>.
128 + * Copyright (C) 2007 Sony Computer Entertainment Inc.
129 + * Copyright 2007 Sony Corp.
131 + * This program is free software; you can redistribute it and/or modify it
132 + * under the terms of the GNU General Public License as published
133 + * by the Free Software Foundation; version 2 of the License.
135 + * This program is distributed in the hope that it will be useful, but
136 + * WITHOUT ANY WARRANTY; without even the implied warranty of
137 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
138 + * General Public License for more details.
140 + * You should have received a copy of the GNU General Public License along
141 + * with this program; if not, write to the Free Software Foundation, Inc.,
142 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
143 + */
145 +#include <linux/blk-mq.h>
146 +#include <linux/slab.h>
147 +#include <linux/module.h>
149 +#include <asm/lv1call.h>
150 +#include <asm/ps3stor.h>
151 +#include <asm/firmware.h>
154 +#define DEVICE_NAME "ps3flash"
156 +#define BOUNCE_SIZE (64*1024)
158 +#define PS3FLASH_MAX_NUM_REGS 8
159 +#define PS3FLASH_MINORS 16
162 +#define PS3FLASH_NAME "ps3flash%c"
165 +struct ps3flash_private {
166 + spinlock_t lock; /* Request queue spinlock */
167 + unsigned int blocking_factor;
168 + struct request *req;
169 + u64 raw_capacity;
170 + int is_vflash;
171 + struct blk_mq_tag_set tag_set[PS3FLASH_MAX_NUM_REGS];
172 + struct gendisk *gendisk[PS3FLASH_MAX_NUM_REGS];
173 + struct request_queue *queue[PS3FLASH_MAX_NUM_REGS];
174 + int next_queue;
178 +#define LV1_STORAGE_ATA_FLUSH_CACHE_EXT (0x31)
181 +static int ps3flash_major;
184 +static const struct block_device_operations ps3flash_fops = {
185 + .owner = THIS_MODULE,
188 +static unsigned int region_flags[] =
190 + 0x6, 0x2, 0x4, 0x4, 0x4, 0x0, 0x2, 0x0,
192 +module_param_array(region_flags, uint, NULL, S_IRUGO);
193 +MODULE_PARM_DESC(region_flags, "Region flags");
196 +static void ps3flash_scatter_gather(struct ps3_storage_device *dev,
197 + struct request *req, int gather)
199 + unsigned int offset = 0;
200 + struct req_iterator iter;
201 + struct bio_vec bvec;
202 + unsigned int i = 0;
203 + size_t size;
204 + void *buf;
206 + rq_for_each_segment(bvec, req, iter) {
207 + unsigned long flags;
208 + dev_dbg(&dev->sbd.core,
209 + "%s:%u: bio %u: %u segs %u sectors from %llu\n",
210 + __func__, __LINE__, i, bio_segments(iter.bio),
211 + bio_sectors(iter.bio), iter.bio->bi_iter.bi_sector);
213 + size = bvec.bv_len;
214 + buf = bvec_kmap_irq(&bvec, &flags);
215 + if (gather)
216 + memcpy(dev->bounce_buf+offset, buf, size);
217 + else
218 + memcpy(buf, dev->bounce_buf+offset, size);
219 + offset += size;
220 + flush_kernel_dcache_page(bvec.bv_page);
221 + bvec_kunmap_irq(buf, &flags);
222 + i++;
226 +static blk_status_t ps3flash_submit_request_sg(struct ps3_storage_device *dev,
227 + struct request *req)
229 + struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
230 + int write = rq_data_dir(req), res;
231 + const char *op = write ? "write" : "read";
232 + u64 start_sector, sectors;
233 + unsigned int region_idx = MINOR(disk_devt(req->rq_disk)) / PS3FLASH_MINORS;
234 + unsigned int region_id = dev->regions[region_idx].id;
235 + unsigned int region_flags = dev->regions[region_idx].flags;
237 +#ifdef DEBUG
238 + unsigned int n = 0;
239 + struct bio_vec bv;
240 + struct req_iterator iter;
242 + rq_for_each_segment(bv, req, iter)
243 + n++;
244 + dev_dbg(&dev->sbd.core,
245 + "%s:%u: %s req has %u bvecs for %u sectors\n",
246 + __func__, __LINE__, op, n, blk_rq_sectors(req));
247 +#endif
249 + start_sector = blk_rq_pos(req) * priv->blocking_factor;
250 + sectors = blk_rq_sectors(req) * priv->blocking_factor;
251 + dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
252 + __func__, __LINE__, op, sectors, start_sector);
254 + if (write) {
255 + ps3flash_scatter_gather(dev, req, 1);
257 + res = lv1_storage_write(dev->sbd.dev_id, region_id,
258 + start_sector, sectors, region_flags,
259 + dev->bounce_lpar, &dev->tag);
260 + } else {
261 + res = lv1_storage_read(dev->sbd.dev_id, region_id,
262 + start_sector, sectors, region_flags,
263 + dev->bounce_lpar, &dev->tag);
265 + if (res) {
266 + dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
267 + __LINE__, op, res);
268 + return BLK_STS_IOERR;
271 + priv->req = req;
272 + return BLK_STS_OK;
275 +static blk_status_t ps3flash_submit_flush_request(struct ps3_storage_device *dev,
276 + struct request *req)
278 + struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
279 + u64 res;
281 + dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
283 + res = lv1_storage_send_device_command(dev->sbd.dev_id,
284 + LV1_STORAGE_ATA_FLUSH_CACHE_EXT, 0, 0, 0,
285 + 0, &dev->tag);
286 + if (res) {
287 + dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
288 + __func__, __LINE__, res);
289 + return BLK_STS_IOERR;
292 + priv->req = req;
293 + return BLK_STS_OK;
296 +static blk_status_t ps3flash_do_request(struct ps3_storage_device *dev,
297 + struct request *req)
299 + struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
301 + dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
303 + if (priv->is_vflash && req_op(req) == REQ_OP_FLUSH) {
304 + return ps3flash_submit_flush_request(dev, req);
305 + } else if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE) {
306 + return ps3flash_submit_request_sg(dev, req);
307 + } else {
308 + blk_dump_rq_flags(req, DEVICE_NAME " bad request");
309 + return BLK_STS_IOERR;
313 +static blk_status_t ps3flash_queue_rq(struct blk_mq_hw_ctx *hctx,
314 + const struct blk_mq_queue_data *bd)
316 + struct request_queue *q = hctx->queue;
317 + struct ps3_storage_device *dev = q->queuedata;
318 + struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
319 + blk_status_t ret;
321 + spin_lock_irq(&priv->lock);
322 + if (priv->req) {
323 + spin_unlock_irq(&priv->lock);
324 + blk_mq_stop_hw_queue(hctx);
325 + return BLK_STS_DEV_RESOURCE;
328 + blk_mq_start_request(bd->rq);
330 + ret = ps3flash_do_request(dev, bd->rq);
331 + spin_unlock_irq(&priv->lock);
333 + return ret;
336 +static irqreturn_t ps3flash_interrupt(int irq, void *data)
338 + struct ps3_storage_device *dev = data;
339 + struct ps3flash_private *priv;
340 + struct request *req;
341 + int res, read, error;
342 + u64 tag, status;
343 + const char *op;
344 + struct request_queue *q;
345 + int old_queue;
347 + res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
349 + if (tag != dev->tag)
350 + dev_err(&dev->sbd.core,
351 + "%s:%u: tag mismatch, got %llx, expected %llx\n",
352 + __func__, __LINE__, tag, dev->tag);
354 + if (res) {
355 + dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
356 + __func__, __LINE__, res, status);
357 + return IRQ_HANDLED;
360 + priv = ps3_system_bus_get_drvdata(&dev->sbd);
361 + req = priv->req;
362 + if (!req) {
363 + dev_dbg(&dev->sbd.core,
364 + "%s:%u non-block layer request completed\n", __func__,
365 + __LINE__);
366 + dev->lv1_status = status;
367 + complete(&dev->done);
368 + return IRQ_HANDLED;
371 + if (req_op(req) == REQ_OP_FLUSH) {
372 + read = 0;
373 + op = "flush";
374 + } else {
375 + read = !rq_data_dir(req);
376 + op = read ? "read" : "write";
378 + if (status) {
379 + dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
380 + __LINE__, op, status);
381 + error = -EIO;
382 + } else {
383 + dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
384 + __LINE__, op);
385 + error = 0;
386 + if (read)
387 + ps3flash_scatter_gather(dev, req, 0);
390 + spin_lock(&priv->lock);
391 + priv->req = NULL;
392 + blk_mq_end_request(req, error);
393 + old_queue = priv->next_queue;
394 + do {
395 + q = priv->queue[priv->next_queue];
397 + priv->next_queue++;
398 + if (priv->next_queue >= dev->num_regions)
399 + priv->next_queue = 0;
401 + if (q && blk_mq_queue_stopped(q)) {
402 + blk_mq_start_stopped_hw_queues(q, true);
403 + break;
405 + } while (old_queue != priv->next_queue);
406 + spin_unlock(&priv->lock);
408 + return IRQ_HANDLED;
411 +static int ps3flash_sync_cache(struct ps3_storage_device *dev)
413 + u64 res;
415 + dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__);
417 + res = ps3stor_send_command(dev, LV1_STORAGE_ATA_FLUSH_CACHE_EXT, 0, 0, 0, 0);
418 + if (res) {
419 + dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
420 + __func__, __LINE__, res);
421 + return -EIO;
423 + return 0;
426 +static const struct blk_mq_ops ps3flash_mq_ops = {
427 + .queue_rq = ps3flash_queue_rq,
430 +static int ps3flash_probe(struct ps3_system_bus_device *_dev)
432 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
433 + struct ps3flash_private *priv;
434 + int error;
435 + unsigned int regidx, devidx;
436 + u64 lpar_id, flash_ext_flag, junk;
437 + struct request_queue *queue;
438 + struct gendisk *gendisk;
440 + BUG_ON(dev->num_regions > PS3FLASH_MAX_NUM_REGS);
442 + if (dev->blk_size < 512) {
443 + dev_err(&dev->sbd.core,
444 + "%s:%u: cannot handle block size %llu\n", __func__,
445 + __LINE__, dev->blk_size);
446 + return -EINVAL;
449 + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
450 + if (!priv) {
451 + error = -ENOMEM;
452 + goto fail;
455 + ps3_system_bus_set_drvdata(_dev, priv);
456 + spin_lock_init(&priv->lock);
458 + dev->bounce_size = BOUNCE_SIZE;
459 + dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
460 + if (!dev->bounce_buf) {
461 + error = -ENOMEM;
462 + goto fail_free_priv;
465 + for (regidx = 0; regidx < dev->num_regions; regidx++)
466 + dev->regions[regidx].flags = region_flags[regidx];
468 + error = ps3stor_setup(dev, ps3flash_interrupt);
469 + if (error)
470 + goto fail_free_bounce;
472 + priv->raw_capacity = dev->regions[0].size;
474 + error = lv1_get_logical_partition_id(&lpar_id);
475 + if (error)
476 + goto fail_teardown;
478 + error = lv1_read_repository_node(1, 0x0000000073797300ul /* sys */,
479 + 0x666c617368000000ul /* flash */,
480 + 0x6578740000000000ul /* ext */,
481 + 0, &flash_ext_flag, &junk);
482 + if (error)
483 + goto fail_teardown;
485 + priv->is_vflash = !(flash_ext_flag & 0x1);
487 + dev_info(&dev->sbd.core, "VFLASH is %s\n",
488 + priv->is_vflash ? "on" : "off");
490 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
491 + if (test_bit(devidx, &dev->accessible_regions) == 0)
492 + continue;
494 + queue = blk_mq_init_sq_queue(&priv->tag_set[devidx], &ps3flash_mq_ops, 1,
495 + BLK_MQ_F_SHOULD_MERGE);
496 + if (IS_ERR(queue)) {
497 + dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_sq_queue failed\n",
498 + __func__, __LINE__);
499 + error = PTR_ERR(queue);
500 + goto fail_cleanup;
503 + priv->queue[devidx] = queue;
504 + queue->queuedata = dev;
506 + blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
508 + blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
509 + blk_queue_dma_alignment(queue, dev->blk_size-1);
510 + blk_queue_logical_block_size(queue, dev->blk_size);
512 + blk_queue_write_cache(queue, true, false);
514 + blk_queue_max_segments(queue, -1);
515 + blk_queue_max_segment_size(queue, dev->bounce_size);
517 + gendisk = alloc_disk(PS3FLASH_MINORS);
518 + if (!gendisk) {
519 + dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
520 + __LINE__);
521 + error = -ENOMEM;
522 + goto fail_cleanup;
525 + priv->gendisk[devidx] = gendisk;
526 + gendisk->major = ps3flash_major;
527 + gendisk->first_minor = devidx * PS3FLASH_MINORS;
528 + gendisk->fops = &ps3flash_fops;
529 + gendisk->queue = queue;
530 + gendisk->private_data = dev;
531 + snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3FLASH_NAME,
532 + devidx+'a');
533 + priv->blocking_factor = dev->blk_size >> 9;
534 + set_capacity(gendisk,
535 + dev->regions[devidx].size*priv->blocking_factor);
537 + dev_info(&dev->sbd.core,
538 + "%s (%llu MiB total, %llu MiB region)\n",
539 + gendisk->disk_name, priv->raw_capacity >> 11,
540 + get_capacity(gendisk) >> 11);
542 + add_disk(gendisk);
545 + return 0;
547 +fail_cleanup:
548 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
549 + if (priv->gendisk[devidx]) {
550 + del_gendisk(priv->gendisk[devidx]);
551 + put_disk(priv->gendisk[devidx]);
554 + if (priv->queue[devidx]) {
555 + blk_cleanup_queue(priv->queue[devidx]);
556 + blk_mq_free_tag_set(&priv->tag_set[devidx]);
559 +fail_teardown:
560 + ps3stor_teardown(dev);
561 +fail_free_bounce:
562 + kfree(dev->bounce_buf);
563 +fail_free_priv:
564 + kfree(priv);
565 + ps3_system_bus_set_drvdata(_dev, NULL);
566 +fail:
567 + return error;
570 +static void ps3flash_remove(struct ps3_system_bus_device *_dev)
572 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
573 + struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
574 + unsigned int devidx;
576 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
577 + if (priv->gendisk[devidx]) {
578 + del_gendisk(priv->gendisk[devidx]);
579 + put_disk(priv->gendisk[devidx]);
582 + if (priv->queue[devidx]) {
583 + blk_cleanup_queue(priv->queue[devidx]);
584 + blk_mq_free_tag_set(&priv->tag_set[devidx]);
588 + if (priv->is_vflash) {
589 + dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
590 + ps3flash_sync_cache(dev);
593 + ps3stor_teardown(dev);
594 + kfree(dev->bounce_buf);
595 + kfree(priv);
596 + ps3_system_bus_set_drvdata(_dev, NULL);
599 +static struct ps3_system_bus_driver ps3flash = {
600 + .match_id = PS3_MATCH_ID_STOR_FLASH,
601 + .core.name = DEVICE_NAME,
602 + .core.owner = THIS_MODULE,
603 + .probe = ps3flash_probe,
604 + .remove = ps3flash_remove,
605 + .shutdown = ps3flash_remove,
609 +static int __init ps3flash_init(void)
611 + int error;
613 + if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
614 + return -ENODEV;
616 + error = register_blkdev(0, DEVICE_NAME);
617 + if (error <= 0) {
618 + printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
619 + __LINE__, error);
620 + return error;
622 + ps3flash_major = error;
624 + pr_info("%s:%u: registered block device major %d\n", __func__,
625 + __LINE__, ps3flash_major);
627 + error = ps3_system_bus_driver_register(&ps3flash);
628 + if (error)
629 + unregister_blkdev(ps3flash_major, DEVICE_NAME);
631 + return error;
634 +static void __exit ps3flash_exit(void)
636 + ps3_system_bus_driver_unregister(&ps3flash);
637 + unregister_blkdev(ps3flash_major, DEVICE_NAME);
640 +module_init(ps3flash_init);
641 +module_exit(ps3flash_exit);
643 +MODULE_LICENSE("GPL");
644 +MODULE_DESCRIPTION("PS3 Flash Storage Driver");
645 +MODULE_AUTHOR("Sony Corporation");
646 +MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);
647 --- /dev/null 2021-09-09 22:47:49.224901655 +0200
648 +++ linux-5.14/drivers/block/ps3nflash.c 2021-09-09 23:10:10.245795262 +0200
649 @@ -0,0 +1,444 @@
651 + * PS3 Flash Storage Driver
653 + * Copyright (C) 2020-2021 Ren\xc3\xa9 Rebe <rene@exactcode.de>.
654 + * Copyright (C) 2019 Emmanuel Nicolet <emmanuel.nicolet@gmail.com>.
655 + * Copyright (C) 2011-2013 glevand <geoffrey.levand@mail.ru>.
656 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>.
657 + * Copyright (C) 2007 Sony Computer Entertainment Inc.
658 + * Copyright 2007 Sony Corp.
660 + * This program is free software; you can redistribute it and/or modify it
661 + * under the terms of the GNU General Public License as published
662 + * by the Free Software Foundation; version 2 of the License.
664 + * This program is distributed in the hope that it will be useful, but
665 + * WITHOUT ANY WARRANTY; without even the implied warranty of
666 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
667 + * General Public License for more details.
669 + * You should have received a copy of the GNU General Public License along
670 + * with this program; if not, write to the Free Software Foundation, Inc.,
671 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
672 + */
674 +#include <linux/blk-mq.h>
675 +#include <linux/slab.h>
676 +#include <linux/module.h>
678 +#include <asm/lv1call.h>
679 +#include <asm/ps3stor.h>
680 +#include <asm/firmware.h>
683 +#define DEVICE_NAME "ps3nflash"
685 +#define BOUNCE_SIZE (64*1024)
686 +#define PS3NFLASH_MAX_NUM_REGS 8
687 +#define PS3NFLASH_MINORS 16
689 +#define PS3NFLASH_NAME "ps3nflash%c"
692 +struct ps3nflash_private {
693 + spinlock_t lock; /* Request queue spinlock */
694 + unsigned int blocking_factor;
695 + struct request *req;
696 + u64 raw_capacity;
697 + struct blk_mq_tag_set tag_set[PS3NFLASH_MAX_NUM_REGS];
698 + struct gendisk *gendisk[PS3NFLASH_MAX_NUM_REGS];
699 + struct request_queue *queue[PS3NFLASH_MAX_NUM_REGS];
700 + int next_queue;
704 +static int ps3nflash_major;
707 +static const struct block_device_operations ps3nflash_fops = {
708 + .owner = THIS_MODULE,
711 +static unsigned int region_flags[] =
713 + 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0,
715 +module_param_array(region_flags, uint, NULL, S_IRUGO);
716 +MODULE_PARM_DESC(region_flags, "Region flags");
719 +static void ps3nflash_scatter_gather(struct ps3_storage_device *dev,
720 + struct request *req, int gather)
722 + unsigned int offset = 0;
723 + struct req_iterator iter;
724 + struct bio_vec bvec;
725 + unsigned int i = 0;
726 + size_t size;
727 + void *buf;
729 + rq_for_each_segment(bvec, req, iter) {
730 + unsigned long flags;
731 + dev_dbg(&dev->sbd.core,
732 + "%s:%u: bio %u: %u segs %u sectors from %llu\n",
733 + __func__, __LINE__, i, bio_segments(iter.bio),
734 + bio_sectors(iter.bio), iter.bio->bi_iter.bi_sector);
736 + size = bvec.bv_len;
737 + buf = bvec_kmap_irq(&bvec, &flags);
738 + if (gather)
739 + memcpy(dev->bounce_buf+offset, buf, size);
740 + else
741 + memcpy(buf, dev->bounce_buf+offset, size);
742 + offset += size;
743 + flush_kernel_dcache_page(bvec.bv_page);
744 + bvec_kunmap_irq(buf, &flags);
745 + i++;
749 +static blk_status_t ps3nflash_submit_request_sg(struct ps3_storage_device *dev,
750 + struct request *req)
752 + struct ps3nflash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
753 + int write = rq_data_dir(req), res;
754 + const char *op = write ? "write" : "read";
755 + u64 start_sector, sectors;
756 + unsigned int region_idx = MINOR(disk_devt(req->rq_disk)) / PS3NFLASH_MINORS;
757 + unsigned int region_id = dev->regions[region_idx].id;
758 + unsigned int region_flags = dev->regions[region_idx].flags;
760 +#ifdef DEBUG
761 + unsigned int n = 0;
762 + struct bio_vec bv;
763 + struct req_iterator iter;
765 + rq_for_each_segment(bv, req, iter)
766 + n++;
767 + dev_dbg(&dev->sbd.core,
768 + "%s:%u: %s req has %u bvecs for %u sectors\n",
769 + __func__, __LINE__, op, n, blk_rq_sectors(req));
770 +#endif
772 + start_sector = blk_rq_pos(req) * priv->blocking_factor;
773 + sectors = blk_rq_sectors(req) * priv->blocking_factor;
774 + dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
775 + __func__, __LINE__, op, sectors, start_sector);
777 + if (write) {
778 + ps3nflash_scatter_gather(dev, req, 1);
780 + res = lv1_storage_write(dev->sbd.dev_id, region_id,
781 + start_sector, sectors, region_flags,
782 + dev->bounce_lpar, &dev->tag);
783 + } else {
784 + res = lv1_storage_read(dev->sbd.dev_id, region_id,
785 + start_sector, sectors, region_flags,
786 + dev->bounce_lpar, &dev->tag);
788 + if (res) {
789 + dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
790 + __LINE__, op, res);
791 + return BLK_STS_IOERR;
794 + priv->req = req;
795 + return BLK_STS_OK;
798 +static blk_status_t ps3nflash_do_request(struct ps3_storage_device *dev,
799 + struct request *req)
801 + dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
803 + switch (req_op(req)) {
804 + case REQ_OP_READ:
805 + case REQ_OP_WRITE:
806 + case REQ_OP_FLUSH:
807 + return ps3nflash_submit_request_sg(dev, req);
808 + default:
809 + blk_dump_rq_flags(req, DEVICE_NAME " bad request");
810 + return BLK_STS_IOERR;
814 +static blk_status_t ps3nflash_queue_rq(struct blk_mq_hw_ctx *hctx,
815 + const struct blk_mq_queue_data *bd)
817 + struct request_queue *q = hctx->queue;
818 + struct ps3_storage_device *dev = q->queuedata;
819 + struct ps3nflash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
820 + blk_status_t ret;
822 + spin_lock_irq(&priv->lock);
823 + if (priv->req) {
824 + spin_unlock_irq(&priv->lock);
825 + blk_mq_stop_hw_queue(hctx);
826 + return BLK_STS_DEV_RESOURCE;
829 + blk_mq_start_request(bd->rq);
831 + ret = ps3nflash_do_request(dev, bd->rq);
832 + spin_unlock_irq(&priv->lock);
834 + return ret;
837 +static irqreturn_t ps3nflash_interrupt(int irq, void *data)
839 + struct ps3_storage_device *dev = data;
840 + struct ps3nflash_private *priv;
841 + struct request *req;
842 + int res, read, error;
843 + u64 tag, status;
844 + const char *op;
845 + struct request_queue *q;
846 + int old_queue;
848 + res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
850 + if (tag != dev->tag)
851 + dev_err(&dev->sbd.core,
852 + "%s:%u: tag mismatch, got %llx, expected %llx\n",
853 + __func__, __LINE__, tag, dev->tag);
855 + if (res) {
856 + dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
857 + __func__, __LINE__, res, status);
858 + return IRQ_HANDLED;
861 + priv = ps3_system_bus_get_drvdata(&dev->sbd);
862 + req = priv->req;
863 + if (!req) {
864 + dev_dbg(&dev->sbd.core,
865 + "%s:%u non-block layer request completed\n", __func__,
866 + __LINE__);
867 + dev->lv1_status = status;
868 + complete(&dev->done);
869 + return IRQ_HANDLED;
872 + read = !rq_data_dir(req);
873 + op = read ? "read" : "write";
875 + if (status) {
876 + dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
877 + __LINE__, op, status);
878 + error = -EIO;
879 + } else {
880 + dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
881 + __LINE__, op);
882 + error = 0;
883 + if (read)
884 + ps3nflash_scatter_gather(dev, req, 0);
887 + spin_lock(&priv->lock);
888 + priv->req = NULL;
889 + blk_mq_end_request(req, error);
890 + old_queue = priv->next_queue;
891 + do {
892 + q = priv->queue[priv->next_queue];
894 + priv->next_queue++;
895 + if (priv->next_queue >= dev->num_regions)
896 + priv->next_queue = 0;
898 + if (q && blk_mq_queue_stopped(q)) {
899 + blk_mq_start_stopped_hw_queues(q, true);
900 + break;
902 + } while (old_queue != priv->next_queue);
903 + spin_unlock(&priv->lock);
905 + return IRQ_HANDLED;
908 +static const struct blk_mq_ops ps3nflash_mq_ops = {
909 + .queue_rq = ps3nflash_queue_rq,
912 +static int ps3nflash_probe(struct ps3_system_bus_device *_dev)
914 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
915 + struct ps3nflash_private *priv;
916 + int error;
917 + unsigned int regidx, devidx;
918 + struct request_queue *queue;
919 + struct gendisk *gendisk;
921 + BUG_ON(dev->num_regions > PS3NFLASH_MAX_NUM_REGS);
923 + if (dev->blk_size < 512) {
924 + dev_err(&dev->sbd.core,
925 + "%s:%u: cannot handle block size %llu\n", __func__,
926 + __LINE__, dev->blk_size);
927 + return -EINVAL;
930 + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
931 + if (!priv) {
932 + error = -ENOMEM;
933 + goto fail;
936 + ps3_system_bus_set_drvdata(_dev, priv);
937 + spin_lock_init(&priv->lock);
939 + dev->bounce_size = BOUNCE_SIZE;
940 + dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
941 + if (!dev->bounce_buf) {
942 + error = -ENOMEM;
943 + goto fail_free_priv;
946 + for (regidx = 0; regidx < dev->num_regions; regidx++)
947 + dev->regions[regidx].flags = region_flags[regidx];
949 + error = ps3stor_setup(dev, ps3nflash_interrupt);
950 + if (error)
951 + goto fail_free_bounce;
953 + priv->raw_capacity = dev->regions[0].size;
955 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
956 + if (test_bit(devidx, &dev->accessible_regions) == 0)
957 + continue;
959 + error = blk_mq_alloc_sq_tag_set(&priv->tag_set[devidx], &ps3nflash_mq_ops, 1,
960 + BLK_MQ_F_SHOULD_MERGE);
961 + if (error) {
962 + goto fail_cleanup;
965 + gendisk = blk_mq_alloc_disk(&priv->tag_set[devidx], dev);
966 + if (IS_ERR(gendisk)) {
967 + dev_err(&dev->sbd.core, "%s:%u: blk_mq_alloc_disk failed\n",
968 + __func__, __LINE__);
969 + error = PTR_ERR(gendisk);
970 + goto fail_cleanup;
973 + blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
975 + blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
976 + blk_queue_dma_alignment(queue, dev->blk_size-1);
977 + blk_queue_logical_block_size(queue, dev->blk_size);
979 + blk_queue_max_segments(queue, -1);
980 + blk_queue_max_segment_size(queue, dev->bounce_size);
982 + priv->gendisk[devidx] = gendisk;
983 + gendisk->major = ps3nflash_major;
984 + gendisk->minors = PS3NFLASH_MINORS;
985 + gendisk->first_minor = devidx * PS3NFLASH_MINORS;
986 + gendisk->fops = &ps3nflash_fops;
987 + gendisk->queue = queue;
988 + gendisk->private_data = dev;
989 + snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3NFLASH_NAME,
990 + devidx + 'a');
991 + priv->blocking_factor = dev->blk_size >> 9;
992 + set_capacity(gendisk,
993 + dev->regions[devidx].size*priv->blocking_factor);
995 + dev_info(&dev->sbd.core,
996 + "%s (%llu MiB total, %llu MiB region)\n",
997 + gendisk->disk_name, priv->raw_capacity >> 11,
998 + get_capacity(gendisk) >> 11);
1000 + add_disk(gendisk);
1003 + return 0;
1005 +fail_cleanup:
1006 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
1007 + if (priv->gendisk[devidx]) {
1008 + del_gendisk(priv->gendisk[devidx]);
1009 + blk_cleanup_disk(priv->gendisk[devidx]);
1012 + ps3stor_teardown(dev);
1013 +fail_free_bounce:
1014 + kfree(dev->bounce_buf);
1015 +fail_free_priv:
1016 + kfree(priv);
1017 + ps3_system_bus_set_drvdata(_dev, NULL);
1018 +fail:
1019 + return error;
1022 +static void ps3nflash_remove(struct ps3_system_bus_device *_dev)
1024 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
1025 + struct ps3nflash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
1026 + unsigned int devidx;
1028 + for (devidx = 0; devidx < dev->num_regions; devidx++) {
1029 + if (priv->gendisk[devidx]) {
1030 + del_gendisk(priv->gendisk[devidx]);
1031 + put_disk(priv->gendisk[devidx]);
1034 + if (priv->queue[devidx]) {
1035 + blk_cleanup_queue(priv->queue[devidx]);
1036 + blk_mq_free_tag_set(&priv->tag_set[devidx]);
1040 + ps3stor_teardown(dev);
1041 + kfree(dev->bounce_buf);
1042 + kfree(priv);
1043 + ps3_system_bus_set_drvdata(_dev, NULL);
1046 +static struct ps3_system_bus_driver ps3nflash = {
1047 + .match_id = PS3_MATCH_ID_STOR_NOR_FLASH,
1048 + .core.name = DEVICE_NAME,
1049 + .core.owner = THIS_MODULE,
1050 + .probe = ps3nflash_probe,
1051 + .remove = ps3nflash_remove,
1052 + .shutdown = ps3nflash_remove,
1056 +static int __init ps3nflash_init(void)
1058 + int error;
1060 + if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
1061 + return -ENODEV;
1063 + error = register_blkdev(0, DEVICE_NAME);
1064 + if (error <= 0) {
1065 + printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
1066 + __LINE__, error);
1067 + return error;
1069 + ps3nflash_major = error;
1071 + pr_info("%s:%u: registered block device major %d\n", __func__,
1072 + __LINE__, ps3nflash_major);
1074 + error = ps3_system_bus_driver_register(&ps3nflash);
1075 + if (error)
1076 + unregister_blkdev(ps3nflash_major, DEVICE_NAME);
1078 + return error;
1081 +static void __exit ps3nflash_exit(void)
1083 + ps3_system_bus_driver_unregister(&ps3nflash);
1084 + unregister_blkdev(ps3nflash_major, DEVICE_NAME);
1087 +module_init(ps3nflash_init);
1088 +module_exit(ps3nflash_exit);
1090 +MODULE_LICENSE("GPL");
1091 +MODULE_DESCRIPTION("PS3 NOR Flash Storage Driver");
1092 +MODULE_AUTHOR("Sony Corporation");
1093 +MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_NOR_FLASH);