static int rio_mport_maint_wr()

in devices/rio_mport_cdev.c [303:352]


static int rio_mport_maint_wr(struct mport_cdev_priv *priv, void __user *arg,
			      int local)
{
	struct rio_mport *mport = priv->md->mport;
	struct rio_mport_maint_io maint_io;
	u32 *buffer;
	u32 offset;
	size_t length;
	int ret = -EINVAL, i;

	if (unlikely(copy_from_user(&maint_io, arg, sizeof(maint_io))))
		return -EFAULT;

	if ((maint_io.offset % 4) ||
	    (maint_io.length == 0) || (maint_io.length % 4) ||
	    (maint_io.length + maint_io.offset) > RIO_MAINT_SPACE_SZ)
		return -EINVAL;

	buffer = vmalloc(maint_io.length);
	if (buffer == NULL)
		return -ENOMEM;
	length = maint_io.length;

	if (unlikely(copy_from_user(buffer,
			(void __user *)(uintptr_t)maint_io.buffer, length))) {
		ret = -EFAULT;
		goto out;
	}

	offset = maint_io.offset;
	length /= sizeof(u32);

	for (i = 0; i < length; i++) {
		if (local)
			ret = __rio_local_write_config_32(mport,
							  offset, buffer[i]);
		else
			ret = rio_mport_write_config_32(mport, maint_io.rioid,
							maint_io.hopcount,
							offset, buffer[i]);
		if (ret)
			goto out;

		offset += 4;
	}

out:
	vfree(buffer);
	return ret;
}