linux/arch/powerpc/platforms/ps3/device-init.c
<<
>>
Prefs
   1/*
   2 *  PS3 device registration routines.
   3 *
   4 *  Copyright (C) 2007 Sony Computer Entertainment Inc.
   5 *  Copyright 2007 Sony Corp.
   6 *
   7 *  This program is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; version 2 of the License.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20
  21#include <linux/delay.h>
  22#include <linux/freezer.h>
  23#include <linux/kernel.h>
  24#include <linux/kthread.h>
  25#include <linux/init.h>
  26#include <linux/reboot.h>
  27
  28#include <asm/firmware.h>
  29#include <asm/lv1call.h>
  30#include <asm/ps3stor.h>
  31
  32#include "platform.h"
  33
  34static int __init ps3_register_lpm_devices(void)
  35{
  36        int result;
  37        u64 tmp1;
  38        u64 tmp2;
  39        struct ps3_system_bus_device *dev;
  40
  41        pr_debug(" -> %s:%d\n", __func__, __LINE__);
  42
  43        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  44        if (!dev)
  45                return -ENOMEM;
  46
  47        dev->match_id = PS3_MATCH_ID_LPM;
  48        dev->dev_type = PS3_DEVICE_TYPE_LPM;
  49
  50        /* The current lpm driver only supports a single BE processor. */
  51
  52        result = ps3_repository_read_be_node_id(0, &dev->lpm.node_id);
  53
  54        if (result) {
  55                pr_debug("%s:%d: ps3_repository_read_be_node_id failed \n",
  56                        __func__, __LINE__);
  57                goto fail_read_repo;
  58        }
  59
  60        result = ps3_repository_read_lpm_privileges(dev->lpm.node_id, &tmp1,
  61                &dev->lpm.rights);
  62
  63        if (result) {
  64                pr_debug("%s:%d: ps3_repository_read_lpm_privleges failed \n",
  65                        __func__, __LINE__);
  66                goto fail_read_repo;
  67        }
  68
  69        lv1_get_logical_partition_id(&tmp2);
  70
  71        if (tmp1 != tmp2) {
  72                pr_debug("%s:%d: wrong lpar\n",
  73                        __func__, __LINE__);
  74                result = -ENODEV;
  75                goto fail_rights;
  76        }
  77
  78        if (!(dev->lpm.rights & PS3_LPM_RIGHTS_USE_LPM)) {
  79                pr_debug("%s:%d: don't have rights to use lpm\n",
  80                        __func__, __LINE__);
  81                result = -EPERM;
  82                goto fail_rights;
  83        }
  84
  85        pr_debug("%s:%d: pu_id %llu, rights %llu(%llxh)\n",
  86                __func__, __LINE__, dev->lpm.pu_id, dev->lpm.rights,
  87                dev->lpm.rights);
  88
  89        result = ps3_repository_read_pu_id(0, &dev->lpm.pu_id);
  90
  91        if (result) {
  92                pr_debug("%s:%d: ps3_repository_read_pu_id failed \n",
  93                        __func__, __LINE__);
  94                goto fail_read_repo;
  95        }
  96
  97        result = ps3_system_bus_device_register(dev);
  98
  99        if (result) {
 100                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 101                        __func__, __LINE__);
 102                goto fail_register;
 103        }
 104
 105        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 106        return 0;
 107
 108
 109fail_register:
 110fail_rights:
 111fail_read_repo:
 112        kfree(dev);
 113        pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
 114        return result;
 115}
 116
 117/**
 118 * ps3_setup_gelic_device - Setup and register a gelic device instance.
 119 *
 120 * Allocates memory for a struct ps3_system_bus_device instance, initialises the
 121 * structure members, and registers the device instance with the system bus.
 122 */
 123
 124static int __init ps3_setup_gelic_device(
 125        const struct ps3_repository_device *repo)
 126{
 127        int result;
 128        struct layout {
 129                struct ps3_system_bus_device dev;
 130                struct ps3_dma_region d_region;
 131        } *p;
 132
 133        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 134
 135        BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
 136        BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
 137
 138        p = kzalloc(sizeof(struct layout), GFP_KERNEL);
 139
 140        if (!p) {
 141                result = -ENOMEM;
 142                goto fail_malloc;
 143        }
 144
 145        p->dev.match_id = PS3_MATCH_ID_GELIC;
 146        p->dev.dev_type = PS3_DEVICE_TYPE_SB;
 147        p->dev.bus_id = repo->bus_id;
 148        p->dev.dev_id = repo->dev_id;
 149        p->dev.d_region = &p->d_region;
 150
 151        result = ps3_repository_find_interrupt(repo,
 152                PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
 153
 154        if (result) {
 155                pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
 156                        __func__, __LINE__);
 157                goto fail_find_interrupt;
 158        }
 159
 160        BUG_ON(p->dev.interrupt_id != 0);
 161
 162        result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
 163                PS3_DMA_OTHER, NULL, 0);
 164
 165        if (result) {
 166                pr_debug("%s:%d ps3_dma_region_init failed\n",
 167                        __func__, __LINE__);
 168                goto fail_dma_init;
 169        }
 170
 171        result = ps3_system_bus_device_register(&p->dev);
 172
 173        if (result) {
 174                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 175                        __func__, __LINE__);
 176                goto fail_device_register;
 177        }
 178
 179        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 180        return result;
 181
 182fail_device_register:
 183fail_dma_init:
 184fail_find_interrupt:
 185        kfree(p);
 186fail_malloc:
 187        pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
 188        return result;
 189}
 190
 191static int __init_refok ps3_setup_uhc_device(
 192        const struct ps3_repository_device *repo, enum ps3_match_id match_id,
 193        enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
 194{
 195        int result;
 196        struct layout {
 197                struct ps3_system_bus_device dev;
 198                struct ps3_dma_region d_region;
 199                struct ps3_mmio_region m_region;
 200        } *p;
 201        u64 bus_addr;
 202        u64 len;
 203
 204        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 205
 206        BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
 207        BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
 208
 209        p = kzalloc(sizeof(struct layout), GFP_KERNEL);
 210
 211        if (!p) {
 212                result = -ENOMEM;
 213                goto fail_malloc;
 214        }
 215
 216        p->dev.match_id = match_id;
 217        p->dev.dev_type = PS3_DEVICE_TYPE_SB;
 218        p->dev.bus_id = repo->bus_id;
 219        p->dev.dev_id = repo->dev_id;
 220        p->dev.d_region = &p->d_region;
 221        p->dev.m_region = &p->m_region;
 222
 223        result = ps3_repository_find_interrupt(repo,
 224                interrupt_type, &p->dev.interrupt_id);
 225
 226        if (result) {
 227                pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
 228                        __func__, __LINE__);
 229                goto fail_find_interrupt;
 230        }
 231
 232        result = ps3_repository_find_reg(repo, reg_type,
 233                &bus_addr, &len);
 234
 235        if (result) {
 236                pr_debug("%s:%d ps3_repository_find_reg failed\n",
 237                        __func__, __LINE__);
 238                goto fail_find_reg;
 239        }
 240
 241        result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
 242                PS3_DMA_INTERNAL, NULL, 0);
 243
 244        if (result) {
 245                pr_debug("%s:%d ps3_dma_region_init failed\n",
 246                        __func__, __LINE__);
 247                goto fail_dma_init;
 248        }
 249
 250        result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
 251                PS3_MMIO_4K);
 252
 253        if (result) {
 254                pr_debug("%s:%d ps3_mmio_region_init failed\n",
 255                        __func__, __LINE__);
 256                goto fail_mmio_init;
 257        }
 258
 259        result = ps3_system_bus_device_register(&p->dev);
 260
 261        if (result) {
 262                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 263                        __func__, __LINE__);
 264                goto fail_device_register;
 265        }
 266
 267        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 268        return result;
 269
 270fail_device_register:
 271fail_mmio_init:
 272fail_dma_init:
 273fail_find_reg:
 274fail_find_interrupt:
 275        kfree(p);
 276fail_malloc:
 277        pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
 278        return result;
 279}
 280
 281static int __init ps3_setup_ehci_device(
 282        const struct ps3_repository_device *repo)
 283{
 284        return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
 285                PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
 286}
 287
 288static int __init ps3_setup_ohci_device(
 289        const struct ps3_repository_device *repo)
 290{
 291        return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
 292                PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
 293}
 294
 295static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
 296        unsigned int port_number)
 297{
 298        int result;
 299        struct layout {
 300                struct ps3_system_bus_device dev;
 301        } *p;
 302
 303        pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
 304                match_id, port_number);
 305
 306        p = kzalloc(sizeof(struct layout), GFP_KERNEL);
 307
 308        if (!p)
 309                return -ENOMEM;
 310
 311        p->dev.match_id = match_id;
 312        p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
 313        p->dev.port_number = port_number;
 314
 315        result = ps3_system_bus_device_register(&p->dev);
 316
 317        if (result) {
 318                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 319                        __func__, __LINE__);
 320                goto fail_device_register;
 321        }
 322        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 323        return 0;
 324
 325fail_device_register:
 326        kfree(p);
 327        pr_debug(" <- %s:%d fail\n", __func__, __LINE__);
 328        return result;
 329}
 330
 331static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
 332                                 enum ps3_match_id match_id)
 333{
 334        int result;
 335        struct ps3_storage_device *p;
 336        u64 port, blk_size, num_blocks;
 337        unsigned int num_regions, i;
 338
 339        pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);
 340
 341        result = ps3_repository_read_stor_dev_info(repo->bus_index,
 342                                                   repo->dev_index, &port,
 343                                                   &blk_size, &num_blocks,
 344                                                   &num_regions);
 345        if (result) {
 346                printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",
 347                       __func__, __LINE__, result);
 348                return -ENODEV;
 349        }
 350
 351        pr_debug("%s:%u: (%u:%u:%u): port %llu blk_size %llu num_blocks %llu "
 352                 "num_regions %u\n", __func__, __LINE__, repo->bus_index,
 353                 repo->dev_index, repo->dev_type, port, blk_size, num_blocks,
 354                 num_regions);
 355
 356        p = kzalloc(sizeof(struct ps3_storage_device) +
 357                    num_regions * sizeof(struct ps3_storage_region),
 358                    GFP_KERNEL);
 359        if (!p) {
 360                result = -ENOMEM;
 361                goto fail_malloc;
 362        }
 363
 364        p->sbd.match_id = match_id;
 365        p->sbd.dev_type = PS3_DEVICE_TYPE_SB;
 366        p->sbd.bus_id = repo->bus_id;
 367        p->sbd.dev_id = repo->dev_id;
 368        p->sbd.d_region = &p->dma_region;
 369        p->blk_size = blk_size;
 370        p->num_regions = num_regions;
 371
 372        result = ps3_repository_find_interrupt(repo,
 373                                               PS3_INTERRUPT_TYPE_EVENT_PORT,
 374                                               &p->sbd.interrupt_id);
 375        if (result) {
 376                printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,
 377                       __LINE__, result);
 378                result = -ENODEV;
 379                goto fail_find_interrupt;
 380        }
 381
 382        for (i = 0; i < num_regions; i++) {
 383                unsigned int id;
 384                u64 start, size;
 385
 386                result = ps3_repository_read_stor_dev_region(repo->bus_index,
 387                                                             repo->dev_index,
 388                                                             i, &id, &start,
 389                                                             &size);
 390                if (result) {
 391                        printk(KERN_ERR
 392                               "%s:%u: read_stor_dev_region failed %d\n",
 393                               __func__, __LINE__, result);
 394                        result = -ENODEV;
 395                        goto fail_read_region;
 396                }
 397                pr_debug("%s:%u: region %u: id %u start %llu size %llu\n",
 398                         __func__, __LINE__, i, id, start, size);
 399
 400                p->regions[i].id = id;
 401                p->regions[i].start = start;
 402                p->regions[i].size = size;
 403        }
 404
 405        result = ps3_system_bus_device_register(&p->sbd);
 406        if (result) {
 407                pr_debug("%s:%u ps3_system_bus_device_register failed\n",
 408                         __func__, __LINE__);
 409                goto fail_device_register;
 410        }
 411
 412        pr_debug(" <- %s:%u\n", __func__, __LINE__);
 413        return 0;
 414
 415fail_device_register:
 416fail_read_region:
 417fail_find_interrupt:
 418        kfree(p);
 419fail_malloc:
 420        pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);
 421        return result;
 422}
 423
 424static int __init ps3_register_vuart_devices(void)
 425{
 426        int result;
 427        unsigned int port_number;
 428
 429        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 430
 431        result = ps3_repository_read_vuart_av_port(&port_number);
 432        if (result)
 433                port_number = 0; /* av default */
 434
 435        result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
 436        WARN_ON(result);
 437
 438        result = ps3_repository_read_vuart_sysmgr_port(&port_number);
 439        if (result)
 440                port_number = 2; /* sysmgr default */
 441
 442        result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
 443                port_number);
 444        WARN_ON(result);
 445
 446        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 447        return result;
 448}
 449
 450static int __init ps3_register_sound_devices(void)
 451{
 452        int result;
 453        struct layout {
 454                struct ps3_system_bus_device dev;
 455                struct ps3_dma_region d_region;
 456                struct ps3_mmio_region m_region;
 457        } *p;
 458
 459        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 460
 461        p = kzalloc(sizeof(*p), GFP_KERNEL);
 462        if (!p)
 463                return -ENOMEM;
 464
 465        p->dev.match_id = PS3_MATCH_ID_SOUND;
 466        p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
 467        p->dev.d_region = &p->d_region;
 468        p->dev.m_region = &p->m_region;
 469
 470        result = ps3_system_bus_device_register(&p->dev);
 471
 472        if (result) {
 473                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 474                        __func__, __LINE__);
 475                goto fail_device_register;
 476        }
 477        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 478        return 0;
 479
 480fail_device_register:
 481        kfree(p);
 482        pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
 483        return result;
 484}
 485
 486static int __init ps3_register_graphics_devices(void)
 487{
 488        int result;
 489        struct layout {
 490                struct ps3_system_bus_device dev;
 491        } *p;
 492
 493        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 494
 495        p = kzalloc(sizeof(struct layout), GFP_KERNEL);
 496
 497        if (!p)
 498                return -ENOMEM;
 499
 500        p->dev.match_id = PS3_MATCH_ID_GPU;
 501        p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_FB;
 502        p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
 503
 504        result = ps3_system_bus_device_register(&p->dev);
 505
 506        if (result) {
 507                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 508                        __func__, __LINE__);
 509                goto fail_device_register;
 510        }
 511
 512        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 513        return 0;
 514
 515fail_device_register:
 516        kfree(p);
 517        pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
 518        return result;
 519}
 520
 521static int __init ps3_register_ramdisk_device(void)
 522{
 523        int result;
 524        struct layout {
 525                struct ps3_system_bus_device dev;
 526        } *p;
 527
 528        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 529
 530        p = kzalloc(sizeof(struct layout), GFP_KERNEL);
 531
 532        if (!p)
 533                return -ENOMEM;
 534
 535        p->dev.match_id = PS3_MATCH_ID_GPU;
 536        p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK;
 537        p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
 538
 539        result = ps3_system_bus_device_register(&p->dev);
 540
 541        if (result) {
 542                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
 543                        __func__, __LINE__);
 544                goto fail_device_register;
 545        }
 546
 547        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 548        return 0;
 549
 550fail_device_register:
 551        kfree(p);
 552        pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
 553        return result;
 554}
 555
 556/**
 557 * ps3_setup_dynamic_device - Setup a dynamic device from the repository
 558 */
 559
 560static int ps3_setup_dynamic_device(const struct ps3_repository_device *repo)
 561{
 562        int result;
 563
 564        switch (repo->dev_type) {
 565        case PS3_DEV_TYPE_STOR_DISK:
 566                result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
 567
 568                /* Some devices are not accessable from the Other OS lpar. */
 569                if (result == -ENODEV) {
 570                        result = 0;
 571                        pr_debug("%s:%u: not accessable\n", __func__,
 572                                 __LINE__);
 573                }
 574
 575                if (result)
 576                        pr_debug("%s:%u ps3_setup_storage_dev failed\n",
 577                                 __func__, __LINE__);
 578                break;
 579
 580        case PS3_DEV_TYPE_STOR_ROM:
 581                result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);
 582                if (result)
 583                        pr_debug("%s:%u ps3_setup_storage_dev failed\n",
 584                                 __func__, __LINE__);
 585                break;
 586
 587        case PS3_DEV_TYPE_STOR_FLASH:
 588                result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);
 589                if (result)
 590                        pr_debug("%s:%u ps3_setup_storage_dev failed\n",
 591                                 __func__, __LINE__);
 592                break;
 593
 594        default:
 595                result = 0;
 596                pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
 597                        repo->dev_type);
 598        }
 599
 600        return result;
 601}
 602
 603/**
 604 * ps3_setup_static_device - Setup a static device from the repository
 605 */
 606
 607static int __init ps3_setup_static_device(const struct ps3_repository_device *repo)
 608{
 609        int result;
 610
 611        switch (repo->dev_type) {
 612        case PS3_DEV_TYPE_SB_GELIC:
 613                result = ps3_setup_gelic_device(repo);
 614                if (result) {
 615                        pr_debug("%s:%d ps3_setup_gelic_device failed\n",
 616                                __func__, __LINE__);
 617                }
 618                break;
 619        case PS3_DEV_TYPE_SB_USB:
 620
 621                /* Each USB device has both an EHCI and an OHCI HC */
 622
 623                result = ps3_setup_ehci_device(repo);
 624
 625                if (result) {
 626                        pr_debug("%s:%d ps3_setup_ehci_device failed\n",
 627                                __func__, __LINE__);
 628                }
 629
 630                result = ps3_setup_ohci_device(repo);
 631
 632                if (result) {
 633                        pr_debug("%s:%d ps3_setup_ohci_device failed\n",
 634                                __func__, __LINE__);
 635                }
 636                break;
 637
 638        default:
 639                return ps3_setup_dynamic_device(repo);
 640        }
 641
 642        return result;
 643}
 644
 645static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
 646{
 647        struct ps3_repository_device repo;
 648        int res;
 649        unsigned int retries;
 650        unsigned long rem;
 651
 652        /*
 653         * On some firmware versions (e.g. 1.90), the device may not show up
 654         * in the repository immediately
 655         */
 656        for (retries = 0; retries < 10; retries++) {
 657                res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id);
 658                if (!res)
 659                        goto found;
 660
 661                rem = msleep_interruptible(100);
 662                if (rem)
 663                        break;
 664        }
 665        pr_warning("%s:%u: device %llu:%llu not found\n", __func__, __LINE__,
 666                   bus_id, dev_id);
 667        return;
 668
 669found:
 670        if (retries)
 671                pr_debug("%s:%u: device %llu:%llu found after %u retries\n",
 672                         __func__, __LINE__, bus_id, dev_id, retries);
 673
 674        ps3_setup_dynamic_device(&repo);
 675        return;
 676}
 677
 678#define PS3_NOTIFICATION_DEV_ID         ULONG_MAX
 679#define PS3_NOTIFICATION_INTERRUPT_ID   0
 680
 681struct ps3_notification_device {
 682        struct ps3_system_bus_device sbd;
 683        spinlock_t lock;
 684        u64 tag;
 685        u64 lv1_status;
 686        struct completion done;
 687};
 688
 689enum ps3_notify_type {
 690        notify_device_ready = 0,
 691        notify_region_probe = 1,
 692        notify_region_update = 2,
 693};
 694
 695struct ps3_notify_cmd {
 696        u64 operation_code;             /* must be zero */
 697        u64 event_mask;                 /* OR of 1UL << enum ps3_notify_type */
 698};
 699
 700struct ps3_notify_event {
 701        u64 event_type;                 /* enum ps3_notify_type */
 702        u64 bus_id;
 703        u64 dev_id;
 704        u64 dev_type;
 705        u64 dev_port;
 706};
 707
 708static irqreturn_t ps3_notification_interrupt(int irq, void *data)
 709{
 710        struct ps3_notification_device *dev = data;
 711        int res;
 712        u64 tag, status;
 713
 714        spin_lock(&dev->lock);
 715        res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag,
 716                                           &status);
 717        if (tag != dev->tag)
 718                pr_err("%s:%u: tag mismatch, got %llx, expected %llx\n",
 719                       __func__, __LINE__, tag, dev->tag);
 720
 721        if (res) {
 722                pr_err("%s:%u: res %d status 0x%llx\n", __func__, __LINE__, res,
 723                       status);
 724        } else {
 725                pr_debug("%s:%u: completed, status 0x%llx\n", __func__,
 726                         __LINE__, status);
 727                dev->lv1_status = status;
 728                complete(&dev->done);
 729        }
 730        spin_unlock(&dev->lock);
 731        return IRQ_HANDLED;
 732}
 733
 734static int ps3_notification_read_write(struct ps3_notification_device *dev,
 735                                       u64 lpar, int write)
 736{
 737        const char *op = write ? "write" : "read";
 738        unsigned long flags;
 739        int res;
 740
 741        init_completion(&dev->done);
 742        spin_lock_irqsave(&dev->lock, flags);
 743        res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
 744                                        &dev->tag)
 745                    : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
 746                                       &dev->tag);
 747        spin_unlock_irqrestore(&dev->lock, flags);
 748        if (res) {
 749                pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res);
 750                return -EPERM;
 751        }
 752        pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);
 753
 754        res = wait_event_interruptible(dev->done.wait,
 755                                       dev->done.done || kthread_should_stop());
 756        if (kthread_should_stop())
 757                res = -EINTR;
 758        if (res) {
 759                pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op);
 760                return res;
 761        }
 762
 763        if (dev->lv1_status) {
 764                pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__,
 765                       __LINE__, op, dev->lv1_status);
 766                return -EIO;
 767        }
 768        pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op);
 769
 770        return 0;
 771}
 772
 773static struct task_struct *probe_task;
 774
 775/**
 776 * ps3_probe_thread - Background repository probing at system startup.
 777 *
 778 * This implementation only supports background probing on a single bus.
 779 * It uses the hypervisor's storage device notification mechanism to wait until
 780 * a storage device is ready.  The device notification mechanism uses a
 781 * pseudo device to asynchronously notify the guest when storage devices become
 782 * ready.  The notification device has a block size of 512 bytes.
 783 */
 784
 785static int ps3_probe_thread(void *data)
 786{
 787        struct ps3_notification_device dev;
 788        int res;
 789        unsigned int irq;
 790        u64 lpar;
 791        void *buf;
 792        struct ps3_notify_cmd *notify_cmd;
 793        struct ps3_notify_event *notify_event;
 794
 795        pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
 796
 797        buf = kzalloc(512, GFP_KERNEL);
 798        if (!buf)
 799                return -ENOMEM;
 800
 801        lpar = ps3_mm_phys_to_lpar(__pa(buf));
 802        notify_cmd = buf;
 803        notify_event = buf;
 804
 805        /* dummy system bus device */
 806        dev.sbd.bus_id = (u64)data;
 807        dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;
 808        dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;
 809
 810        res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0);
 811        if (res) {
 812                pr_err("%s:%u: lv1_open_device failed %s\n", __func__,
 813                       __LINE__, ps3_result(res));
 814                goto fail_free;
 815        }
 816
 817        res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY,
 818                                              &irq);
 819        if (res) {
 820                pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
 821                       __func__, __LINE__, res);
 822               goto fail_close_device;
 823        }
 824
 825        spin_lock_init(&dev.lock);
 826
 827        res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
 828                          "ps3_notification", &dev);
 829        if (res) {
 830                pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
 831                       res);
 832                goto fail_sb_event_receive_port_destroy;
 833        }
 834
 835        /* Setup and write the request for device notification. */
 836        notify_cmd->operation_code = 0; /* must be zero */
 837        notify_cmd->event_mask = 1UL << notify_region_probe;
 838
 839        res = ps3_notification_read_write(&dev, lpar, 1);
 840        if (res)
 841                goto fail_free_irq;
 842
 843        /* Loop here processing the requested notification events. */
 844        do {
 845                try_to_freeze();
 846
 847                memset(notify_event, 0, sizeof(*notify_event));
 848
 849                res = ps3_notification_read_write(&dev, lpar, 0);
 850                if (res)
 851                        break;
 852
 853                pr_debug("%s:%u: notify event type 0x%llx bus id %llu dev id %llu"
 854                         " type %llu port %llu\n", __func__, __LINE__,
 855                         notify_event->event_type, notify_event->bus_id,
 856                         notify_event->dev_id, notify_event->dev_type,
 857                         notify_event->dev_port);
 858
 859                if (notify_event->event_type != notify_region_probe ||
 860                    notify_event->bus_id != dev.sbd.bus_id) {
 861                        pr_warning("%s:%u: bad notify_event: event %llu, "
 862                                   "dev_id %llu, dev_type %llu\n",
 863                                   __func__, __LINE__, notify_event->event_type,
 864                                   notify_event->dev_id,
 865                                   notify_event->dev_type);
 866                        continue;
 867                }
 868
 869                ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);
 870
 871        } while (!kthread_should_stop());
 872
 873fail_free_irq:
 874        free_irq(irq, &dev);
 875fail_sb_event_receive_port_destroy:
 876        ps3_sb_event_receive_port_destroy(&dev.sbd, irq);
 877fail_close_device:
 878        lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id);
 879fail_free:
 880        kfree(buf);
 881
 882        probe_task = NULL;
 883
 884        pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
 885
 886        return 0;
 887}
 888
 889/**
 890 * ps3_stop_probe_thread - Stops the background probe thread.
 891 *
 892 */
 893
 894static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code,
 895                                 void *data)
 896{
 897        if (probe_task)
 898                kthread_stop(probe_task);
 899        return 0;
 900}
 901
 902static struct notifier_block nb = {
 903        .notifier_call = ps3_stop_probe_thread
 904};
 905
 906/**
 907 * ps3_start_probe_thread - Starts the background probe thread.
 908 *
 909 */
 910
 911static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
 912{
 913        int result;
 914        struct task_struct *task;
 915        struct ps3_repository_device repo;
 916
 917        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 918
 919        memset(&repo, 0, sizeof(repo));
 920
 921        repo.bus_type = bus_type;
 922
 923        result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
 924
 925        if (result) {
 926                printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
 927                return -ENODEV;
 928        }
 929
 930        result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
 931
 932        if (result) {
 933                printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
 934                        result);
 935                return -ENODEV;
 936        }
 937
 938        task = kthread_run(ps3_probe_thread, (void *)repo.bus_id,
 939                           "ps3-probe-%u", bus_type);
 940
 941        if (IS_ERR(task)) {
 942                result = PTR_ERR(task);
 943                printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
 944                       result);
 945                return result;
 946        }
 947
 948        probe_task = task;
 949        register_reboot_notifier(&nb);
 950
 951        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 952        return 0;
 953}
 954
 955/**
 956 * ps3_register_devices - Probe the system and register devices found.
 957 *
 958 * A device_initcall() routine.
 959 */
 960
 961static int __init ps3_register_devices(void)
 962{
 963        int result;
 964
 965        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 966                return -ENODEV;
 967
 968        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 969
 970        /* ps3_repository_dump_bus_info(); */
 971
 972        result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
 973
 974        ps3_register_vuart_devices();
 975
 976        ps3_register_graphics_devices();
 977
 978        ps3_repository_find_devices(PS3_BUS_TYPE_SB, ps3_setup_static_device);
 979
 980        ps3_register_sound_devices();
 981
 982        ps3_register_lpm_devices();
 983
 984        ps3_register_ramdisk_device();
 985
 986        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 987        return 0;
 988}
 989
 990device_initcall(ps3_register_devices);
 991