Exemple #1
0
/**
 *	ps3stor_read_write_sectors - read/write from/to a storage device
 *	@dev: Pointer to a struct ps3_storage_device
 *	@lpar: HV logical partition address
 *	@start_sector: First sector to read/write
 *	@sectors: Number of sectors to read/write
 *	@write: Flag indicating write (non-zero) or read (zero)
 *
 *	Returns 0 for success, -1 in case of failure to submit the command, or
 *	an LV1 status value in case of other errors
 */
u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
			       u64 start_sector, u64 sectors, int write)
{
	unsigned int region_id = dev->regions[dev->region_idx].id;
	const char *op = write ? "write" : "read";
	int res;

	dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
		__func__, __LINE__, op, sectors, start_sector);

	init_completion(&dev->done);
	res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
					start_sector, sectors, 0, lpar,
					&dev->tag)
		    : lv1_storage_read(dev->sbd.dev_id, region_id,
				       start_sector, sectors, 0, lpar,
				       &dev->tag);
	if (res) {
		dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
			__LINE__, op, res);
		return -1;
	}

	wait_for_completion(&dev->done);
	if (dev->lv1_status) {
		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
			__LINE__, op, dev->lv1_status);
		return dev->lv1_status;
	}

	dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
		op);

	return 0;
}
Exemple #2
0
int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx,
        uint64_t start_sector, uint64_t sector_count, uint64_t flags, char *buf)
{
#define MIN(a, b)			((a) <= (b) ? (a) : (b))
#define BOUNCE_SECTORS			(sizeof(dma_buf) / sd->sd_blksize)
#define ASYNC_STATUS_POLL_PERIOD	100 /* microseconds */

	struct ps3_storreg *reg = &sd->sd_regs[regidx];
	uint64_t nleft, nread, nsectors;
	uint64_t tag, status;
	unsigned int timeout;
	int err = 0;

	nleft = sector_count;
	nread = 0;

	while (nleft) {
		nsectors = MIN(nleft, BOUNCE_SECTORS);

		err = lv1_storage_read(sd->sd_devid, reg->sr_id,
		    start_sector + nread, nsectors, flags, (uint32_t)dma_buf,
		    &tag);
		if (err)
			return err;

		timeout = 5000000; /* microseconds */

		while (1) {
			if (timeout < ASYNC_STATUS_POLL_PERIOD)
				return ETIMEDOUT;

			err = lv1_storage_check_async_status(sd->sd_devid, tag,
			    &status);
			if (!err && !status)
				break;

			delay(ASYNC_STATUS_POLL_PERIOD);
			timeout -= ASYNC_STATUS_POLL_PERIOD;
		}

		if (status != 0)
			return EIO;

		memcpy(buf + nread * sd->sd_blksize, (u_char *)dma_buf,
		    nsectors * sd->sd_blksize);
		nread += nsectors;
		nleft -= nsectors;
	}

	return err;

#undef MIN
#undef BOUNCE_SECTORS
#undef ASYNC_STATUS_POLL_PERIOD
}
static int ps3rom_read_request(struct ps3_storage_device *dev,
			       struct scsi_cmnd *cmd, u32 start_sector,
			       u32 sectors)
{
	int res;

	dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
		__func__, __LINE__, sectors, start_sector);

	res = lv1_storage_read(dev->sbd.dev_id,
			       dev->regions[dev->region_idx].id, start_sector,
			       sectors, 0, dev->bounce_lpar, &dev->tag);
	if (res) {
		dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
			__LINE__, res);
		return DID_ERROR << 16;
	}

	return 0;
}
static int ps3_notification_read_write(struct ps3_notification_device *dev,
				       u64 lpar, int write)
{
	const char *op = write ? "write" : "read";
	unsigned long flags;
	int res;

	init_completion(&dev->done);
	spin_lock_irqsave(&dev->lock, flags);
	res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
					&dev->tag)
		    : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
				       &dev->tag);
	spin_unlock_irqrestore(&dev->lock, flags);
	if (res) {
		pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res);
		return -EPERM;
	}
	pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);

	res = swait_event_interruptible(dev->done.wait,
				       dev->done.done || kthread_should_stop());
	if (kthread_should_stop())
		res = -EINTR;
	if (res) {
		pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op);
		return res;
	}

	if (dev->lv1_status) {
		pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__,
		       __LINE__, op, dev->lv1_status);
		return -EIO;
	}
	pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op);

	return 0;
}
Exemple #5
0
int lv1_stor_wrapper_read(lv1_stor_wrapper_var *stor_var, u64 region_id, u64 start_sector, u64 num_sectors, u64 flags, void *data)
{
	u64 tag, status;
	int result;

	result = lv1_storage_read(stor_var->dev_id, region_id, start_sector, num_sectors,
		flags, stor_var->dma_lpar_addr, &tag);
	if (result != 0)
		return result;

	for (;;)
	{
		result = lv1_storage_check_async_status(stor_var->dev_id, tag, &status);
		if (result != 0)
			continue;

		if (status == 0)
			break;
	}

	memcpy(data, stor_var->dma, stor_var->block_size * num_sectors);	

	return 0;
}
Exemple #6
0
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;
}