static void gelic_debug_shutdown(void) { if (bus_addr) unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, sizeof(dbg)); lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID); }
static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev) { int result; BUG_ON(!dev->bus_id); mutex_lock(&usage_hack.mutex); if (ps3_is_device(dev, 1, 1)) { usage_hack.sb_11--; if (usage_hack.sb_11) { result = 0; goto done; } } if (ps3_is_device(dev, 1, 2)) { usage_hack.sb_12--; if (usage_hack.sb_12) { result = 0; goto done; } } result = lv1_close_device(dev->bus_id, dev->dev_id); BUG_ON(result); done: mutex_unlock(&usage_hack.mutex); return result; }
static int ps3_probe_thread(void *data) { struct ps3_notification_device dev; int res; unsigned int irq; u64 lpar; void *buf; struct ps3_notify_cmd *notify_cmd; struct ps3_notify_event *notify_event; pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); buf = kzalloc(512, GFP_KERNEL); if (!buf) return -ENOMEM; lpar = ps3_mm_phys_to_lpar(__pa(buf)); notify_cmd = buf; notify_event = buf; /* dummy system bus device */ dev.sbd.bus_id = (u64)data; dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID; dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID; res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0); if (res) { pr_err("%s:%u: lv1_open_device failed %s\n", __func__, __LINE__, ps3_result(res)); goto fail_free; } res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY, &irq); if (res) { pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n", __func__, __LINE__, res); goto fail_close_device; } spin_lock_init(&dev.lock); res = request_irq(irq, ps3_notification_interrupt, 0, "ps3_notification", &dev); if (res) { pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__, res); goto fail_sb_event_receive_port_destroy; } /* Setup and write the request for device notification. */ notify_cmd->operation_code = 0; /* must be zero */ notify_cmd->event_mask = 1UL << notify_region_probe; res = ps3_notification_read_write(&dev, lpar, 1); if (res) goto fail_free_irq; /* Loop here processing the requested notification events. */ do { try_to_freeze(); memset(notify_event, 0, sizeof(*notify_event)); res = ps3_notification_read_write(&dev, lpar, 0); if (res) break; pr_debug("%s:%u: notify event type 0x%llx bus id %llu dev id %llu" " type %llu port %llu\n", __func__, __LINE__, notify_event->event_type, notify_event->bus_id, notify_event->dev_id, notify_event->dev_type, notify_event->dev_port); if (notify_event->event_type != notify_region_probe || notify_event->bus_id != dev.sbd.bus_id) { pr_warning("%s:%u: bad notify_event: event %llu, " "dev_id %llu, dev_type %llu\n", __func__, __LINE__, notify_event->event_type, notify_event->dev_id, notify_event->dev_type); continue; } ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id); } while (!kthread_should_stop()); fail_free_irq: free_irq(irq, &dev); fail_sb_event_receive_port_destroy: ps3_sb_event_receive_port_destroy(&dev.sbd, irq); fail_close_device: lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id); fail_free: kfree(buf); probe_task = NULL; pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); return 0; }
int ps3stor_setup(struct ps3_stordev *sd, int type) { unsigned int i; int err; sd->sd_type = type; err = ps3repo_find_bus_by_type(PS3_BUS_TYPE_STOR, &sd->sd_busidx); if (err) goto out; err = ps3repo_read_bus_id(sd->sd_busidx, &sd->sd_busid); if (err) goto out; err = ps3repo_find_bus_dev_by_type(sd->sd_busidx, type, &sd->sd_devidx); if (err) goto out; err = ps3repo_read_bus_dev_id(sd->sd_busidx, sd->sd_devidx, &sd->sd_devid); if (err) goto out; err = ps3repo_read_bus_dev_blk_size(sd->sd_busidx, sd->sd_devidx, &sd->sd_blksize); if (err) goto out; err = ps3repo_read_bus_dev_nblocks(sd->sd_busidx, sd->sd_devidx, &sd->sd_nblocks); if (err) goto out; err = ps3repo_read_bus_dev_nregs(sd->sd_busidx, sd->sd_devidx, &sd->sd_nregs); if (err) goto out; for (i = 0; i < sd->sd_nregs; i++) { err = ps3repo_read_bus_dev_reg_id(sd->sd_busidx, sd->sd_devidx, i, &sd->sd_regs[i].sr_id); if (err) goto out; err = ps3repo_read_bus_dev_reg_start(sd->sd_busidx, sd->sd_devidx, i, &sd->sd_regs[i].sr_start); if (err) goto out; err = ps3repo_read_bus_dev_reg_size(sd->sd_busidx, sd->sd_devidx, i, &sd->sd_regs[i].sr_size); if (err) goto out; } if (!sd->sd_nregs) { err = ENODEV; goto out; } err = lv1_open_device(sd->sd_busid, sd->sd_devid, 0); if (err) goto out; err = lv1_setup_dma(sd->sd_busid, sd->sd_devid, &sd->sd_dmabase); if (err) goto close_dev; return 0; close_dev: lv1_close_device(sd->sd_busid, sd->sd_devid); out: return err; }
static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) { int error = -ENODEV; int result; const u64 notification_dev_id = (u64)-1LL; const unsigned int timeout = HZ; u64 lpar; u64 tag; void *buf; enum ps3_notify_type { notify_device_ready = 0, notify_region_probe = 1, notify_region_update = 2, }; struct { u64 operation_code; /* must be zero */ u64 event_mask; /* OR of 1UL << enum ps3_notify_type */ } *notify_cmd; struct { u64 event_type; /* enum ps3_notify_type */ u64 bus_id; u64 dev_id; u64 dev_type; u64 dev_port; } *notify_event; pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id, repo->dev_id, repo->dev_type); buf = kzalloc(512, GFP_KERNEL); if (!buf) return -ENOMEM; lpar = ps3_mm_phys_to_lpar(__pa(buf)); notify_cmd = buf; notify_event = buf; result = lv1_open_device(repo->bus_id, notification_dev_id, 0); if (result) { printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, __LINE__, ps3_result(result)); goto fail_free; } /* Setup and write the request for device notification. */ notify_cmd->operation_code = 0; /* must be zero */ notify_cmd->event_mask = 1UL << notify_region_probe; result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, &tag); if (result) { printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, ps3_result(result)); goto fail_close; } /* Wait for the write completion */ result = ps3stor_wait_for_completion(notification_dev_id, tag, timeout); if (result) { printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, __LINE__, ps3_result(result)); goto fail_close; } /* Loop here processing the requested notification events. */ while (1) { memset(notify_event, 0, sizeof(*notify_event)); result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, lpar, &tag); if (result) { printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, ps3_result(result)); break; } result = ps3stor_wait_for_completion(notification_dev_id, tag, timeout); if (result) { printk(KERN_ERR "%s:%u: read not completed %s\n", __func__, __LINE__, ps3_result(result)); break; } pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, " "port %lu\n", __func__, __LINE__, repo->bus_index, repo->dev_index, repo->dev_type, notify_event->event_type, notify_event->dev_port); if (notify_event->event_type != notify_region_probe || notify_event->bus_id != repo->bus_id) { pr_debug("%s:%u: bad notify_event: event %lu, " "dev_id %lu, dev_type %lu\n", __func__, __LINE__, notify_event->event_type, notify_event->dev_id, notify_event->dev_type); break; } if (notify_event->dev_id == repo->dev_id && notify_event->dev_type == repo->dev_type) { pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__, __LINE__, repo->bus_index, repo->dev_index, repo->dev_type); error = 0; break; } if (notify_event->dev_id == repo->dev_id && notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { pr_debug("%s:%u: no access: dev_id %u\n", __func__, __LINE__, repo->dev_id); break; } } fail_close: lv1_close_device(repo->bus_id, notification_dev_id); fail_free: kfree(buf); pr_debug(" <- %s:%u\n", __func__, __LINE__); return error; }