From 6232b073d44646e3051a8871feb2deaabe9d624c Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@linaro.org>
Date: Tue, 21 Oct 2014 22:43:31 -0400
Subject: [PATCH] greybus: ap: process the UniPro link up message

The link up message is the event that tells the AP what device ID
has been assigned to a particular interface on a module during
enumeration. The link up is sent *only* after the hotplug event
for a particular module has been sent to the AP.

The link up payload must carry the Module ID and Interface ID
to uniquely identify the struct gb_interface to which the
Device ID has been assigned.

After processing of the link up message, the interface's device_id
field will contain the assigned Device ID so that the AP has the
information necessary to issue network route commands.

Signed-off-by: Matt Porter <mporter@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
---
 drivers/staging/greybus/ap.c      | 19 +++++++++++++++++++
 drivers/staging/greybus/svc_msg.h |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c
index 5b6335643bc0e..c8f30f64e3759 100644
--- a/drivers/staging/greybus/ap.c
+++ b/drivers/staging/greybus/ap.c
@@ -106,6 +106,9 @@ static void svc_handshake(struct svc_function_handshake *handshake,
 static void svc_management(struct svc_function_unipro_management *management,
 			   int payload_length, struct greybus_host_device *hd)
 {
+	struct gb_module *module;
+	struct gb_interface *interface;
+
 	if (payload_length != sizeof(struct svc_function_unipro_management)) {
 		dev_err(hd->parent,
 			"Illegal size of svc management message %d\n",
@@ -114,6 +117,22 @@ static void svc_management(struct svc_function_unipro_management *management,
 	}
 
 	switch (management->management_packet_type) {
+	case SVC_MANAGEMENT_LINK_UP:
+		module = gb_module_find(hd, management->link_up.module_id);
+		if (!module) {
+			dev_err(hd->parent, "Module ID %d not found\n",
+				management->link_up.module_id);
+			return;
+		}
+		interface = gb_interface_find(module,
+					      management->link_up.interface_id);
+		if (!interface) {
+			dev_err(hd->parent, "Interface ID %d not found\n",
+				management->link_up.interface_id);
+			return;
+		}
+		interface->device_id = management->link_up.device_id;
+		break;
 	case SVC_MANAGEMENT_AP_DEVICE_ID:
 		hd->device_id = management->ap_device_id.device_id;
 		break;
diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h
index 4aa7e177f0766..47597e6cd47b2 100644
--- a/drivers/staging/greybus/svc_msg.h
+++ b/drivers/staging/greybus/svc_msg.h
@@ -55,6 +55,8 @@ struct svc_function_unipro_set_route {
 };
 
 struct svc_function_unipro_link_up {
+	__u8	module_id;
+	__u8	interface_id;
 	__u8	device_id;
 };
 
-- 
2.30.2