Merge "usb: typec: ucsi_glink: add a debug log in ucsi_qti_notify_work()"

This commit is contained in:
qctecmdr 2022-05-16 09:37:14 -07:00 committed by Gerrit - the friendly Code Review server
commit 5ecc408cde
2 changed files with 92 additions and 16 deletions

View File

@ -1,6 +1,6 @@
// 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__
@ -11,6 +11,7 @@
#include <linux/notifier.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/soc/qcom/pmic_glink.h>
#include <linux/usb/typec.h>
#include <linux/usb/ucsi_glink.h>
@ -67,6 +68,11 @@ struct ucsi_notify_ind_msg {
u32 reserved;
};
struct constat_info_entry {
struct list_head node;
struct ucsi_glink_constat_info constat_info;
};
struct ucsi_dev {
struct device *dev;
struct ucsi *ucsi;
@ -77,11 +83,12 @@ 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;
unsigned long cmd_requested_flags;
struct ucsi_glink_constat_info constat_info;
struct list_head constat_info_list;
struct work_struct notify_work;
struct work_struct setup_work;
atomic_t state;
@ -201,6 +208,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 +241,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 +306,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 +338,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);
@ -348,12 +369,43 @@ static int ucsi_qti_sync_write(struct ucsi *ucsi, unsigned int offset,
return ucsi_qti_glink_write(udev, offset, val, val_len, true);
}
static void ucsi_qti_clean_notification(struct ucsi_dev *udev)
{
struct constat_info_entry *entry, *tmp;
mutex_lock(&udev->notify_lock);
list_for_each_entry_safe(entry, tmp, &udev->constat_info_list, node) {
list_del(&entry->node);
kfree(entry);
}
INIT_LIST_HEAD(&udev->constat_info_list);
mutex_unlock(&udev->notify_lock);
}
static void ucsi_qti_notify_work(struct work_struct *work)
{
struct ucsi_dev *udev = container_of(work, struct ucsi_dev,
notify_work);
struct constat_info_entry *entry;
raw_notifier_call_chain(&ucsi_glink_notifier, 0, &udev->constat_info);
mutex_lock(&udev->notify_lock);
while (!list_empty(&udev->constat_info_list)) {
entry = list_first_entry(&udev->constat_info_list,
struct constat_info_entry, node);
list_del(&entry->node);
mutex_unlock(&udev->notify_lock);
pr_debug("acc: %d usb: %d alt_mode: %d change: %d connect: %d\n",
entry->constat_info.acc,
entry->constat_info.partner_usb,
entry->constat_info.partner_alternate_mode,
entry->constat_info.partner_change,
entry->constat_info.connect);
raw_notifier_call_chain(&ucsi_glink_notifier,
0, &entry->constat_info);
kfree(entry);
mutex_lock(&udev->notify_lock);
}
mutex_unlock(&udev->notify_lock);
}
static void ucsi_qti_notify(struct ucsi_dev *udev, unsigned int offset,
@ -361,6 +413,7 @@ static void ucsi_qti_notify(struct ucsi_dev *udev, unsigned int offset,
{
u8 conn_partner_type, conn_partner_flag;
bool cmd_requested;
struct constat_info_entry *entry;
if (len != sizeof(*status))
return;
@ -370,39 +423,49 @@ static void ucsi_qti_notify(struct ucsi_dev *udev, unsigned int offset,
mutex_unlock(&udev->notify_lock);
if (cmd_requested && offset == UCSI_MESSAGE_IN) {
cancel_work_sync(&udev->notify_work);
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
udev->constat_info.partner_usb = false;
udev->constat_info.partner_alternate_mode = false;
INIT_LIST_HEAD(&entry->node);
entry->constat_info.partner_usb = false;
entry->constat_info.partner_alternate_mode = false;
entry->constat_info.partner_change =
status->change & UCSI_CONSTAT_PARTNER_CHANGE;
entry->constat_info.connect =
status->flags & UCSI_CONSTAT_CONNECTED;
conn_partner_type = UCSI_CONSTAT_PARTNER_TYPE(status->flags);
switch (conn_partner_type) {
case UCSI_CONSTAT_PARTNER_TYPE_AUDIO:
udev->constat_info.acc = TYPEC_ACCESSORY_AUDIO;
entry->constat_info.acc = TYPEC_ACCESSORY_AUDIO;
break;
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
udev->constat_info.acc = TYPEC_ACCESSORY_DEBUG;
entry->constat_info.acc = TYPEC_ACCESSORY_DEBUG;
break;
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_DFP:
udev->constat_info.partner_usb = true;
entry->constat_info.partner_usb = true;
fallthrough;
default:
udev->constat_info.acc = TYPEC_ACCESSORY_NONE;
entry->constat_info.acc = TYPEC_ACCESSORY_NONE;
break;
}
conn_partner_flag = UCSI_CONSTAT_PARTNER_FLAGS(status->flags);
if (conn_partner_flag & UCSI_CONSTAT_PARTNER_FLAG_USB)
udev->constat_info.partner_usb = true;
entry->constat_info.partner_usb = true;
if (conn_partner_flag & UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE)
udev->constat_info.partner_alternate_mode = true;
entry->constat_info.partner_alternate_mode = true;
mutex_lock(&udev->notify_lock);
list_add_tail(&entry->node, &udev->constat_info_list);
clear_bit(CONN_STAT_REQD, &udev->cmd_requested_flags);
mutex_unlock(&udev->notify_lock);
@ -479,11 +542,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;
}
@ -494,9 +559,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;
}
@ -514,15 +581,18 @@ 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");
dev_dbg(udev->dev, "ucsi is NULL\n");
mutex_unlock(&udev->state_lock);
return;
}
ucsi_qti_clean_notification(udev);
ucsi_unregister(udev->ucsi);
ucsi_destroy(udev->ucsi);
udev->ucsi = NULL;
@ -533,6 +603,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)
@ -546,11 +617,13 @@ static int ucsi_probe(struct platform_device *pdev)
if (!udev)
return -ENOMEM;
INIT_LIST_HEAD(&udev->constat_info_list);
INIT_WORK(&udev->notify_work, ucsi_qti_notify_work);
INIT_WORK(&udev->setup_work, ucsi_qti_setup_work);
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);
@ -595,6 +668,7 @@ static int ucsi_remove(struct platform_device *pdev)
struct ucsi_dev *udev = dev_get_drvdata(dev);
int rc;
ucsi_qti_clean_notification(udev);
cancel_work_sync(&udev->notify_work);
ucsi_unregister(udev->ucsi);
ucsi_destroy(udev->ucsi);

View File

@ -13,6 +13,8 @@ struct ucsi_glink_constat_info {
enum typec_accessory acc;
bool partner_usb;
bool partner_alternate_mode;
bool partner_change;
bool connect;
};
struct notifier_block;