summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-03-29 09:32:27 +0200
committerchrome-bot <chrome-bot@chromium.org>2017-05-09 20:36:42 -0700
commit600df851c5565237a38f5ba0edda2beef8db618c (patch)
tree5198c8b2be99f14aa1c66b229c4a68f8cbaf5a65
parent92e409827006949b9f908217f04acdcbf695e701 (diff)
downloadchrome-ec-600df851c5565237a38f5ba0edda2beef8db618c.tar.gz
Eve,Gru,Poppy,Reef: forbid DR_SWAP in RO firmware.
Currently, when we jump from RO to RW, we forget our USB PD state. To recover from this, we send a SOFT_RESET (resetting the counters...), then either the USB PD partner is happy about it and we can continue, or it will issue a HARD_RESET to recover from our mismatched vision of the current connection (e.g wrong role) resulting in a reset of VBUS. The following use-case is still problematic: if the system is not write-protected (ie it does USB PD negotiation in RO EC) and we have no battery (or fully drained-one) as buffer, when we are connected to a PD power supply, if it issues the HARD_RESET mentioned above, we are going to brown-out. It's happening with power-supplies supporting DR_SWAP, the RO EC will negotiate a power-contract (as a sink), then try to reverse data role (from UFP to DFP) to identify the power-supply. We end-up being Sink/DFP, then when we sysjump to RW, we reset roles and send the SOFT_RESET as Sink/DFP, the power-supply identifies the incorrect data role and issues the HARD_RESET browning us out. As a workaround, now we never ask for the DR_SWAP in RO firmware and stays Sink/UFP. This is not affecting regular write-protected machines (which are not doing USB PD in RO EC). For developers, we are no longer doing the DR_SWAP in RO mode, this is mostly innocuous for a regular power-supply, but this would break the docking use-case. Normally, we will do it as soon as we have jumped to RW, so the dock should still work unless the developer is using the machine with RO EC (eg EC development with soft-sync disabled). Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=reef BUG=b:35648282 TEST=Boot Snappy without battery. Verify RO image doesn't swap data roles and soft reset issued by RW image as SNK/UFP is accepted by the HP adapter. Change-Id: Id184f0d24a006cd46212d04ceae02f640f5bda65 Reviewed-on: https://chromium-review.googlesource.com/461142 Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Sam Hurst <shurst@google.com>
-rw-r--r--board/eve/usb_pd_policy.c15
-rw-r--r--board/kevin/usb_pd_policy.c15
-rw-r--r--board/poppy/usb_pd_policy.c15
-rw-r--r--board/reef/usb_pd_policy.c15
-rw-r--r--util/genvif.c7
5 files changed, 54 insertions, 13 deletions
diff --git a/board/eve/usb_pd_policy.c b/board/eve/usb_pd_policy.c
index 5829aaff76..e1425c15d8 100644
--- a/board/eve/usb_pd_policy.c
+++ b/board/eve/usb_pd_policy.c
@@ -190,8 +190,15 @@ int pd_check_power_swap(int port)
int pd_check_data_swap(int port, int data_role)
{
- /* Allow data swap if we are a UFP, otherwise don't allow */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
+ /*
+ * Allow data swap if we are a UFP, otherwise don't allow.
+ *
+ * When we are still in the Read-Only firmware, avoid swapping roles
+ * so we don't jump in RW as a SNK/DFP and potentially confuse the
+ * power supply by sending a soft-reset with wrong data role.
+ */
+ return (data_role == PD_ROLE_UFP) &&
+ (system_get_image_copy() != SYSTEM_IMAGE_RO) ? 1 : 0;
}
int pd_check_vconn_swap(int port)
@@ -229,7 +236,9 @@ void pd_check_pr_role(int port, int pr_role, int flags)
void pd_check_dr_role(int port, int dr_role, int flags)
{
/* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) &&
+ dr_role == PD_ROLE_UFP &&
+ system_get_image_copy() != SYSTEM_IMAGE_RO)
pd_request_data_swap(port);
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/kevin/usb_pd_policy.c b/board/kevin/usb_pd_policy.c
index deef42c250..c72433dbb3 100644
--- a/board/kevin/usb_pd_policy.c
+++ b/board/kevin/usb_pd_policy.c
@@ -174,8 +174,15 @@ int pd_check_power_swap(int port)
int pd_check_data_swap(int port, int data_role)
{
- /* Allow data swap if we are a UFP, otherwise don't allow */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
+ /*
+ * Allow data swap if we are a UFP, otherwise don't allow.
+ *
+ * When we are still in the Read-Only firmware, avoid swapping roles
+ * so we don't jump in RW as a SNK/DFP and potentially confuse the
+ * power supply by sending a soft-reset with wrong data role.
+ */
+ return (data_role == PD_ROLE_UFP) &&
+ (system_get_image_copy() != SYSTEM_IMAGE_RO) ? 1 : 0;
}
int pd_check_vconn_swap(int port)
@@ -212,7 +219,9 @@ void pd_check_pr_role(int port, int pr_role, int flags)
void pd_check_dr_role(int port, int dr_role, int flags)
{
/* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) &&
+ dr_role == PD_ROLE_UFP &&
+ system_get_image_copy() != SYSTEM_IMAGE_RO)
pd_request_data_swap(port);
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/poppy/usb_pd_policy.c b/board/poppy/usb_pd_policy.c
index 3d926415bf..3e39ac8269 100644
--- a/board/poppy/usb_pd_policy.c
+++ b/board/poppy/usb_pd_policy.c
@@ -177,8 +177,15 @@ int pd_check_power_swap(int port)
int pd_check_data_swap(int port, int data_role)
{
- /* Allow data swap if we are a UFP, otherwise don't allow */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
+ /*
+ * Allow data swap if we are a UFP, otherwise don't allow.
+ *
+ * When we are still in the Read-Only firmware, avoid swapping roles
+ * so we don't jump in RW as a SNK/DFP and potentially confuse the
+ * power supply by sending a soft-reset with wrong data role.
+ */
+ return (data_role == PD_ROLE_UFP) &&
+ (system_get_image_copy() != SYSTEM_IMAGE_RO) ? 1 : 0;
}
int pd_check_vconn_swap(int port)
@@ -216,7 +223,9 @@ void pd_check_pr_role(int port, int pr_role, int flags)
void pd_check_dr_role(int port, int dr_role, int flags)
{
/* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) &&
+ dr_role == PD_ROLE_UFP &&
+ system_get_image_copy() != SYSTEM_IMAGE_RO)
pd_request_data_swap(port);
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/board/reef/usb_pd_policy.c b/board/reef/usb_pd_policy.c
index bc530687bd..7b2ec9d1bd 100644
--- a/board/reef/usb_pd_policy.c
+++ b/board/reef/usb_pd_policy.c
@@ -170,8 +170,15 @@ int pd_check_power_swap(int port)
int pd_check_data_swap(int port, int data_role)
{
- /* Allow data swap if we are a UFP, otherwise don't allow */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
+ /*
+ * Allow data swap if we are a UFP, otherwise don't allow.
+ *
+ * When we are still in the Read-Only firmware, avoid swapping roles
+ * so we don't jump in RW as a SNK/DFP and potentially confuse the
+ * power supply by sending a soft-reset with wrong data role.
+ */
+ return (data_role == PD_ROLE_UFP) &&
+ (system_get_image_copy() != SYSTEM_IMAGE_RO) ? 1 : 0;
}
int pd_check_vconn_swap(int port)
@@ -209,7 +216,9 @@ void pd_check_pr_role(int port, int pr_role, int flags)
void pd_check_dr_role(int port, int dr_role, int flags)
{
/* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) &&
+ dr_role == PD_ROLE_UFP &&
+ system_get_image_copy() != SYSTEM_IMAGE_RO)
pd_request_data_swap(port);
}
/* ----------------- Vendor Defined Messages ------------------ */
diff --git a/util/genvif.c b/util/genvif.c
index e9e7223019..50e4680e24 100644
--- a/util/genvif.c
+++ b/util/genvif.c
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <dirent.h>
@@ -20,6 +19,7 @@
#include "usb_pd.h"
#include "usb_pd_tcpm.h"
#include "charge_manager.h"
+#include "system.h"
#define PD_REV_2_0 1
#define PD_REV_3_0 2
@@ -40,6 +40,11 @@ char *yes_no(int val)
return val ? "YES" : "NO";
}
+enum system_image_copy_t system_get_image_copy(void)
+{
+ return SYSTEM_IMAGE_RW;
+}
+
static void init_src_pdos(void)
{
#ifdef CONFIG_USB_PD_DYNAMIC_SRC_CAP