Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07d66921 authored by Khalid Aziz's avatar Khalid Aziz Committed by David S. Miller
Browse files

sparc: Add support for seek and shorter read to /dev/mdesc



/dev/mdesc on Linux does not support reading arbitrary number
of bytes and seeking while /dev/mdesc on Solaris does. This
causes tools that work on Solaris to break on Linux. This patch
adds these two capabilities to /dev/mdesc.

Signed-off-by: default avatarKhalid Aziz <khalid.aziz@oracle.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e7fbaf01
Loading
Loading
Loading
Loading
+69 −13
Original line number Original line Diff line number Diff line
@@ -906,29 +906,85 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
	smp_fill_in_sib_core_maps();
	smp_fill_in_sib_core_maps();
}
}


static ssize_t mdesc_read(struct file *file, char __user *buf,
/* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
			  size_t len, loff_t *offp)
 * opened. Hold this reference until /dev/mdesc is closed to ensure
 * mdesc data structure is not released underneath us. Store the
 * pointer to mdesc structure in private_data for read and seek to use
 */
static int mdesc_open(struct inode *inode, struct file *file)
{
{
	struct mdesc_handle *hp = mdesc_grab();
	struct mdesc_handle *hp = mdesc_grab();
	int err;


	if (!hp)
	if (!hp)
		return -ENODEV;
		return -ENODEV;


	err = hp->handle_size;
	file->private_data = hp;
	if (len < hp->handle_size)

		err = -EMSGSIZE;
	return 0;
	else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
}
		err = -EFAULT;

	mdesc_release(hp);
static ssize_t mdesc_read(struct file *file, char __user *buf,
			  size_t len, loff_t *offp)
{
	struct mdesc_handle *hp = file->private_data;
	unsigned char *mdesc;
	int bytes_left, count = len;

	if (*offp >= hp->handle_size)
		return 0;

	bytes_left = hp->handle_size - *offp;
	if (count > bytes_left)
		count = bytes_left;

	mdesc = (unsigned char *)&hp->mdesc;
	mdesc += *offp;
	if (!copy_to_user(buf, mdesc, count)) {
		*offp += count;
		return count;
	} else {
		return -EFAULT;
	}
}


	return err;
static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
{
	struct mdesc_handle *hp;

	switch (whence) {
	case SEEK_CUR:
		offset += file->f_pos;
		break;
	case SEEK_SET:
		break;
	default:
		return -EINVAL;
	}

	hp = file->private_data;
	if (offset > hp->handle_size)
		return -EINVAL;
	else
		file->f_pos = offset;

	return offset;
}

/* mdesc_close() - /dev/mdesc is being closed, release the reference to
 * mdesc structure.
 */
static int mdesc_close(struct inode *inode, struct file *file)
{
	mdesc_release(file->private_data);
	return 0;
}
}


static const struct file_operations mdesc_fops = {
static const struct file_operations mdesc_fops = {
	.open    = mdesc_open,
	.read	 = mdesc_read,
	.read	 = mdesc_read,
	.llseek  = mdesc_llseek,
	.release = mdesc_close,
	.owner	 = THIS_MODULE,
	.owner	 = THIS_MODULE,
	.llseek = noop_llseek,
};
};


static struct miscdevice mdesc_misc = {
static struct miscdevice mdesc_misc = {