summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus
diff options
context:
space:
mode:
authorMitchell Tasman <tasman@leaflabs.com>2016-05-04 17:30:23 -0400
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-04 18:41:05 -0700
commitee2f2074fdb20d4939c943d0372f3751d833dedf (patch)
tree676eb9aceb5d0ea2f6e97f53bfea3a7af1d8cf30 /drivers/staging/greybus
parent3e29bcf4b148b8983dcb30faec0b59f681eabe9e (diff)
greybus: svc: reconfig APBridgeA-Switch link to handle required load
SW-4894, SW-4389, and share a common root cause, namely that the power-on reset configuration of the APBridgeA-Switch link of PWM Gear 1, 1 Lane, Slow Auto, is insufficient to handle some required traffic loads, such as 3 audio streams plus boot-over-UniPro or 4 audio streams. The correct long-term solution is to implement a UniPro Power Mode Manager as in that considers the demands placed on the network, and adjusts power modes accordingly. The present commit implements a short-term, brute-force hack to allow continued system testing: - Upon receiving an SVC HELLO request, schedule deferred work to reconfigure the APB1-Switch link to PWM G2, 1 lane, Slow Auto - When the Camera driver transitions a White Camera module from active to inactive, return the APB1-Switch link to PWM G2, 1 lane, Slow Auto The Camera driver already steps up the APBridgeA-Camera link speed while a camera module is active, which affords sufficient margin for simultaneous audio and hotplug activity, and the Camera driver already steps down the link speed thereafter: the change made by the present patch is simply to tweak the stepped-down power mode to match the new baseline configuration. Signed-off-by: Mitchell Tasman <tasman@leaflabs.com> Tested-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus')
-rw-r--r--drivers/staging/greybus/camera.c4
-rw-r--r--drivers/staging/greybus/svc.c36
2 files changed, 37 insertions, 3 deletions
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index 956fbf05b8e0..ba76f5633256 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -131,9 +131,9 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id,
ret = gb_svc_intf_set_power_mode(svc, intf_id,
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
- 1, 2,
+ 2, 1,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
- 1, 2,
+ 2, 1,
0, 0);
return ret;
diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c
index 577e680f6a90..f3ee94e4b03e 100644
--- a/drivers/staging/greybus/svc.c
+++ b/drivers/staging/greybus/svc.c
@@ -23,6 +23,8 @@ struct gb_svc_deferred_request {
};
+static int gb_svc_queue_deferred_request(struct gb_operation *operation);
+
static ssize_t endo_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -695,7 +697,7 @@ static int gb_svc_hello(struct gb_operation *op)
gb_svc_debugfs_init(svc);
- return 0;
+ return gb_svc_queue_deferred_request(op);
}
static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc,
@@ -754,6 +756,35 @@ static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf)
mutex_unlock(&intf->mutex);
}
+static void gb_svc_process_hello_deferred(struct gb_operation *operation)
+{
+ struct gb_connection *connection = operation->connection;
+ struct gb_svc *svc = gb_connection_get_data(connection);
+ int ret;
+
+ /*
+ * XXX This is a hack/work-around to reconfigure the APBridgeA-Switch
+ * link to PWM G2, 1 Lane, Slow Auto, so that it has sufficient
+ * bandwidth for 3 audio streams plus boot-over-UniPro of a hot-plugged
+ * module.
+ *
+ * The code should be removed once SW-2217, Heuristic for UniPro
+ * Power Mode Changes is resolved.
+ */
+ ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id,
+ GB_SVC_UNIPRO_HS_SERIES_A,
+ GB_SVC_UNIPRO_SLOW_AUTO_MODE,
+ 2, 1,
+ GB_SVC_UNIPRO_SLOW_AUTO_MODE,
+ 2, 1,
+ 0, 0);
+
+ if (ret)
+ dev_warn(&svc->dev,
+ "power mode change failed on AP to switch link: %d\n",
+ ret);
+}
+
static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
{
struct gb_svc_intf_hotplug_request *request;
@@ -963,6 +994,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work)
type = operation->request->header->type;
switch (type) {
+ case GB_SVC_TYPE_SVC_HELLO:
+ gb_svc_process_hello_deferred(operation);
+ break;
case GB_SVC_TYPE_INTF_HOTPLUG:
gb_svc_process_intf_hotplug(operation);
break;