static int ps3_ohci_remove(struct ps3_system_bus_device *dev) { unsigned int tmp; struct usb_hcd *hcd = ps3_system_bus_get_drvdata(dev); BUG_ON(!hcd); dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); tmp = hcd->irq; ohci_shutdown(hcd); usb_remove_hcd(hcd); ps3_system_bus_set_drvdata(dev, NULL); BUG_ON(!hcd->regs); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); ps3_io_irq_destroy(tmp); ps3_free_mmio_region(dev->m_region); ps3_dma_region_free(dev->d_region); ps3_close_hv_device(dev); return 0; }
static int ps3flash_remove(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); ps3_os_area_flash_register(NULL); misc_deregister(&ps3flash_misc); ps3stor_teardown(dev); kfree(ps3_system_bus_get_drvdata(&dev->sbd)); ps3_system_bus_set_drvdata(&dev->sbd, NULL); ps3flash_dev = NULL; return 0; }
static int ps3encdec_remove(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); misc_deregister(&ps3encdec_misc); ps3stor_teardown(dev); kfree(ps3_system_bus_get_drvdata(&dev->sbd)); ps3_system_bus_set_drvdata(&dev->sbd, NULL); kfree(dev->bounce_buf); ps3encdec_dev = NULL; return 0; }
static int ps3flash_read_write_sectors(struct ps3_storage_device *dev, u64 start_sector, int write) { struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, start_sector, priv->chunk_sectors, write); if (res) { dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__, __LINE__, write ? "write" : "read", res); return -EIO; } return 0; }
static int ps3flash_writeback(struct ps3_storage_device *dev) { struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); int res; if (!priv->dirty || priv->tag < 0) return 0; res = ps3flash_read_write_sectors(dev, priv->tag, 1); if (res) return res; priv->dirty = false; return 0; }
static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector) { struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); int res; if (start_sector == priv->tag) return 0; res = ps3flash_writeback(dev); if (res) return res; priv->tag = -1; res = ps3flash_read_write_sectors(dev, start_sector, 0); if (res) return res; priv->tag = start_sector; return 0; }
static ssize_t ps3flash_write(const char __user *userbuf, const void *kernelbuf, size_t count, loff_t *pos) { struct ps3_storage_device *dev = ps3flash_dev; struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); u64 size, sector, offset; int res = 0; size_t remaining, n; void *dst; dev_dbg(&dev->sbd.core, "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n", __func__, __LINE__, count, *pos, userbuf, kernelbuf); size = dev->regions[dev->region_idx].size*dev->blk_size; if (*pos >= size || !count) return 0; if (*pos + count > size) { dev_dbg(&dev->sbd.core, "%s:%u Truncating count from %zu to %llu\n", __func__, __LINE__, count, size - *pos); count = size - *pos; } sector = *pos / dev->bounce_size * priv->chunk_sectors; offset = *pos % dev->bounce_size; remaining = count; do { n = min_t(u64, remaining, dev->bounce_size - offset); dst = dev->bounce_buf + offset; mutex_lock(&priv->mutex); if (n != dev->bounce_size) res = ps3flash_fetch(dev, sector); else if (sector != priv->tag) res = ps3flash_writeback(dev); if (res) goto fail; dev_dbg(&dev->sbd.core, "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n", __func__, __LINE__, n, userbuf, kernelbuf, dst); if (userbuf) { if (copy_from_user(dst, userbuf, n)) { res = -EFAULT; goto fail; } userbuf += n; } if (kernelbuf) { memcpy(dst, kernelbuf, n); kernelbuf += n; } priv->tag = sector; priv->dirty = true; mutex_unlock(&priv->mutex); *pos += n; remaining -= n; sector += priv->chunk_sectors; offset = 0; } while (remaining > 0); return count; fail: mutex_unlock(&priv->mutex); return res; }
static long ps3encdec_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ps3_storage_device *dev = ps3encdec_dev; struct ps3encdec_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); void __user *argp = (void __user *) arg; int res = -EFAULT; mutex_lock(&priv->mutex); pr_debug("%s:%d cmd %x\n", __func__, __LINE__, cmd); switch (cmd) { case PS3ENCDEC_IOCTL_DO_REQUEST: { struct ps3encdec_ioctl_do_request do_request; void *cmdbuf; u64 cmdbuf_lpar; if (copy_from_user(&do_request, argp, sizeof(do_request))) { pr_debug("%s:%d: copy_from_user failed\n", __func__, __LINE__); res = -EFAULT; break; } BUG_ON(do_request.respbuf_size > BOUNCE_SIZE); pr_debug("%s:%d: cmd (%llx) cmdbuf_size (%lld) respbuf_size (%lld)\n", __func__, __LINE__, do_request.cmd, do_request.cmdbuf_size, do_request.respbuf_size); cmdbuf = kmalloc(do_request.cmdbuf_size, GFP_KERNEL); if (!cmdbuf) { pr_debug("%s:%d: kmalloc failed\n", __func__, __LINE__); res = -ENOMEM; break; } if (copy_from_user(cmdbuf, (const void __user *) do_request.cmdbuf, do_request.cmdbuf_size)) { pr_debug("%s:%d: copy_from_user failed\n", __func__, __LINE__); res = -EFAULT; goto kfree_cmdbuf; } cmdbuf_lpar = ps3_mm_phys_to_lpar(__pa(cmdbuf)); res = ps3stor_send_command(dev, do_request.cmd, cmdbuf_lpar, do_request.cmdbuf_size, dev->bounce_lpar, do_request.respbuf_size); if (res) { pr_debug("%s:%d: ps3stor_send_command failed (%d)\n", __func__, __LINE__, res); res = -EFAULT; goto kfree_cmdbuf; } if (copy_to_user((void __user *) do_request.respbuf, dev->bounce_buf, do_request.respbuf_size)) { pr_debug("%s:%d: copy_to_user failed\n", __func__, __LINE__); res = -EFAULT; goto kfree_cmdbuf; } res = 0; kfree_cmdbuf: kfree(cmdbuf); break; } } mutex_unlock(&priv->mutex); return res; }