diff options
author | Heikki Krogerus <heikki.krogerus@linux.intel.com> | 2021-09-20 17:24:18 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-10-05 13:42:38 +0300 |
commit | bd19ac98f77e04aa50a842bb7387f95637bf58d1 (patch) | |
tree | 000b61e0e6aad3340ed6b82c3311d75a3b1eafa7 /drivers | |
parent | 6cbe4b2d5a3f290fba764e722b19cb55968a84d2 (diff) | |
download | linux-bd19ac98f77e04aa50a842bb7387f95637bf58d1.tar.xz |
usb: typec: ucsi: Read the PDOs in separate work
Polling also the PDOs, just like the alt modes.
After this ucsi_handle_connector_change() doesn't execute
any commands.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20210920142419.54493-7-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/typec/ucsi/ucsi.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 188181737acf..e7267e47c3e4 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -571,7 +571,7 @@ static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner, command |= UCSI_GET_PDOS_SRC_PDOS; ret = ucsi_send_command(ucsi, command, pdos + offset, num_pdos * sizeof(u32)); - if (ret < 0) + if (ret < 0 && ret != -ETIMEDOUT) dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); if (ret == 0 && offset == 0) dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n"); @@ -579,26 +579,30 @@ static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner, return ret; } -static void ucsi_get_src_pdos(struct ucsi_connector *con, int is_partner) +static int ucsi_get_src_pdos(struct ucsi_connector *con) { int ret; /* UCSI max payload means only getting at most 4 PDOs at a time */ ret = ucsi_get_pdos(con, 1, con->src_pdos, 0, UCSI_MAX_PDOS); if (ret < 0) - return; + return ret; con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */ if (con->num_pdos < UCSI_MAX_PDOS) - return; + return 0; /* get the remaining PDOs, if any */ ret = ucsi_get_pdos(con, 1, con->src_pdos, UCSI_MAX_PDOS, PDO_MAX_OBJECTS - UCSI_MAX_PDOS); if (ret < 0) - return; + return ret; con->num_pdos += ret / sizeof(u32); + + ucsi_port_psy_changed(con); + + return 0; } static int ucsi_check_altmodes(struct ucsi_connector *con) @@ -626,7 +630,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con) case UCSI_CONSTAT_PWR_OPMODE_PD: con->rdo = con->status.request_data_obj; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD); - ucsi_get_src_pdos(con, 1); + ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0); ucsi_partner_task(con, ucsi_check_altmodes, 30, 0); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: @@ -844,12 +848,6 @@ static void ucsi_handle_connector_change(struct work_struct *work) role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); - if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE || - con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) { - ucsi_pwr_opmode_change(con); - ucsi_port_psy_changed(con); - } - if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) { typec_set_pwr_role(con->port, role); @@ -900,6 +898,10 @@ static void ucsi_handle_connector_change(struct work_struct *work) con->num, u_role); } + if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE || + con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) + ucsi_pwr_opmode_change(con); + if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) ucsi_partner_change(con); @@ -1248,8 +1250,10 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ret = 0; } - if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == UCSI_CONSTAT_PWR_OPMODE_PD) + if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == UCSI_CONSTAT_PWR_OPMODE_PD) { + ucsi_get_src_pdos(con); ucsi_check_altmodes(con); + } trace_ucsi_register_port(con->num, &con->status); |