in devices/rio_mport_cdev.c [258:301]
static int rio_mport_maint_rd(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, 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/sizeof(u32);
offset = maint_io.offset;
for (i = 0; i < length; i++) {
if (local)
ret = __rio_local_read_config_32(mport,
offset, &buffer[i]);
else
ret = rio_mport_read_config_32(mport, maint_io.rioid,
maint_io.hopcount, offset, &buffer[i]);
if (ret)
goto out;
offset += 4;
}
if (unlikely(copy_to_user((void __user *)(uintptr_t)maint_io.buffer,
buffer, maint_io.length)))
ret = -EFAULT;
out:
vfree(buffer);
return ret;
}