esoc: add support for additonal physical link info

Some of the device configurations support multiple external SOCs.
To differentiate physical links, add support for additonal info
about the physical link.

CRs-Fixed: 2024578
Change-Id: If71bf23d798f8bf0b6594a686415fe9b806e4226
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt b/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt
index 6ddc725..a6537eb 100644
--- a/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt
+++ b/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt
@@ -108,6 +108,8 @@
 - qcom,sysmon-id: platform device id that sysmon is probed with for the subsystem.
 - qcom,pil-force-shutdown: Boolean. If set, the SSR framework will not trigger graceful shutdown
 			   on behalf of the subsystem driver.
+- qcom,mdm-link-info: a string indicating additional info about the physical link.
+			For example: "devID_domain.bus.slot" in case of PCIe.
 
 Example:
 	mdm0: qcom,mdm0 {
diff --git a/drivers/esoc/esoc-mdm-4x.c b/drivers/esoc/esoc-mdm-4x.c
index 6c42f54..334278b 100644
--- a/drivers/esoc/esoc-mdm-4x.c
+++ b/drivers/esoc/esoc-mdm-4x.c
@@ -937,6 +937,10 @@
 	mdm->dual_interface = of_property_read_bool(node,
 						"qcom,mdm-dual-link");
 	esoc->link_name = MDM9x55_PCIE;
+	ret = of_property_read_string(node, "qcom,mdm-link-info",
+					&esoc->link_info);
+	if (ret)
+		dev_info(mdm->dev, "esoc link info missing\n");
 	esoc->clink_ops = clink_ops;
 	esoc->parent = mdm->dev;
 	esoc->owner = THIS_MODULE;
diff --git a/drivers/esoc/esoc.h b/drivers/esoc/esoc.h
index 0cec985..9fc3192 100644
--- a/drivers/esoc/esoc.h
+++ b/drivers/esoc/esoc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,7 @@
  * struct esoc_clink: Representation of external esoc device
  * @name: Name of the external esoc.
  * @link_name: name of the physical link.
+ * @link_info: additional info about the physical link.
  * @parent: parent device.
  * @dev: device for userspace interface.
  * @id: id of the external device.
@@ -62,6 +63,7 @@
 struct esoc_clink {
 	const char *name;
 	const char *link_name;
+	const char *link_info;
 	struct device *parent;
 	struct device dev;
 	unsigned int id;
diff --git a/drivers/esoc/esoc_bus.c b/drivers/esoc/esoc_bus.c
index dc94742..cef570b 100644
--- a/drivers/esoc/esoc_bus.c
+++ b/drivers/esoc/esoc_bus.c
@@ -32,10 +32,19 @@
 				to_esoc_clink(dev)->link_name);
 }
 
+static ssize_t
+esoc_link_info_show(struct device *dev, struct device_attribute *attr,
+							char *buf)
+{
+	return snprintf(buf, ESOC_LINK_LEN, "%s",
+				to_esoc_clink(dev)->link_info);
+}
+
 static struct device_attribute esoc_clink_attrs[] = {
 
 	__ATTR_RO(esoc_name),
 	__ATTR_RO(esoc_link),
+	__ATTR_RO(esoc_link_info),
 	__ATTR_NULL,
 };
 
diff --git a/drivers/esoc/esoc_client.c b/drivers/esoc/esoc_client.c
index b9d6833..446735c 100644
--- a/drivers/esoc/esoc_client.c
+++ b/drivers/esoc/esoc_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -44,7 +44,7 @@
 	struct device_node *np = dev->of_node;
 	struct esoc_clink *esoc_clink;
 	struct esoc_desc *desc;
-	char *esoc_name, *esoc_link;
+	char *esoc_name, *esoc_link, *esoc_link_info;
 
 	for (index = 0;; index++) {
 		esoc_prop = kasprintf(GFP_KERNEL, "esoc-%d", index);
@@ -86,16 +86,26 @@
 			kfree(esoc_name);
 			return ERR_PTR(-ENOMEM);
 		}
+		esoc_link_info = kasprintf(GFP_KERNEL, "%s",
+					esoc_clink->link_info);
+		if (IS_ERR_OR_NULL(esoc_link_info)) {
+			dev_err(dev, "unable to alloc link info name\n");
+			kfree(esoc_name);
+			kfree(esoc_link);
+			return ERR_PTR(-ENOMEM);
+		}
 		desc = devres_alloc(devm_esoc_desc_release,
 						sizeof(*desc), GFP_KERNEL);
 		if (IS_ERR_OR_NULL(desc)) {
 			kfree(esoc_name);
 			kfree(esoc_link);
+			kfree(esoc_link_info);
 			dev_err(dev, "unable to allocate esoc descriptor\n");
 			return ERR_PTR(-ENOMEM);
 		}
 		desc->name = esoc_name;
 		desc->link = esoc_link;
+		desc->link_info = esoc_link_info;
 		desc->priv = esoc_clink;
 		devres_add(dev, desc);
 		return desc;
diff --git a/include/linux/esoc_client.h b/include/linux/esoc_client.h
index 77a8b50..7a4913d 100644
--- a/include/linux/esoc_client.h
+++ b/include/linux/esoc_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
 struct esoc_desc {
 	const char *name;
 	const char *link;
+	const char *link_info;
 	void *priv;
 };