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

Commit c1c7f2ef authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: typec: ucsi_glink: Fix a NULL pointer dereference"

parents ca256478 4129360b
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"UCSI: %s: " fmt, __func__
@@ -77,6 +77,7 @@ struct ucsi_dev {
	struct mutex			read_lock;
	struct mutex			write_lock;
	struct mutex			notify_lock;
	struct mutex			state_lock;
	struct ucsi_read_buf_resp_msg	rx_buf;
	unsigned long			flags;
	atomic_t			rx_valid;
@@ -201,6 +202,19 @@ static int handle_ucsi_notify(struct ucsi_dev *udev, void *data, size_t len)
		return -EINVAL;
	}

	mutex_lock(&udev->state_lock);
	if (atomic_read(&udev->state) == PMIC_GLINK_STATE_DOWN) {
		pr_err("glink state is down\n");
		mutex_unlock(&udev->state_lock);
		return -ENOTCONN;
	}

	if (!udev->ucsi) {
		pr_err("ucsi is NULL\n");
		mutex_unlock(&udev->state_lock);
		return -ENODEV;
	}

	msg_ptr = data;
	cci = msg_ptr->notification;
	ucsi_log("notify:", UCSI_CCI, (u8 *)&cci, sizeof(cci));
@@ -221,6 +235,7 @@ static int handle_ucsi_notify(struct ucsi_dev *udev, void *data, size_t len)
		if (con && con->ucsi)
			ucsi_connector_change(udev->ucsi, con_num);
	}
	mutex_unlock(&udev->state_lock);

	return 0;
}
@@ -285,6 +300,9 @@ static int ucsi_qti_glink_write(struct ucsi_dev *udev, unsigned int offset,
		reinit_completion(&udev->sync_write_ack);
	}

	ucsi_log(sync ? "sync_write:" : "async_write:", offset,
			(u8 *)val, val_len);

	rc = pmic_glink_write(udev->client, &ucsi_buf,
					sizeof(ucsi_buf));
	if (rc < 0) {
@@ -314,9 +332,6 @@ static int ucsi_qti_glink_write(struct ucsi_dev *udev, unsigned int offset,
		}
	}

	ucsi_log(sync ? "sync_write:" : "async_write:", offset,
			(u8 *)val, val_len);

	if (((u8 *)val)[0] == UCSI_GET_CONNECTOR_STATUS) {
		mutex_lock(&udev->notify_lock);
		set_bit(CONN_STAT_REQD, &udev->cmd_requested_flags);
@@ -485,11 +500,13 @@ static int ucsi_setup(struct ucsi_dev *udev)
		return -EINVAL;
	}

	mutex_lock(&udev->state_lock);
	udev->ucsi = ucsi_create(udev->dev, &ucsi_qti_ops);
	if (IS_ERR(udev->ucsi)) {
		rc = PTR_ERR(udev->ucsi);
		dev_err(udev->dev, "ucsi_create failed rc=%d\n", rc);
		udev->ucsi = NULL;
		mutex_unlock(&udev->state_lock);
		return rc;
	}

@@ -500,9 +517,11 @@ static int ucsi_setup(struct ucsi_dev *udev)
		dev_err(udev->dev, "ucsi_register failed rc=%d\n", rc);
		ucsi_destroy(udev->ucsi);
		udev->ucsi = NULL;
		mutex_unlock(&udev->state_lock);
		return rc;
	}

	mutex_unlock(&udev->state_lock);
	return 0;
}

@@ -520,12 +539,14 @@ static void ucsi_qti_state_cb(void *priv, enum pmic_glink_state state)

	dev_dbg(udev->dev, "state: %d\n", state);

	mutex_lock(&udev->state_lock);
	atomic_set(&udev->state, state);

	switch (state) {
	case PMIC_GLINK_STATE_DOWN:
		if (!udev->ucsi) {
			dev_err(udev->dev, "ucsi is NULL\n");
			mutex_unlock(&udev->state_lock);
			return;
		}

@@ -539,6 +560,7 @@ static void ucsi_qti_state_cb(void *priv, enum pmic_glink_state state)
	default:
		break;
	}
	mutex_unlock(&udev->state_lock);
}

static int ucsi_probe(struct platform_device *pdev)
@@ -557,6 +579,7 @@ static int ucsi_probe(struct platform_device *pdev)
	mutex_init(&udev->read_lock);
	mutex_init(&udev->write_lock);
	mutex_init(&udev->notify_lock);
	mutex_init(&udev->state_lock);
	init_completion(&udev->read_ack);
	init_completion(&udev->write_ack);
	init_completion(&udev->sync_write_ack);