Path: blob/master/arch/powerpc/platforms/ps3/device-init.c
10818 views
/*1* PS3 device registration routines.2*3* Copyright (C) 2007 Sony Computer Entertainment Inc.4* Copyright 2007 Sony Corp.5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; version 2 of the License.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920#include <linux/delay.h>21#include <linux/freezer.h>22#include <linux/kernel.h>23#include <linux/kthread.h>24#include <linux/init.h>25#include <linux/slab.h>26#include <linux/reboot.h>2728#include <asm/firmware.h>29#include <asm/lv1call.h>30#include <asm/ps3stor.h>3132#include "platform.h"3334static int __init ps3_register_lpm_devices(void)35{36int result;37u64 tmp1;38u64 tmp2;39struct ps3_system_bus_device *dev;4041pr_debug(" -> %s:%d\n", __func__, __LINE__);4243dev = kzalloc(sizeof(*dev), GFP_KERNEL);44if (!dev)45return -ENOMEM;4647dev->match_id = PS3_MATCH_ID_LPM;48dev->dev_type = PS3_DEVICE_TYPE_LPM;4950/* The current lpm driver only supports a single BE processor. */5152result = ps3_repository_read_be_node_id(0, &dev->lpm.node_id);5354if (result) {55pr_debug("%s:%d: ps3_repository_read_be_node_id failed \n",56__func__, __LINE__);57goto fail_read_repo;58}5960result = ps3_repository_read_lpm_privileges(dev->lpm.node_id, &tmp1,61&dev->lpm.rights);6263if (result) {64pr_debug("%s:%d: ps3_repository_read_lpm_privleges failed \n",65__func__, __LINE__);66goto fail_read_repo;67}6869lv1_get_logical_partition_id(&tmp2);7071if (tmp1 != tmp2) {72pr_debug("%s:%d: wrong lpar\n",73__func__, __LINE__);74result = -ENODEV;75goto fail_rights;76}7778if (!(dev->lpm.rights & PS3_LPM_RIGHTS_USE_LPM)) {79pr_debug("%s:%d: don't have rights to use lpm\n",80__func__, __LINE__);81result = -EPERM;82goto fail_rights;83}8485pr_debug("%s:%d: pu_id %llu, rights %llu(%llxh)\n",86__func__, __LINE__, dev->lpm.pu_id, dev->lpm.rights,87dev->lpm.rights);8889result = ps3_repository_read_pu_id(0, &dev->lpm.pu_id);9091if (result) {92pr_debug("%s:%d: ps3_repository_read_pu_id failed \n",93__func__, __LINE__);94goto fail_read_repo;95}9697result = ps3_system_bus_device_register(dev);9899if (result) {100pr_debug("%s:%d ps3_system_bus_device_register failed\n",101__func__, __LINE__);102goto fail_register;103}104105pr_debug(" <- %s:%d\n", __func__, __LINE__);106return 0;107108109fail_register:110fail_rights:111fail_read_repo:112kfree(dev);113pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);114return result;115}116117/**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 the121* structure members, and registers the device instance with the system bus.122*/123124static int __init ps3_setup_gelic_device(125const struct ps3_repository_device *repo)126{127int result;128struct layout {129struct ps3_system_bus_device dev;130struct ps3_dma_region d_region;131} *p;132133pr_debug(" -> %s:%d\n", __func__, __LINE__);134135BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);136BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);137138p = kzalloc(sizeof(struct layout), GFP_KERNEL);139140if (!p) {141result = -ENOMEM;142goto fail_malloc;143}144145p->dev.match_id = PS3_MATCH_ID_GELIC;146p->dev.dev_type = PS3_DEVICE_TYPE_SB;147p->dev.bus_id = repo->bus_id;148p->dev.dev_id = repo->dev_id;149p->dev.d_region = &p->d_region;150151result = ps3_repository_find_interrupt(repo,152PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);153154if (result) {155pr_debug("%s:%d ps3_repository_find_interrupt failed\n",156__func__, __LINE__);157goto fail_find_interrupt;158}159160BUG_ON(p->dev.interrupt_id != 0);161162result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,163PS3_DMA_OTHER, NULL, 0);164165if (result) {166pr_debug("%s:%d ps3_dma_region_init failed\n",167__func__, __LINE__);168goto fail_dma_init;169}170171result = ps3_system_bus_device_register(&p->dev);172173if (result) {174pr_debug("%s:%d ps3_system_bus_device_register failed\n",175__func__, __LINE__);176goto fail_device_register;177}178179pr_debug(" <- %s:%d\n", __func__, __LINE__);180return result;181182fail_device_register:183fail_dma_init:184fail_find_interrupt:185kfree(p);186fail_malloc:187pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);188return result;189}190191static int __init_refok ps3_setup_uhc_device(192const struct ps3_repository_device *repo, enum ps3_match_id match_id,193enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)194{195int result;196struct layout {197struct ps3_system_bus_device dev;198struct ps3_dma_region d_region;199struct ps3_mmio_region m_region;200} *p;201u64 bus_addr;202u64 len;203204pr_debug(" -> %s:%d\n", __func__, __LINE__);205206BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);207BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);208209p = kzalloc(sizeof(struct layout), GFP_KERNEL);210211if (!p) {212result = -ENOMEM;213goto fail_malloc;214}215216p->dev.match_id = match_id;217p->dev.dev_type = PS3_DEVICE_TYPE_SB;218p->dev.bus_id = repo->bus_id;219p->dev.dev_id = repo->dev_id;220p->dev.d_region = &p->d_region;221p->dev.m_region = &p->m_region;222223result = ps3_repository_find_interrupt(repo,224interrupt_type, &p->dev.interrupt_id);225226if (result) {227pr_debug("%s:%d ps3_repository_find_interrupt failed\n",228__func__, __LINE__);229goto fail_find_interrupt;230}231232result = ps3_repository_find_reg(repo, reg_type,233&bus_addr, &len);234235if (result) {236pr_debug("%s:%d ps3_repository_find_reg failed\n",237__func__, __LINE__);238goto fail_find_reg;239}240241result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,242PS3_DMA_INTERNAL, NULL, 0);243244if (result) {245pr_debug("%s:%d ps3_dma_region_init failed\n",246__func__, __LINE__);247goto fail_dma_init;248}249250result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,251PS3_MMIO_4K);252253if (result) {254pr_debug("%s:%d ps3_mmio_region_init failed\n",255__func__, __LINE__);256goto fail_mmio_init;257}258259result = ps3_system_bus_device_register(&p->dev);260261if (result) {262pr_debug("%s:%d ps3_system_bus_device_register failed\n",263__func__, __LINE__);264goto fail_device_register;265}266267pr_debug(" <- %s:%d\n", __func__, __LINE__);268return result;269270fail_device_register:271fail_mmio_init:272fail_dma_init:273fail_find_reg:274fail_find_interrupt:275kfree(p);276fail_malloc:277pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);278return result;279}280281static int __init ps3_setup_ehci_device(282const struct ps3_repository_device *repo)283{284return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,285PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);286}287288static int __init ps3_setup_ohci_device(289const struct ps3_repository_device *repo)290{291return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,292PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);293}294295static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,296unsigned int port_number)297{298int result;299struct layout {300struct ps3_system_bus_device dev;301} *p;302303pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,304match_id, port_number);305306p = kzalloc(sizeof(struct layout), GFP_KERNEL);307308if (!p)309return -ENOMEM;310311p->dev.match_id = match_id;312p->dev.dev_type = PS3_DEVICE_TYPE_VUART;313p->dev.port_number = port_number;314315result = ps3_system_bus_device_register(&p->dev);316317if (result) {318pr_debug("%s:%d ps3_system_bus_device_register failed\n",319__func__, __LINE__);320goto fail_device_register;321}322pr_debug(" <- %s:%d\n", __func__, __LINE__);323return 0;324325fail_device_register:326kfree(p);327pr_debug(" <- %s:%d fail\n", __func__, __LINE__);328return result;329}330331static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,332enum ps3_match_id match_id)333{334int result;335struct ps3_storage_device *p;336u64 port, blk_size, num_blocks;337unsigned int num_regions, i;338339pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);340341result = ps3_repository_read_stor_dev_info(repo->bus_index,342repo->dev_index, &port,343&blk_size, &num_blocks,344&num_regions);345if (result) {346printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",347__func__, __LINE__, result);348return -ENODEV;349}350351pr_debug("%s:%u: (%u:%u:%u): port %llu blk_size %llu num_blocks %llu "352"num_regions %u\n", __func__, __LINE__, repo->bus_index,353repo->dev_index, repo->dev_type, port, blk_size, num_blocks,354num_regions);355356p = kzalloc(sizeof(struct ps3_storage_device) +357num_regions * sizeof(struct ps3_storage_region),358GFP_KERNEL);359if (!p) {360result = -ENOMEM;361goto fail_malloc;362}363364p->sbd.match_id = match_id;365p->sbd.dev_type = PS3_DEVICE_TYPE_SB;366p->sbd.bus_id = repo->bus_id;367p->sbd.dev_id = repo->dev_id;368p->sbd.d_region = &p->dma_region;369p->blk_size = blk_size;370p->num_regions = num_regions;371372result = ps3_repository_find_interrupt(repo,373PS3_INTERRUPT_TYPE_EVENT_PORT,374&p->sbd.interrupt_id);375if (result) {376printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,377__LINE__, result);378result = -ENODEV;379goto fail_find_interrupt;380}381382for (i = 0; i < num_regions; i++) {383unsigned int id;384u64 start, size;385386result = ps3_repository_read_stor_dev_region(repo->bus_index,387repo->dev_index,388i, &id, &start,389&size);390if (result) {391printk(KERN_ERR392"%s:%u: read_stor_dev_region failed %d\n",393__func__, __LINE__, result);394result = -ENODEV;395goto fail_read_region;396}397pr_debug("%s:%u: region %u: id %u start %llu size %llu\n",398__func__, __LINE__, i, id, start, size);399400p->regions[i].id = id;401p->regions[i].start = start;402p->regions[i].size = size;403}404405result = ps3_system_bus_device_register(&p->sbd);406if (result) {407pr_debug("%s:%u ps3_system_bus_device_register failed\n",408__func__, __LINE__);409goto fail_device_register;410}411412pr_debug(" <- %s:%u\n", __func__, __LINE__);413return 0;414415fail_device_register:416fail_read_region:417fail_find_interrupt:418kfree(p);419fail_malloc:420pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);421return result;422}423424static int __init ps3_register_vuart_devices(void)425{426int result;427unsigned int port_number;428429pr_debug(" -> %s:%d\n", __func__, __LINE__);430431result = ps3_repository_read_vuart_av_port(&port_number);432if (result)433port_number = 0; /* av default */434435result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);436WARN_ON(result);437438result = ps3_repository_read_vuart_sysmgr_port(&port_number);439if (result)440port_number = 2; /* sysmgr default */441442result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,443port_number);444WARN_ON(result);445446pr_debug(" <- %s:%d\n", __func__, __LINE__);447return result;448}449450static int __init ps3_register_sound_devices(void)451{452int result;453struct layout {454struct ps3_system_bus_device dev;455struct ps3_dma_region d_region;456struct ps3_mmio_region m_region;457} *p;458459pr_debug(" -> %s:%d\n", __func__, __LINE__);460461p = kzalloc(sizeof(*p), GFP_KERNEL);462if (!p)463return -ENOMEM;464465p->dev.match_id = PS3_MATCH_ID_SOUND;466p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;467p->dev.d_region = &p->d_region;468p->dev.m_region = &p->m_region;469470result = ps3_system_bus_device_register(&p->dev);471472if (result) {473pr_debug("%s:%d ps3_system_bus_device_register failed\n",474__func__, __LINE__);475goto fail_device_register;476}477pr_debug(" <- %s:%d\n", __func__, __LINE__);478return 0;479480fail_device_register:481kfree(p);482pr_debug(" <- %s:%d failed\n", __func__, __LINE__);483return result;484}485486static int __init ps3_register_graphics_devices(void)487{488int result;489struct layout {490struct ps3_system_bus_device dev;491} *p;492493pr_debug(" -> %s:%d\n", __func__, __LINE__);494495p = kzalloc(sizeof(struct layout), GFP_KERNEL);496497if (!p)498return -ENOMEM;499500p->dev.match_id = PS3_MATCH_ID_GPU;501p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_FB;502p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;503504result = ps3_system_bus_device_register(&p->dev);505506if (result) {507pr_debug("%s:%d ps3_system_bus_device_register failed\n",508__func__, __LINE__);509goto fail_device_register;510}511512pr_debug(" <- %s:%d\n", __func__, __LINE__);513return 0;514515fail_device_register:516kfree(p);517pr_debug(" <- %s:%d failed\n", __func__, __LINE__);518return result;519}520521static int __init ps3_register_ramdisk_device(void)522{523int result;524struct layout {525struct ps3_system_bus_device dev;526} *p;527528pr_debug(" -> %s:%d\n", __func__, __LINE__);529530p = kzalloc(sizeof(struct layout), GFP_KERNEL);531532if (!p)533return -ENOMEM;534535p->dev.match_id = PS3_MATCH_ID_GPU;536p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK;537p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;538539result = ps3_system_bus_device_register(&p->dev);540541if (result) {542pr_debug("%s:%d ps3_system_bus_device_register failed\n",543__func__, __LINE__);544goto fail_device_register;545}546547pr_debug(" <- %s:%d\n", __func__, __LINE__);548return 0;549550fail_device_register:551kfree(p);552pr_debug(" <- %s:%d failed\n", __func__, __LINE__);553return result;554}555556/**557* ps3_setup_dynamic_device - Setup a dynamic device from the repository558*/559560static int ps3_setup_dynamic_device(const struct ps3_repository_device *repo)561{562int result;563564switch (repo->dev_type) {565case PS3_DEV_TYPE_STOR_DISK:566result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);567568/* Some devices are not accessible from the Other OS lpar. */569if (result == -ENODEV) {570result = 0;571pr_debug("%s:%u: not accessible\n", __func__,572__LINE__);573}574575if (result)576pr_debug("%s:%u ps3_setup_storage_dev failed\n",577__func__, __LINE__);578break;579580case PS3_DEV_TYPE_STOR_ROM:581result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);582if (result)583pr_debug("%s:%u ps3_setup_storage_dev failed\n",584__func__, __LINE__);585break;586587case PS3_DEV_TYPE_STOR_FLASH:588result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);589if (result)590pr_debug("%s:%u ps3_setup_storage_dev failed\n",591__func__, __LINE__);592break;593594default:595result = 0;596pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,597repo->dev_type);598}599600return result;601}602603/**604* ps3_setup_static_device - Setup a static device from the repository605*/606607static int __init ps3_setup_static_device(const struct ps3_repository_device *repo)608{609int result;610611switch (repo->dev_type) {612case PS3_DEV_TYPE_SB_GELIC:613result = ps3_setup_gelic_device(repo);614if (result) {615pr_debug("%s:%d ps3_setup_gelic_device failed\n",616__func__, __LINE__);617}618break;619case PS3_DEV_TYPE_SB_USB:620621/* Each USB device has both an EHCI and an OHCI HC */622623result = ps3_setup_ehci_device(repo);624625if (result) {626pr_debug("%s:%d ps3_setup_ehci_device failed\n",627__func__, __LINE__);628}629630result = ps3_setup_ohci_device(repo);631632if (result) {633pr_debug("%s:%d ps3_setup_ohci_device failed\n",634__func__, __LINE__);635}636break;637638default:639return ps3_setup_dynamic_device(repo);640}641642return result;643}644645static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)646{647struct ps3_repository_device repo;648int res;649unsigned int retries;650unsigned long rem;651652/*653* On some firmware versions (e.g. 1.90), the device may not show up654* in the repository immediately655*/656for (retries = 0; retries < 10; retries++) {657res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id);658if (!res)659goto found;660661rem = msleep_interruptible(100);662if (rem)663break;664}665pr_warning("%s:%u: device %llu:%llu not found\n", __func__, __LINE__,666bus_id, dev_id);667return;668669found:670if (retries)671pr_debug("%s:%u: device %llu:%llu found after %u retries\n",672__func__, __LINE__, bus_id, dev_id, retries);673674ps3_setup_dynamic_device(&repo);675return;676}677678#define PS3_NOTIFICATION_DEV_ID ULONG_MAX679#define PS3_NOTIFICATION_INTERRUPT_ID 0680681struct ps3_notification_device {682struct ps3_system_bus_device sbd;683spinlock_t lock;684u64 tag;685u64 lv1_status;686struct completion done;687};688689enum ps3_notify_type {690notify_device_ready = 0,691notify_region_probe = 1,692notify_region_update = 2,693};694695struct ps3_notify_cmd {696u64 operation_code; /* must be zero */697u64 event_mask; /* OR of 1UL << enum ps3_notify_type */698};699700struct ps3_notify_event {701u64 event_type; /* enum ps3_notify_type */702u64 bus_id;703u64 dev_id;704u64 dev_type;705u64 dev_port;706};707708static irqreturn_t ps3_notification_interrupt(int irq, void *data)709{710struct ps3_notification_device *dev = data;711int res;712u64 tag, status;713714spin_lock(&dev->lock);715res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag,716&status);717if (tag != dev->tag)718pr_err("%s:%u: tag mismatch, got %llx, expected %llx\n",719__func__, __LINE__, tag, dev->tag);720721if (res) {722pr_err("%s:%u: res %d status 0x%llx\n", __func__, __LINE__, res,723status);724} else {725pr_debug("%s:%u: completed, status 0x%llx\n", __func__,726__LINE__, status);727dev->lv1_status = status;728complete(&dev->done);729}730spin_unlock(&dev->lock);731return IRQ_HANDLED;732}733734static int ps3_notification_read_write(struct ps3_notification_device *dev,735u64 lpar, int write)736{737const char *op = write ? "write" : "read";738unsigned long flags;739int res;740741init_completion(&dev->done);742spin_lock_irqsave(&dev->lock, flags);743res = 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);747spin_unlock_irqrestore(&dev->lock, flags);748if (res) {749pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res);750return -EPERM;751}752pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);753754res = wait_event_interruptible(dev->done.wait,755dev->done.done || kthread_should_stop());756if (kthread_should_stop())757res = -EINTR;758if (res) {759pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op);760return res;761}762763if (dev->lv1_status) {764pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__,765__LINE__, op, dev->lv1_status);766return -EIO;767}768pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op);769770return 0;771}772773static struct task_struct *probe_task;774775/**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 until780* a storage device is ready. The device notification mechanism uses a781* pseudo device to asynchronously notify the guest when storage devices become782* ready. The notification device has a block size of 512 bytes.783*/784785static int ps3_probe_thread(void *data)786{787struct ps3_notification_device dev;788int res;789unsigned int irq;790u64 lpar;791void *buf;792struct ps3_notify_cmd *notify_cmd;793struct ps3_notify_event *notify_event;794795pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);796797buf = kzalloc(512, GFP_KERNEL);798if (!buf)799return -ENOMEM;800801lpar = ps3_mm_phys_to_lpar(__pa(buf));802notify_cmd = buf;803notify_event = buf;804805/* dummy system bus device */806dev.sbd.bus_id = (u64)data;807dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;808dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;809810res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0);811if (res) {812pr_err("%s:%u: lv1_open_device failed %s\n", __func__,813__LINE__, ps3_result(res));814goto fail_free;815}816817res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY,818&irq);819if (res) {820pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n",821__func__, __LINE__, res);822goto fail_close_device;823}824825spin_lock_init(&dev.lock);826827res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,828"ps3_notification", &dev);829if (res) {830pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,831res);832goto fail_sb_event_receive_port_destroy;833}834835/* Setup and write the request for device notification. */836notify_cmd->operation_code = 0; /* must be zero */837notify_cmd->event_mask = 1UL << notify_region_probe;838839res = ps3_notification_read_write(&dev, lpar, 1);840if (res)841goto fail_free_irq;842843/* Loop here processing the requested notification events. */844do {845try_to_freeze();846847memset(notify_event, 0, sizeof(*notify_event));848849res = ps3_notification_read_write(&dev, lpar, 0);850if (res)851break;852853pr_debug("%s:%u: notify event type 0x%llx bus id %llu dev id %llu"854" type %llu port %llu\n", __func__, __LINE__,855notify_event->event_type, notify_event->bus_id,856notify_event->dev_id, notify_event->dev_type,857notify_event->dev_port);858859if (notify_event->event_type != notify_region_probe ||860notify_event->bus_id != dev.sbd.bus_id) {861pr_warning("%s:%u: bad notify_event: event %llu, "862"dev_id %llu, dev_type %llu\n",863__func__, __LINE__, notify_event->event_type,864notify_event->dev_id,865notify_event->dev_type);866continue;867}868869ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);870871} while (!kthread_should_stop());872873fail_free_irq:874free_irq(irq, &dev);875fail_sb_event_receive_port_destroy:876ps3_sb_event_receive_port_destroy(&dev.sbd, irq);877fail_close_device:878lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id);879fail_free:880kfree(buf);881882probe_task = NULL;883884pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);885886return 0;887}888889/**890* ps3_stop_probe_thread - Stops the background probe thread.891*892*/893894static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code,895void *data)896{897if (probe_task)898kthread_stop(probe_task);899return 0;900}901902static struct notifier_block nb = {903.notifier_call = ps3_stop_probe_thread904};905906/**907* ps3_start_probe_thread - Starts the background probe thread.908*909*/910911static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)912{913int result;914struct task_struct *task;915struct ps3_repository_device repo;916917pr_debug(" -> %s:%d\n", __func__, __LINE__);918919memset(&repo, 0, sizeof(repo));920921repo.bus_type = bus_type;922923result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);924925if (result) {926printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);927return -ENODEV;928}929930result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);931932if (result) {933printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,934result);935return -ENODEV;936}937938task = kthread_run(ps3_probe_thread, (void *)repo.bus_id,939"ps3-probe-%u", bus_type);940941if (IS_ERR(task)) {942result = PTR_ERR(task);943printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,944result);945return result;946}947948probe_task = task;949register_reboot_notifier(&nb);950951pr_debug(" <- %s:%d\n", __func__, __LINE__);952return 0;953}954955/**956* ps3_register_devices - Probe the system and register devices found.957*958* A device_initcall() routine.959*/960961static int __init ps3_register_devices(void)962{963int result;964965if (!firmware_has_feature(FW_FEATURE_PS3_LV1))966return -ENODEV;967968pr_debug(" -> %s:%d\n", __func__, __LINE__);969970/* ps3_repository_dump_bus_info(); */971972result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);973974ps3_register_vuart_devices();975976ps3_register_graphics_devices();977978ps3_repository_find_devices(PS3_BUS_TYPE_SB, ps3_setup_static_device);979980ps3_register_sound_devices();981982ps3_register_lpm_devices();983984ps3_register_ramdisk_device();985986pr_debug(" <- %s:%d\n", __func__, __LINE__);987return 0;988}989990device_initcall(ps3_register_devices);991992993