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

Commit 390f9933 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: hab: hold the message when the read buffer is smaller"

parents 6e5dae3a c7e6dca7
Loading
Loading
Loading
Loading
+23 −27
Original line number Diff line number Diff line
@@ -356,18 +356,21 @@ err:
	return ret;
}

struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
int hab_vchan_recv(struct uhab_context *ctx,
				struct hab_message **message,
				int vcid,
				int *rsize,
				unsigned int flags)
{
	struct virtual_channel *vchan;
	struct hab_message *message;
	int ret = 0;
	int nonblocking_flag = flags & HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING;

	vchan = hab_get_vchan_fromvcid(vcid, ctx);
	if (!vchan)
		return ERR_PTR(-ENODEV);
	if (!vchan) {
		pr_err("vcid %X, vchan %p ctx %p\n", vcid, vchan, ctx);
		return -ENODEV;
	}

	if (nonblocking_flag) {
		/*
@@ -378,18 +381,18 @@ struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
		physical_channel_rx_dispatch((unsigned long) vchan->pchan);
	}

	message = hab_msg_dequeue(vchan, flags);
	if (!message) {
	ret = hab_msg_dequeue(vchan, message, rsize, flags);
	if (!(*message)) {
		if (nonblocking_flag)
			ret = -EAGAIN;
		else if (vchan->otherend_closed)
			ret = -ENODEV;
		else
			ret = -EPIPE;
		else if (ret == -ERESTARTSYS)
			ret = -EINTR;
	}

	hab_vchan_put(vchan);
	return ret ? ERR_PTR(ret) : message;
	return ret;
}

bool hab_is_loopback(void)
@@ -843,28 +846,21 @@ static long hab_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
			break;
		}

		msg = hab_vchan_recv(ctx, recv_param->vcid, recv_param->flags);

		if (IS_ERR(msg)) {
			recv_param->sizebytes = 0;
			ret = PTR_ERR(msg);
			break;
		}
		ret = hab_vchan_recv(ctx, &msg, recv_param->vcid,
				&recv_param->sizebytes, recv_param->flags);

		if (recv_param->sizebytes < msg->sizebytes) {
			recv_param->sizebytes = 0;
			ret = -EINVAL;
		} else if (copy_to_user((void __user *)recv_param->data,
		if (ret == 0 && msg) {
			if (copy_to_user((void __user *)recv_param->data,
					msg->data,
					msg->sizebytes)) {
				pr_err("copy_to_user failed: vc=%x size=%d\n",
				   recv_param->vcid, (int)msg->sizebytes);
				recv_param->sizebytes = 0;
				ret = -EFAULT;
		} else {
			recv_param->sizebytes = msg->sizebytes;
			}
		}

		if (msg)
			hab_msg_free(msg);
		break;
	case IOCTL_HAB_VC_EXPORT:
+7 −5
Original line number Diff line number Diff line
@@ -373,8 +373,10 @@ long hab_vchan_send(struct uhab_context *ctx,
		size_t sizebytes,
		void *data,
		unsigned int flags);
struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
int hab_vchan_recv(struct uhab_context *ctx,
		struct hab_message **msg,
		int vcid,
		int *rsize,
		unsigned int flags);
void hab_vchan_stop(struct virtual_channel *vchan);
void hab_vchans_stop(struct physical_channel *pchan);
@@ -422,8 +424,8 @@ int habmem_imp_hyp_mmap(struct file *flip, struct vm_area_struct *vma);


void hab_msg_free(struct hab_message *message);
struct hab_message *hab_msg_dequeue(struct virtual_channel *vchan,
		unsigned int flags);
int hab_msg_dequeue(struct virtual_channel *vchan,
		struct hab_message **msg, int *rsize, unsigned int flags);

void hab_msg_recv(struct physical_channel *pchan,
		struct hab_header *header);
+22 −6
Original line number Diff line number Diff line
@@ -42,8 +42,9 @@ void hab_msg_free(struct hab_message *message)
	kfree(message);
}

struct hab_message *
hab_msg_dequeue(struct virtual_channel *vchan, unsigned int flags)
int
hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
		int *rsize, unsigned int flags)
{
	struct hab_message *message = NULL;
	int ret = 0;
@@ -64,15 +65,30 @@ hab_msg_dequeue(struct virtual_channel *vchan, unsigned int flags)
	}

	/* return all the received messages before the remote close */
	if (!ret && !hab_rx_queue_empty(vchan)) {
	if ((!ret || (ret == -ERESTARTSYS)) && !hab_rx_queue_empty(vchan)) {
		spin_lock_bh(&vchan->rx_lock);
		message = list_first_entry(&vchan->rx_list,
				struct hab_message, node);
		if (message) {
			if (*rsize >= message->sizebytes) {
				/* msg can be safely retrieved in full */
				list_del(&message->node);
		spin_unlock_bh(&vchan->rx_lock);
				ret = 0;
				*rsize = message->sizebytes;
			} else {
				pr_err("rcv buffer too small %d < %zd\n",
					   *rsize, message->sizebytes);
				*rsize = 0;
				message = NULL;
				ret = -EINVAL;
			}
		}
		spin_unlock_bh(&vchan->rx_lock);
	} else
		*rsize = 0;

	return message;
	*msg = message;
	return ret;
}

static void hab_msg_queue(struct virtual_channel *vchan,
+5 −13
Original line number Diff line number Diff line
@@ -51,22 +51,14 @@ int32_t habmm_socket_recv(int32_t handle, void *dst_buff, uint32_t *size_bytes,
	if (!size_bytes || !dst_buff)
		return -EINVAL;

	msg = hab_vchan_recv(hab_driver.kctx, handle, flags);
	ret = hab_vchan_recv(hab_driver.kctx, &msg, handle, size_bytes, flags);

	if (IS_ERR(msg)) {
		*size_bytes = 0;
		return PTR_ERR(msg);
	}

	if (*size_bytes < msg->sizebytes) {
		*size_bytes = 0;
		ret = -EINVAL;
	} else {
	if (ret == 0 && msg)
		memcpy(dst_buff, msg->data, msg->sizebytes);
		*size_bytes = msg->sizebytes;
	}

	if (msg)
		hab_msg_free(msg);

	return ret;
}
EXPORT_SYMBOL(habmm_socket_recv);