linux/drivers/block/ps3disk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * PS3 Disk Storage Driver
   4 *
   5 * Copyright (C) 2007 Sony Computer Entertainment Inc.
   6 * Copyright 2007 Sony Corp.
   7 */
   8
   9#include <linux/ata.h>
  10#include <linux/blk-mq.h>
  11#include <linux/slab.h>
  12#include <linux/module.h>
  13
  14#include <asm/lv1call.h>
  15#include <asm/ps3stor.h>
  16#include <asm/firmware.h>
  17
  18
  19#define DEVICE_NAME             "ps3disk"
  20
  21#define BOUNCE_SIZE             (64*1024)
  22
  23#define PS3DISK_MAX_DISKS       16
  24#define PS3DISK_MINORS          16
  25
  26
  27#define PS3DISK_NAME            "ps3d%c"
  28
  29
  30struct ps3disk_private {
  31        spinlock_t lock;                /* Request queue spinlock */
  32        struct request_queue *queue;
  33        struct blk_mq_tag_set tag_set;
  34        struct gendisk *gendisk;
  35        unsigned int blocking_factor;
  36        struct request *req;
  37        u64 raw_capacity;
  38        unsigned char model[ATA_ID_PROD_LEN+1];
  39};
  40
  41
  42#define LV1_STORAGE_SEND_ATA_COMMAND    (2)
  43#define LV1_STORAGE_ATA_HDDOUT          (0x23)
  44
  45struct lv1_ata_cmnd_block {
  46        u16     features;
  47        u16     sector_count;
  48        u16     LBA_low;
  49        u16     LBA_mid;
  50        u16     LBA_high;
  51        u8      device;
  52        u8      command;
  53        u32     is_ext;
  54        u32     proto;
  55        u32     in_out;
  56        u32     size;
  57        u64     buffer;
  58        u32     arglen;
  59};
  60
  61enum lv1_ata_proto {
  62        NON_DATA_PROTO     = 0,
  63        PIO_DATA_IN_PROTO  = 1,
  64        PIO_DATA_OUT_PROTO = 2,
  65        DMA_PROTO = 3
  66};
  67
  68enum lv1_ata_in_out {
  69        DIR_WRITE = 0,                  /* memory -> device */
  70        DIR_READ = 1                    /* device -> memory */
  71};
  72
  73static int ps3disk_major;
  74
  75
  76static const struct block_device_operations ps3disk_fops = {
  77        .owner          = THIS_MODULE,
  78};
  79
  80
  81static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
  82                                   struct request *req, int gather)
  83{
  84        unsigned int offset = 0;
  85        struct req_iterator iter;
  86        struct bio_vec bvec;
  87        unsigned int i = 0;
  88        size_t size;
  89        void *buf;
  90
  91        rq_for_each_segment(bvec, req, iter) {
  92                unsigned long flags;
  93                dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %llu\n",
  94                        __func__, __LINE__, i, bio_sectors(iter.bio),
  95                        iter.bio->bi_iter.bi_sector);
  96
  97                size = bvec.bv_len;
  98                buf = bvec_kmap_irq(&bvec, &flags);
  99                if (gather)
 100                        memcpy(dev->bounce_buf+offset, buf, size);
 101                else
 102                        memcpy(buf, dev->bounce_buf+offset, size);
 103                offset += size;
 104                flush_kernel_dcache_page(bvec.bv_page);
 105                bvec_kunmap_irq(buf, &flags);
 106                i++;
 107        }
 108}
 109
 110static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 111                                              struct request *req)
 112{
 113        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 114        int write = rq_data_dir(req), res;
 115        const char *op = write ? "write" : "read";
 116        u64 start_sector, sectors;
 117        unsigned int region_id = dev->regions[dev->region_idx].id;
 118
 119#ifdef DEBUG
 120        unsigned int n = 0;
 121        struct bio_vec bv;
 122        struct req_iterator iter;
 123
 124        rq_for_each_segment(bv, req, iter)
 125                n++;
 126        dev_dbg(&dev->sbd.core,
 127                "%s:%u: %s req has %u bvecs for %u sectors\n",
 128                __func__, __LINE__, op, n, blk_rq_sectors(req));
 129#endif
 130
 131        start_sector = blk_rq_pos(req) * priv->blocking_factor;
 132        sectors = blk_rq_sectors(req) * priv->blocking_factor;
 133        dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
 134                __func__, __LINE__, op, sectors, start_sector);
 135
 136        if (write) {
 137                ps3disk_scatter_gather(dev, req, 1);
 138
 139                res = lv1_storage_write(dev->sbd.dev_id, region_id,
 140                                        start_sector, sectors, 0,
 141                                        dev->bounce_lpar, &dev->tag);
 142        } else {
 143                res = lv1_storage_read(dev->sbd.dev_id, region_id,
 144                                       start_sector, sectors, 0,
 145                                       dev->bounce_lpar, &dev->tag);
 146        }
 147        if (res) {
 148                dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
 149                        __LINE__, op, res);
 150                return BLK_STS_IOERR;
 151        }
 152
 153        priv->req = req;
 154        return BLK_STS_OK;
 155}
 156
 157static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev,
 158                                                 struct request *req)
 159{
 160        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 161        u64 res;
 162
 163        dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
 164
 165        res = lv1_storage_send_device_command(dev->sbd.dev_id,
 166                                              LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
 167                                              0, &dev->tag);
 168        if (res) {
 169                dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 170                        __func__, __LINE__, res);
 171                return BLK_STS_IOERR;
 172        }
 173
 174        priv->req = req;
 175        return BLK_STS_OK;
 176}
 177
 178static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev,
 179                                       struct request *req)
 180{
 181        dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 182
 183        switch (req_op(req)) {
 184        case REQ_OP_FLUSH:
 185                return ps3disk_submit_flush_request(dev, req);
 186        case REQ_OP_READ:
 187        case REQ_OP_WRITE:
 188                return ps3disk_submit_request_sg(dev, req);
 189        default:
 190                blk_dump_rq_flags(req, DEVICE_NAME " bad request");
 191                return BLK_STS_IOERR;
 192        }
 193}
 194
 195static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
 196                                     const struct blk_mq_queue_data *bd)
 197{
 198        struct request_queue *q = hctx->queue;
 199        struct ps3_storage_device *dev = q->queuedata;
 200        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 201        blk_status_t ret;
 202
 203        blk_mq_start_request(bd->rq);
 204
 205        spin_lock_irq(&priv->lock);
 206        ret = ps3disk_do_request(dev, bd->rq);
 207        spin_unlock_irq(&priv->lock);
 208
 209        return ret;
 210}
 211
 212static irqreturn_t ps3disk_interrupt(int irq, void *data)
 213{
 214        struct ps3_storage_device *dev = data;
 215        struct ps3disk_private *priv;
 216        struct request *req;
 217        int res, read;
 218        blk_status_t error;
 219        u64 tag, status;
 220        const char *op;
 221
 222        res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
 223
 224        if (tag != dev->tag)
 225                dev_err(&dev->sbd.core,
 226                        "%s:%u: tag mismatch, got %llx, expected %llx\n",
 227                        __func__, __LINE__, tag, dev->tag);
 228
 229        if (res) {
 230                dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
 231                        __func__, __LINE__, res, status);
 232                return IRQ_HANDLED;
 233        }
 234
 235        priv = ps3_system_bus_get_drvdata(&dev->sbd);
 236        req = priv->req;
 237        if (!req) {
 238                dev_dbg(&dev->sbd.core,
 239                        "%s:%u non-block layer request completed\n", __func__,
 240                        __LINE__);
 241                dev->lv1_status = status;
 242                complete(&dev->done);
 243                return IRQ_HANDLED;
 244        }
 245
 246        if (req_op(req) == REQ_OP_FLUSH) {
 247                read = 0;
 248                op = "flush";
 249        } else {
 250                read = !rq_data_dir(req);
 251                op = read ? "read" : "write";
 252        }
 253        if (status) {
 254                dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
 255                        __LINE__, op, status);
 256                error = BLK_STS_IOERR;
 257        } else {
 258                dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
 259                        __LINE__, op);
 260                error = 0;
 261                if (read)
 262                        ps3disk_scatter_gather(dev, req, 0);
 263        }
 264
 265        spin_lock(&priv->lock);
 266        priv->req = NULL;
 267        blk_mq_end_request(req, error);
 268        spin_unlock(&priv->lock);
 269
 270        blk_mq_run_hw_queues(priv->queue, true);
 271        return IRQ_HANDLED;
 272}
 273
 274static int ps3disk_sync_cache(struct ps3_storage_device *dev)
 275{
 276        u64 res;
 277
 278        dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__);
 279
 280        res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0);
 281        if (res) {
 282                dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 283                        __func__, __LINE__, res);
 284                return -EIO;
 285        }
 286        return 0;
 287}
 288
 289
 290/* ATA helpers copied from drivers/ata/libata-core.c */
 291
 292static void swap_buf_le16(u16 *buf, unsigned int buf_words)
 293{
 294#ifdef __BIG_ENDIAN
 295        unsigned int i;
 296
 297        for (i = 0; i < buf_words; i++)
 298                buf[i] = le16_to_cpu(buf[i]);
 299#endif /* __BIG_ENDIAN */
 300}
 301
 302static u64 ata_id_n_sectors(const u16 *id)
 303{
 304        if (ata_id_has_lba(id)) {
 305                if (ata_id_has_lba48(id))
 306                        return ata_id_u64(id, 100);
 307                else
 308                        return ata_id_u32(id, 60);
 309        } else {
 310                if (ata_id_current_chs_valid(id))
 311                        return ata_id_u32(id, 57);
 312                else
 313                        return id[1] * id[3] * id[6];
 314        }
 315}
 316
 317static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs,
 318                          unsigned int len)
 319{
 320        unsigned int c;
 321
 322        while (len > 0) {
 323                c = id[ofs] >> 8;
 324                *s = c;
 325                s++;
 326
 327                c = id[ofs] & 0xff;
 328                *s = c;
 329                s++;
 330
 331                ofs++;
 332                len -= 2;
 333        }
 334}
 335
 336static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs,
 337                            unsigned int len)
 338{
 339        unsigned char *p;
 340
 341        WARN_ON(!(len & 1));
 342
 343        ata_id_string(id, s, ofs, len - 1);
 344
 345        p = s + strnlen(s, len - 1);
 346        while (p > s && p[-1] == ' ')
 347                p--;
 348        *p = '\0';
 349}
 350
 351static int ps3disk_identify(struct ps3_storage_device *dev)
 352{
 353        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 354        struct lv1_ata_cmnd_block ata_cmnd;
 355        u16 *id = dev->bounce_buf;
 356        u64 res;
 357
 358        dev_dbg(&dev->sbd.core, "%s:%u: identify disk\n", __func__, __LINE__);
 359
 360        memset(&ata_cmnd, 0, sizeof(struct lv1_ata_cmnd_block));
 361        ata_cmnd.command = ATA_CMD_ID_ATA;
 362        ata_cmnd.sector_count = 1;
 363        ata_cmnd.size = ata_cmnd.arglen = ATA_ID_WORDS * 2;
 364        ata_cmnd.buffer = dev->bounce_lpar;
 365        ata_cmnd.proto = PIO_DATA_IN_PROTO;
 366        ata_cmnd.in_out = DIR_READ;
 367
 368        res = ps3stor_send_command(dev, LV1_STORAGE_SEND_ATA_COMMAND,
 369                                   ps3_mm_phys_to_lpar(__pa(&ata_cmnd)),
 370                                   sizeof(ata_cmnd), ata_cmnd.buffer,
 371                                   ata_cmnd.arglen);
 372        if (res) {
 373                dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%llx\n",
 374                        __func__, __LINE__, res);
 375                return -EIO;
 376        }
 377
 378        swap_buf_le16(id, ATA_ID_WORDS);
 379
 380        /* All we're interested in are raw capacity and model name */
 381        priv->raw_capacity = ata_id_n_sectors(id);
 382        ata_id_c_string(id, priv->model, ATA_ID_PROD, sizeof(priv->model));
 383        return 0;
 384}
 385
 386static unsigned long ps3disk_mask;
 387
 388static DEFINE_MUTEX(ps3disk_mask_mutex);
 389
 390static const struct blk_mq_ops ps3disk_mq_ops = {
 391        .queue_rq       = ps3disk_queue_rq,
 392};
 393
 394static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 395{
 396        struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
 397        struct ps3disk_private *priv;
 398        int error;
 399        unsigned int devidx;
 400        struct request_queue *queue;
 401        struct gendisk *gendisk;
 402
 403        if (dev->blk_size < 512) {
 404                dev_err(&dev->sbd.core,
 405                        "%s:%u: cannot handle block size %llu\n", __func__,
 406                        __LINE__, dev->blk_size);
 407                return -EINVAL;
 408        }
 409
 410        BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
 411        mutex_lock(&ps3disk_mask_mutex);
 412        devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
 413        if (devidx >= PS3DISK_MAX_DISKS) {
 414                dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
 415                        __LINE__);
 416                mutex_unlock(&ps3disk_mask_mutex);
 417                return -ENOSPC;
 418        }
 419        __set_bit(devidx, &ps3disk_mask);
 420        mutex_unlock(&ps3disk_mask_mutex);
 421
 422        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 423        if (!priv) {
 424                error = -ENOMEM;
 425                goto fail;
 426        }
 427
 428        ps3_system_bus_set_drvdata(_dev, priv);
 429        spin_lock_init(&priv->lock);
 430
 431        dev->bounce_size = BOUNCE_SIZE;
 432        dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
 433        if (!dev->bounce_buf) {
 434                error = -ENOMEM;
 435                goto fail_free_priv;
 436        }
 437
 438        error = ps3stor_setup(dev, ps3disk_interrupt);
 439        if (error)
 440                goto fail_free_bounce;
 441
 442        ps3disk_identify(dev);
 443
 444        queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 1,
 445                                        BLK_MQ_F_SHOULD_MERGE);
 446        if (IS_ERR(queue)) {
 447                dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n",
 448                        __func__, __LINE__);
 449                error = PTR_ERR(queue);
 450                goto fail_teardown;
 451        }
 452
 453        priv->queue = queue;
 454        queue->queuedata = dev;
 455
 456        blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
 457        blk_queue_dma_alignment(queue, dev->blk_size-1);
 458        blk_queue_logical_block_size(queue, dev->blk_size);
 459
 460        blk_queue_write_cache(queue, true, false);
 461
 462        blk_queue_max_segments(queue, -1);
 463        blk_queue_max_segment_size(queue, dev->bounce_size);
 464
 465        gendisk = alloc_disk(PS3DISK_MINORS);
 466        if (!gendisk) {
 467                dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
 468                        __LINE__);
 469                error = -ENOMEM;
 470                goto fail_cleanup_queue;
 471        }
 472
 473        priv->gendisk = gendisk;
 474        gendisk->major = ps3disk_major;
 475        gendisk->first_minor = devidx * PS3DISK_MINORS;
 476        gendisk->fops = &ps3disk_fops;
 477        gendisk->queue = queue;
 478        gendisk->private_data = dev;
 479        snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
 480                 devidx+'a');
 481        priv->blocking_factor = dev->blk_size >> 9;
 482        set_capacity(gendisk,
 483                     dev->regions[dev->region_idx].size*priv->blocking_factor);
 484
 485        dev_info(&dev->sbd.core,
 486                 "%s is a %s (%llu MiB total, %llu MiB for OtherOS)\n",
 487                 gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
 488                 get_capacity(gendisk) >> 11);
 489
 490        device_add_disk(&dev->sbd.core, gendisk, NULL);
 491        return 0;
 492
 493fail_cleanup_queue:
 494        blk_cleanup_queue(queue);
 495        blk_mq_free_tag_set(&priv->tag_set);
 496fail_teardown:
 497        ps3stor_teardown(dev);
 498fail_free_bounce:
 499        kfree(dev->bounce_buf);
 500fail_free_priv:
 501        kfree(priv);
 502        ps3_system_bus_set_drvdata(_dev, NULL);
 503fail:
 504        mutex_lock(&ps3disk_mask_mutex);
 505        __clear_bit(devidx, &ps3disk_mask);
 506        mutex_unlock(&ps3disk_mask_mutex);
 507        return error;
 508}
 509
 510static void ps3disk_remove(struct ps3_system_bus_device *_dev)
 511{
 512        struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
 513        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 514
 515        mutex_lock(&ps3disk_mask_mutex);
 516        __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
 517                    &ps3disk_mask);
 518        mutex_unlock(&ps3disk_mask_mutex);
 519        del_gendisk(priv->gendisk);
 520        blk_cleanup_queue(priv->queue);
 521        blk_mq_free_tag_set(&priv->tag_set);
 522        put_disk(priv->gendisk);
 523        dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
 524        ps3disk_sync_cache(dev);
 525        ps3stor_teardown(dev);
 526        kfree(dev->bounce_buf);
 527        kfree(priv);
 528        ps3_system_bus_set_drvdata(_dev, NULL);
 529}
 530
 531static struct ps3_system_bus_driver ps3disk = {
 532        .match_id       = PS3_MATCH_ID_STOR_DISK,
 533        .core.name      = DEVICE_NAME,
 534        .core.owner     = THIS_MODULE,
 535        .probe          = ps3disk_probe,
 536        .remove         = ps3disk_remove,
 537        .shutdown       = ps3disk_remove,
 538};
 539
 540
 541static int __init ps3disk_init(void)
 542{
 543        int error;
 544
 545        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 546                return -ENODEV;
 547
 548        error = register_blkdev(0, DEVICE_NAME);
 549        if (error <= 0) {
 550                printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
 551                       __LINE__, error);
 552                return error;
 553        }
 554        ps3disk_major = error;
 555
 556        pr_info("%s:%u: registered block device major %d\n", __func__,
 557                __LINE__, ps3disk_major);
 558
 559        error = ps3_system_bus_driver_register(&ps3disk);
 560        if (error)
 561                unregister_blkdev(ps3disk_major, DEVICE_NAME);
 562
 563        return error;
 564}
 565
 566static void __exit ps3disk_exit(void)
 567{
 568        ps3_system_bus_driver_unregister(&ps3disk);
 569        unregister_blkdev(ps3disk_major, DEVICE_NAME);
 570}
 571
 572module_init(ps3disk_init);
 573module_exit(ps3disk_exit);
 574
 575MODULE_LICENSE("GPL");
 576MODULE_DESCRIPTION("PS3 Disk Storage Driver");
 577MODULE_AUTHOR("Sony Corporation");
 578MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_DISK);
 579