mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-03-11 23:27:42 +07:00
usb: typec: tcpm: Refactor tcpm_handle_vdm_request
Refactor tcpm_handle_vdm_request and its tcpm_pd_svdm helper function so that reporting the results of the vdm to the altmode-driver is separated out into a clear separate step inside tcpm_handle_vdm_request, instead of being scattered over various places inside the tcpm_pd_svdm helper. This is a preparation patch for fixing an AB BA lock inversion between the tcpm code and some altmode drivers. Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20200724174702.61754-4-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8afe9a3548
commit
95b4d51c96
@ -159,6 +159,14 @@ enum pd_msg_request {
|
||||
PD_MSG_DATA_SOURCE_CAP,
|
||||
};
|
||||
|
||||
enum adev_actions {
|
||||
ADEV_NONE = 0,
|
||||
ADEV_NOTIFY_USB_AND_QUEUE_VDM,
|
||||
ADEV_QUEUE_VDM,
|
||||
ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL,
|
||||
ADEV_ATTENTION,
|
||||
};
|
||||
|
||||
/* Events from low level driver */
|
||||
|
||||
#define TCPM_CC_EVENT BIT(0)
|
||||
@ -1080,10 +1088,10 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
|
||||
|
||||
#define supports_modal(port) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header)
|
||||
|
||||
static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
u32 *response)
|
||||
static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
|
||||
const u32 *p, int cnt, u32 *response,
|
||||
enum adev_actions *adev_action)
|
||||
{
|
||||
struct typec_altmode *adev;
|
||||
struct typec_altmode *pdev;
|
||||
struct pd_mode_data *modep;
|
||||
int rlen = 0;
|
||||
@ -1099,9 +1107,6 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
|
||||
modep = &port->mode_data;
|
||||
|
||||
adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX,
|
||||
PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
|
||||
|
||||
pdev = typec_match_altmode(port->partner_altmode, ALTMODE_DISCOVERY_MAX,
|
||||
PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
|
||||
|
||||
@ -1127,8 +1132,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
break;
|
||||
case CMD_ATTENTION:
|
||||
/* Attention command does not have response */
|
||||
if (adev)
|
||||
typec_altmode_attention(adev, p[1]);
|
||||
*adev_action = ADEV_ATTENTION;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
@ -1182,23 +1186,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
case CMD_ENTER_MODE:
|
||||
if (adev && pdev) {
|
||||
typec_altmode_update_active(pdev, true);
|
||||
|
||||
if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
|
||||
response[0] = VDO(adev->svid, 1,
|
||||
CMD_EXIT_MODE);
|
||||
response[0] |= VDO_OPOS(adev->mode);
|
||||
return 1;
|
||||
}
|
||||
*adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL;
|
||||
}
|
||||
return 0;
|
||||
case CMD_EXIT_MODE:
|
||||
if (adev && pdev) {
|
||||
typec_altmode_update_active(pdev, false);
|
||||
|
||||
/* Back to USB Operation */
|
||||
WARN_ON(typec_altmode_notify(adev,
|
||||
TYPEC_STATE_USB,
|
||||
NULL));
|
||||
*adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1209,11 +1205,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
switch (cmd) {
|
||||
case CMD_ENTER_MODE:
|
||||
/* Back to USB Operation */
|
||||
if (adev)
|
||||
WARN_ON(typec_altmode_notify(adev,
|
||||
TYPEC_STATE_USB,
|
||||
NULL));
|
||||
break;
|
||||
*adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1223,15 +1216,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
|
||||
}
|
||||
|
||||
/* Informing the alternate mode drivers about everything */
|
||||
if (adev)
|
||||
typec_altmode_vdm(adev, p[0], &p[1], cnt);
|
||||
|
||||
*adev_action = ADEV_QUEUE_VDM;
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static void tcpm_handle_vdm_request(struct tcpm_port *port,
|
||||
const __le32 *payload, int cnt)
|
||||
{
|
||||
enum adev_actions adev_action = ADEV_NONE;
|
||||
struct typec_altmode *adev;
|
||||
u32 p[PD_MAX_PAYLOAD];
|
||||
u32 response[8] = { };
|
||||
int i, rlen = 0;
|
||||
@ -1239,6 +1232,9 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
|
||||
for (i = 0; i < cnt; i++)
|
||||
p[i] = le32_to_cpu(payload[i]);
|
||||
|
||||
adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX,
|
||||
PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
|
||||
|
||||
if (port->vdm_state == VDM_STATE_BUSY) {
|
||||
/* If UFP responded busy retry after timeout */
|
||||
if (PD_VDO_CMDT(p[0]) == CMDT_RSP_BUSY) {
|
||||
@ -1253,7 +1249,31 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
|
||||
}
|
||||
|
||||
if (PD_VDO_SVDM(p[0]))
|
||||
rlen = tcpm_pd_svdm(port, p, cnt, response);
|
||||
rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action);
|
||||
|
||||
if (adev) {
|
||||
switch (adev_action) {
|
||||
case ADEV_NONE:
|
||||
break;
|
||||
case ADEV_NOTIFY_USB_AND_QUEUE_VDM:
|
||||
WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL));
|
||||
typec_altmode_vdm(adev, p[0], &p[1], cnt);
|
||||
break;
|
||||
case ADEV_QUEUE_VDM:
|
||||
typec_altmode_vdm(adev, p[0], &p[1], cnt);
|
||||
break;
|
||||
case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL:
|
||||
if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
|
||||
response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE);
|
||||
response[0] |= VDO_OPOS(adev->mode);
|
||||
rlen = 1;
|
||||
}
|
||||
break;
|
||||
case ADEV_ATTENTION:
|
||||
typec_altmode_attention(adev, p[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rlen > 0)
|
||||
tcpm_queue_vdm(port, response[0], &response[1], rlen - 1);
|
||||
|
Loading…
Reference in New Issue
Block a user