Re: [PATCH 7/7] misc: intel-ish-client: add intel ishtp clients driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Dec 23, 2016 at 09:22:29AM +0800, Even Xu wrote:
> +static int ishtp_cl_open(struct inode *inode, struct file *file)
> +{
> +	struct miscdevice *misc = file->private_data;
> +	struct ishtp_cl *cl;
> +	struct ishtp_device *dev;
> +	struct ishtp_cl_miscdev *ishtp_cl_misc;
> +	int ret;
> +
> +	/* Non-blocking semantics are not supported */
> +	if (file->f_flags & O_NONBLOCK)
> +		return -EINVAL;
> +
> +	ishtp_cl_misc = container_of(misc,
> +				struct ishtp_cl_miscdev, cl_miscdev);
> +	if (!ishtp_cl_misc || !ishtp_cl_misc->cl_device)
> +		return -ENODEV;

How can ishtp_cl_misc ever be NULL?  Are you sure you know what
container_of() really does here?  :)

> +	dev = ishtp_cl_misc->cl_device->ishtp_dev;
> +	if (!dev)
> +		return -ENODEV;

How can dev be NULL?

> +
> +	mutex_lock(&ishtp_cl_misc->cl_mutex);
> +
> +	/*
> +	 * Every client only supports one opened instance
> +	 * at the sametime.
> +	 */
> +	if (ishtp_cl_misc->cl) {
> +		ret = -EBUSY;
> +		goto out_unlock;
> +	}
> +
> +	cl = ishtp_cl_allocate(dev);
> +	if (!cl) {
> +		ret = -ENOMEM;
> +		goto out_free;
> +	}
> +
> +	if (dev->dev_state != ISHTP_DEV_ENABLED) {
> +		ret = -ENODEV;
> +		goto out_free;
> +	}
> +
> +	ret = ishtp_cl_link(cl, ISHTP_HOST_CLIENT_ID_ANY);
> +	if (ret)
> +		goto out_free;
> +
> +	ishtp_cl_misc->cl = cl;
> +
> +	file->private_data = ishtp_cl_misc;
> +
> +	mutex_unlock(&ishtp_cl_misc->cl_mutex);
> +
> +	return nonseekable_open(inode, file);
> +
> +out_free:
> +	kfree(cl);
> +out_unlock:
> +	mutex_unlock(&ishtp_cl_misc->cl_mutex);
> +	return ret;
> +}
> +
> +#define WAIT_FOR_SEND_SLICE_MS		100
> +#define WAIT_FOR_SEND_COUNT		10
> +
> +static int ishtp_cl_release(struct inode *inode, struct file *file)
> +{
> +	struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data;
> +	struct ishtp_cl *cl;
> +	struct ishtp_cl_rb *rb;
> +	struct ishtp_device *dev;
> +	int try = WAIT_FOR_SEND_COUNT;
> +	int ret;
> +
> +	mutex_lock(&ishtp_cl_misc->cl_mutex);
> +
> +	/* Wake up from waiting if anyone wait on it */
> +	wake_up_interruptible(&ishtp_cl_misc->read_wait);
> +
> +	cl = ishtp_cl_misc->cl;
> +	dev = cl->dev;
> +
> +	/*
> +	 * May happen if device sent FW reset or was intentionally
> +	 * halted by host SW. The client is then invalid.
> +	 */
> +	if ((dev->dev_state == ISHTP_DEV_ENABLED) &&
> +			(cl->state == ISHTP_CL_CONNECTED)) {
> +		/*
> +		 * Check and wait 1s for message in tx_list to be sent.
> +		 */
> +		do {
> +			if (!ishtp_cl_tx_empty(cl))
> +				msleep_interruptible(WAIT_FOR_SEND_SLICE_MS);
> +			else
> +				break;
> +		} while (--try);

So just try it a bunch and hope it all works out?  No error message if
something went wrong?  Why not try forever?  Why that specific number of
trys?  This feels hacky.


> +
> +		cl->state = ISHTP_CL_DISCONNECTING;
> +		ret = ishtp_cl_disconnect(cl);
> +	}
> +
> +	ishtp_cl_unlink(cl);
> +	ishtp_cl_flush_queues(cl);
> +	/* Disband and free all Tx and Rx client-level rings */
> +	ishtp_cl_free(cl);
> +
> +	ishtp_cl_misc->cl = NULL;
> +
> +	rb = ishtp_cl_misc->read_rb;
> +	if (rb) {
> +		ishtp_cl_io_rb_recycle(rb);
> +		ishtp_cl_misc->read_rb = NULL;
> +	}
> +
> +	file->private_data = NULL;
> +
> +	mutex_unlock(&ishtp_cl_misc->cl_mutex);
> +
> +	return ret;
> +}
> +
> +static ssize_t ishtp_cl_read(struct file *file, char __user *ubuf,
> +			size_t length, loff_t *offset)
> +{
> +	struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data;
> +	struct ishtp_cl *cl;
> +	struct ishtp_cl_rb *rb;
> +	struct ishtp_device *dev;
> +	int ret = 0;
> +
> +	/* Non-blocking semantics are not supported */
> +	if (file->f_flags & O_NONBLOCK)
> +		return -EINVAL;
> +
> +	mutex_lock(&ishtp_cl_misc->cl_mutex);
> +
> +	cl = ishtp_cl_misc->cl;
> +
> +	/*
> +	 * ISHFW reset will cause cl be freed and re-allocated.
> +	 * So must make sure cl is re-allocated successfully.
> +	 */
> +	if (!cl || !cl->dev) {
> +		ret = -ENODEV;
> +		goto out_unlock;
> +	}

How can these ever be true?

> +
> +	dev = cl->dev;
> +	if (dev->dev_state != ISHTP_DEV_ENABLED) {
> +		ret = -ENODEV;
> +		goto out_unlock;
> +	}
> +
> +	if (ishtp_cl_misc->read_rb)
> +		goto get_rb;
> +
> +	rb = ishtp_cl_rx_get_rb(cl);
> +	if (rb)
> +		goto copy_buffer;
> +
> +	/*
> +	 * Release mutex for other operation can be processed parallelly
> +	 * during waiting.
> +	 */
> +	mutex_unlock(&ishtp_cl_misc->cl_mutex);
> +
> +	if (wait_event_interruptible(ishtp_cl_misc->read_wait,
> +			ishtp_cl_misc->read_rb != NULL)) {
> +		dev_err(&ishtp_cl_misc->cl_device->dev,
> +			"Wake up not successful;"
> +			"signal pending = %d signal = %08lX\n",
> +			signal_pending(current),
> +			current->pending.signal.sig[0]);

Why spam the error log for this?

> +		return -ERESTARTSYS;
> +	}
> +
> +	mutex_lock(&ishtp_cl_misc->cl_mutex);
> +
> +	/*
> +	 * waitqueue can be woken up in many cases, so must check
> +	 * if dev and cl is still available.
> +	 */
> +	if (dev->dev_state != ISHTP_DEV_ENABLED) {
> +		ret = -ENODEV;
> +		goto out_unlock;
> +	}
> +
> +	cl = ishtp_cl_misc->cl;
> +	if (!cl) {
> +		ret = -ENODEV;
> +		goto out_unlock;
> +	}
> +
> +	if (cl->state == ISHTP_CL_INITIALIZING ||
> +		cl->state == ISHTP_CL_DISCONNECTED ||
> +		cl->state == ISHTP_CL_DISCONNECTING) {
> +		ret = -EBUSY;
> +		goto out_unlock;
> +	}
> +
> +get_rb:
> +	rb = ishtp_cl_misc->read_rb;
> +	if (!rb) {
> +		ret = -ENODEV;
> +		goto out_unlock;
> +	}
> +
> +copy_buffer:
> +	/* Now copy the data to user space */
> +	if (!length || !ubuf || *offset > rb->buf_idx) {
> +		ret = -EMSGSIZE;
> +		goto out_unlock;
> +	}
> +
> +	/*
> +	 * length is being truncated, however buf_idx may
> +	 * point beyond that.
> +	 */
> +	length = min_t(size_t, length, rb->buf_idx - *offset);
> +
> +	if (copy_to_user(ubuf, rb->buffer.data + *offset, length)) {
> +		ret = -EFAULT;
> +		goto out_unlock;
> +	}
> +
> +	*offset += length;
> +	if ((unsigned long)*offset < rb->buf_idx)
> +		goto out_unlock;
> +
> +	ishtp_cl_io_rb_recycle(rb);
> +	ishtp_cl_misc->read_rb = NULL;
> +	*offset = 0;
> +
> +out_unlock:
> +	mutex_unlock(&ishtp_cl_misc->cl_mutex);
> +	return ret < 0 ? ret : length;
> +}

I still don't understand what is being read/written through this
character device node.  What is it used for?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux