Commit 7a9366aa authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman
Browse files

greybus: don't let i2c code assume non-null payload pointer



This is in preparation for an upcoming patch, which makes the
payload pointer be NULL when a message has zero bytes of payload.

It ensures a null payload pointer never gets dereferenced.  To do
this we pass the response structure to gb_i2c_transfer_response()
rather than just its data, and if it's null, returning immediately.

Rearrange the logic in gb_i2c_transfer_operation() a bit.

Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 93bbe859
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -258,11 +258,15 @@ gb_i2c_transfer_request(struct gb_connection *connection,
}

static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count,
					void *data)
				struct gb_i2c_transfer_response *response)
{
	struct i2c_msg *msg = msgs;
	u8 *data;
	u32 i;

	if (!response)
		return;
	data = response->data;
	for (i = 0; i < msg_count; i++) {
		if (msg->flags & I2C_M_RD) {
			memcpy(msg->buf, data, msg->len);
@@ -276,7 +280,6 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev,
					struct i2c_msg *msgs, u32 msg_count)
{
	struct gb_connection *connection = gb_i2c_dev->connection;
	struct gb_i2c_transfer_response *response;
	struct gb_operation *operation;
	int ret;

@@ -284,15 +287,15 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev,
	if (!operation)
		return -ENOMEM;

	/* Synchronous operation--no callback */
	ret = gb_operation_request_send_sync(operation);
	if (ret) {
		if (ret != -EAGAIN)
			pr_err("transfer operation failed (%d)\n", ret);
	} else {
	if (!ret) {
		struct gb_i2c_transfer_response *response;

		response = operation->response->payload;
		gb_i2c_transfer_response(msgs, msg_count, response->data);
		gb_i2c_transfer_response(msgs, msg_count, response);
		ret = msg_count;
	} else if (ret != -EAGAIN) {
		pr_err("transfer operation failed (%d)\n", ret);
	}
	gb_operation_destroy(operation);