Skip to contentSkip to conversation

soc: qcom: Add SoC info driver

PATCH Superseded Imran Khan 2 participants 4 messages Nov 16, 2016 – Dec 12, 2016

Subsystems (2)

v5 of 10 Superseded Latest is v10 →

lore
Share & tools
lore

Imran Khan

author
#0 lore raw

PATCH v5 1/1 soc: qcom: Add SoC info driver

The SoC info driver provides information such as Chip ID, Chip family, serial number and other such details about Qualcomm SoCs.

---
v4 --> v5:
- Removed redundant function socinfo_print

v3 --> v4:
- Corrected makefile so that smem and socinfo are treated as one module
- Moved the code snippet to get socinfo smem item into socinfo.c
- Removed redundant use of socinfo major version as it is always zero
- Removed unused enums
- Removed redundant indirections
- Use image_version object to store information about each entry in the smem image table
- Replaced usage of snprintf with sprintf and scnprintf
- Get the address of image version table at the beginning and setup image version attributes only if image version table is available
- Do the same for platform_subtype
- Make different type of image version objects read only or readable/ writable depending on their types. For example apps image attributes can be modified via sysfs but the same can't be done for modem image
- Show PMIC model in a human readable form rather than a numeric number
- Avoid using table in single sysfs entry
- Removed checkpatch warnings about S_IRUGO

v2 --> v3:
- Add support to toss soc information data into entropy pool
- Since socinfo is rolled into smem driver, compile the relevant portion of socinfo driver with smem driver

v1 --> v2:
- Removed inclusion of system_misc.h
- merged socinfo.h into socinfo.c
- made platform type and subtype arrays static
- replaced uint32_t with u32
- made functions static to avoid exposing vendor specific interface
- Replaced usage of IS_ERR_OR_NULL with IS_ERR.
- Remove raw-id attribute usage as human readable soc-id will suffice here
- Avoid using a separate platform driver for socinfo by rolling it into smem driver itself. The sysfs setup is being done in a separate file (socinfo.c)
- Replaced macro BUILD_ID_LENGTH with SMEM_SOCINFO_BUILD_ID_LENGTH.
- For failure cases where socinfo can not be read use a single dummy socinfo with error values.
- Removed usage of early_machine_is_xxx.

 drivers/soc/qcom/Kconfig   |   1 +
 drivers/soc/qcom/Makefile  |   3 +-
 drivers/soc/qcom/smem.c    |   5 +
 drivers/soc/qcom/socinfo.c | 989 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 997 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/qcom/socinfo.c
drivers/soc/qcom/Kconfig +1 -0
index 461b387..f89d34d 100644
@@ -24,6 +24,7 @@ config QCOM_SMEM
 	tristate "Qualcomm Shared Memory Manager (SMEM)"
 	depends on ARCH_QCOM
 	depends on HWSPINLOCK
+	select SOC_BUS
 	help
 	  Say y here to enable support for the Qualcomm Shared Memory Manager.
 	  The driver provides an interface to items in a heap shared among all
drivers/soc/qcom/Makefile +2 -1
index fdd664e..438efec 100644
@@ -2,7 +2,8 @@ obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
 obj-$(CONFIG_QCOM_SMD) +=	smd.o
 obj-$(CONFIG_QCOM_SMD_RPM)	+= smd-rpm.o
-obj-$(CONFIG_QCOM_SMEM) +=	smem.o
+obj-$(CONFIG_QCOM_SMEM) +=	qcom_smem.o
+qcom_smem-y := smem.o socinfo.o
 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
drivers/soc/qcom/smem.c +5 -0
index 18ec52f..a57acfb0 100644
@@ -85,6 +85,9 @@
 /* Max number of processors/hosts in a system */
 #define SMEM_HOST_COUNT		9
 
+
+extern int qcom_socinfo_init(struct platform_device *pdev);
+
 /**
   * struct smem_proc_comm - proc_comm communication struct (legacy)
   * @command:	current command to be executed
@@ -751,6 +754,8 @@ static int qcom_smem_probe(struct platform_device *pdev)
 
 	__smem = smem;
 
+	qcom_socinfo_init(pdev);
+
 	return 0;
 }
 
drivers/soc/qcom/socinfo.c new file +989 -0

989 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#1 lore raw
Quoted 150 lines · Imran Khan

The SoC info driver provides information such as Chip ID, Chip family, serial number and other such details about Qualcomm SoCs.

---
v4 --> v5:
- Removed redundant function socinfo_print

v3 --> v4:
- Corrected makefile so that smem and socinfo are treated as one module
- Moved the code snippet to get socinfo smem item into socinfo.c
- Removed redundant use of socinfo major version as it is always zero
- Removed unused enums
- Removed redundant indirections
- Use image_version object to store information about each entry in the smem image table
- Replaced usage of snprintf with sprintf and scnprintf
- Get the address of image version table at the beginning and setup image version attributes only if image version table is available
- Do the same for platform_subtype
- Make different type of image version objects read only or readable/ writable depending on their types. For example apps image attributes can be modified via sysfs but the same can't be done for modem image
- Show PMIC model in a human readable form rather than a numeric number
- Avoid using table in single sysfs entry
- Removed checkpatch warnings about S_IRUGO

v2 --> v3:
- Add support to toss soc information data into entropy pool
- Since socinfo is rolled into smem driver, compile the relevant portion of socinfo driver with smem driver

v1 --> v2:
- Removed inclusion of system_misc.h
- merged socinfo.h into socinfo.c
- made platform type and subtype arrays static
- replaced uint32_t with u32
- made functions static to avoid exposing vendor specific interface
- Replaced usage of IS_ERR_OR_NULL with IS_ERR.
- Remove raw-id attribute usage as human readable soc-id will suffice here
- Avoid using a separate platform driver for socinfo by rolling it into smem driver itself. The sysfs setup is being done in a separate file (socinfo.c)
- Replaced macro BUILD_ID_LENGTH with SMEM_SOCINFO_BUILD_ID_LENGTH.
- For failure cases where socinfo can not be read use a single dummy socinfo with error values.
- Removed usage of early_machine_is_xxx.

 drivers/soc/qcom/Kconfig   |   1 +
 drivers/soc/qcom/Makefile  |   3 +-
 drivers/soc/qcom/smem.c    |   5 +
 drivers/soc/qcom/socinfo.c | 989 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 997 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/qcom/socinfo.c
drivers/soc/qcom/Kconfig +1 -0
index 461b387..f89d34d 100644
@@ -24,6 +24,7 @@ config QCOM_SMEM
 	tristate "Qualcomm Shared Memory Manager (SMEM)"
 	depends on ARCH_QCOM
 	depends on HWSPINLOCK
+	select SOC_BUS
 	help
 	  Say y here to enable support for the Qualcomm Shared Memory Manager.
 	  The driver provides an interface to items in a heap shared among all
drivers/soc/qcom/Makefile +2 -1
index fdd664e..438efec 100644
@@ -2,7 +2,8 @@ obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
 obj-$(CONFIG_QCOM_SMD) +=	smd.o
 obj-$(CONFIG_QCOM_SMD_RPM)	+= smd-rpm.o
-obj-$(CONFIG_QCOM_SMEM) +=	smem.o
+obj-$(CONFIG_QCOM_SMEM) +=	qcom_smem.o
+qcom_smem-y := smem.o socinfo.o
 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
drivers/soc/qcom/smem.c +5 -0
index 18ec52f..a57acfb0 100644
@@ -85,6 +85,9 @@
 /* Max number of processors/hosts in a system */
 #define SMEM_HOST_COUNT		9
 
+
+extern int qcom_socinfo_init(struct platform_device *pdev);
+
 /**
   * struct smem_proc_comm - proc_comm communication struct (legacy)
   * @command:	current command to be executed
@@ -751,6 +754,8 @@ static int qcom_smem_probe(struct platform_device *pdev)
 
 	__smem = smem;
 
+	qcom_socinfo_init(pdev);
+
 	return 0;
 }
 
drivers/soc/qcom/socinfo.c new file +40 -0
new file mode 100644
index 0000000..eca46df
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 2009-2016, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/soc/qcom/smem.h>
+
+#define PMIC_MODEL_UNKNOWN 0
+#define HW_PLATFORM_QRD 11
+#define PLATFORM_SUBTYPE_QRD_INVALID 6
+#define PLATFORM_SUBTYPE_INVALID 4
+/*
+ * SOC version type with major number in the upper 16 bits and minor
+ * number in the lower 16 bits.  For example:
+ *   1.0 -> 0x00010000
+ *   2.3 -> 0x00020003
+ */
+#define SOC_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16)
+#define SOC_VERSION_MINOR(ver) ((ver) & 0x0000ffff)
+#define SOCINFO_FORMAT(x)  (x)

drivers/soc/qcom/socinfo.c line 50

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+#define SOCINFO_VERSION_MAJOR	SOC_VERSION_MAJOR
+#define SOCINFO_VERSION_MINOR	SOC_VERSION_MINOR
+
+#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
+#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
+#define SMEM_IMAGE_VERSION_SIZE 4096
+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
+#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
+#define SMEM_IMAGE_VERSION_OEM_SIZE 32
+#define SMEM_IMAGE_VERSION_PARTITION_APPS 10

Please indent the values evenly, making this slightly easier to read.

drivers/soc/qcom/socinfo.c line 61

Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+
+/*
+ * Shared memory identifiers, used to acquire handles to respective memory
+ * region.
+ */
+#define SMEM_IMAGE_VERSION_TABLE	469
+
+/*
+ * Shared memory identifiers, used to acquire handles to respective memory
+ * region.
+ */

Duplicating this comment doesn't add value, please just drop this second copy and replace the above comment with something like "SMEM item ids"

Quoted 107 lines
drivers/soc/qcom/socinfo.c new file +107 -0
+#define SMEM_HW_SW_BUILD_ID		137
+
+/*
+ * SMEM Image table indices
+ */
+enum smem_image_table_index {
+	SMEM_IMAGE_TABLE_BOOT_INDEX = 0,
+	SMEM_IMAGE_TABLE_TZ_INDEX,
+	SMEM_IMAGE_TABLE_RPM_INDEX = 3,
+	SMEM_IMAGE_TABLE_APPS_INDEX = 10,
+	SMEM_IMAGE_TABLE_MPSS_INDEX,
+	SMEM_IMAGE_TABLE_ADSP_INDEX,
+	SMEM_IMAGE_TABLE_CNSS_INDEX,
+	SMEM_IMAGE_TABLE_VIDEO_INDEX
+};
+
+#define SMEM_IMAGE_TABLE_ATTR(type, index)				\
+static ssize_t								\
+qcom_get_##type##_image_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_version(index, buf);			\
+}									\
+static ssize_t								\
+qcom_set_##type##_image_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			const char *buf,				\
+			size_t count)					\
+{									\
+	return	qcom_set_image_version(index, buf);			\
+}									\
+static ssize_t								\
+qcom_get_##type##_image_variant(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_variant(index, buf);			\
+}									\
+static ssize_t								\
+qcom_set_##type##_image_variant(struct device *dev,			\
+			struct device_attribute *attr,			\
+			const char *buf,				\
+			size_t count)					\
+{									\
+	return	qcom_set_image_variant(index, buf);			\
+}									\
+static ssize_t								\
+qcom_get_##type##_image_crm_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_crm_version(index, buf);			\
+}									\
+static ssize_t								\
+qcom_set_##type##_image_crm_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			const char *buf,				\
+			size_t count)					\
+{									\
+	return	qcom_set_image_crm_version(index, buf);			\
+}									\
+DEVICE_ATTR(type##_image_version, 0644, qcom_get_##type##_image_version,\
+				qcom_set_##type##_image_version);	\
+DEVICE_ATTR(type##_image_variant, 0644, qcom_get_##type##_image_variant,\
+				qcom_set_##type##_image_variant);	\
+DEVICE_ATTR(type##_image_crm_version, 0644,				\
+				qcom_get_##type##_image_crm_version,	\
+				qcom_set_##type##_image_crm_version);	\
+static struct attribute *type##_image_attrs[] = {			\
+	&dev_attr_##type##_image_version.attr,				\
+	&dev_attr_##type##_image_variant.attr,				\
+	&dev_attr_##type##_image_crm_version.attr,			\
+	NULL,								\
+};									\
+static struct attribute_group type##_image_attr_group = {		\
+	.attrs = type##_image_attrs,					\
+}
+
+#define SMEM_IMAGE_TABLE_RO_ATTR(type, index)				\
+static ssize_t								\
+qcom_get_##type##_image_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_version(index, buf);			\
+}									\
+static ssize_t								\
+qcom_get_##type##_image_variant(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_variant(index, buf);			\
+}									\
+static ssize_t								\
+qcom_get_##type##_image_crm_version(struct device *dev,			\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	return	qcom_get_image_crm_version(index, buf);			\
+}									\
+DEVICE_ATTR(type##_image_version, 0444, qcom_get_##type##_image_version,\
+					NULL);				\
+DEVICE_ATTR(type##_image_variant, 0444, qcom_get_##type##_image_variant,\
+					NULL);				\
+DEVICE_ATTR(type##_image_crm_version, 0444,				\
+				qcom_get_##type##_image_crm_version,	\

drivers/soc/qcom/socinfo.c line 178

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+					NULL);				\
+static struct attribute *type##_image_attrs[] = {			\
+	&dev_attr_##type##_image_version.attr,				\
+	&dev_attr_##type##_image_variant.attr,				\
+	&dev_attr_##type##_image_crm_version.attr,			\
+	NULL,								\
+	};								\
+static struct attribute_group type##_image_attr_group = {		\
+	.attrs = type##_image_attrs,					\
+}

Rather than having this based on two huge macros take a look at DEVICE_INT_ATTR() and struct dev_ext_attribute in include/linux/device.h. It looks like if you just put the index in a struct and use container_of to reach that you can replace these with direct functions.

Also, it's perfectly fine to always specify a store operation and use 0444 vs 0644 to control it's availability. So you don't need two sets if you just expose the mode in your macro.

Quoted 7 lines
drivers/soc/qcom/socinfo.c new file +7 -0
+
+/*
+ * Qcom SoC types
+ */
+enum qcom_cpu {
+	MSM_CPU_UNKNOWN = 0,
+	MSM_CPU_8960,

drivers/soc/qcom/socinfo.c line 195

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+	MSM_CPU_8960AB,
+	MSM_CPU_8064,
+	MSM_CPU_8974,
+	MSM_CPU_8974PRO_AA,
+	MSM_CPU_8974PRO_AB,
+	MSM_CPU_8974PRO_AC,
+	MSM_CPU_8916,
+	MSM_CPU_8084,
+	MSM_CPU_8996
+};

These are now "unused" (per below comment).

drivers/soc/qcom/socinfo.c line 198

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+
+struct qcom_soc_info {
+	enum qcom_cpu generic_soc_type;

This enum is no longer used, seems like you can turn cpu_of_id into a simple char *[] array with with soc_id_string indexed by id.

Quoted 137 lines
drivers/soc/qcom/socinfo.c new file +137 -0
+	char *soc_id_string;
+};
+
+/* Hardware platform types */
+static const char *hw_platform[] = {
+	[0] = "Unknown",
+	[1] = "Surf",
+	[2] = "FFA",
+	[3] = "Fluid",
+	[4] = "SVLTE_FFA",
+	[5] = "SLVTE_SURF",
+	[7] = "MDM_MTP_NO_DISPLAY",
+	[8] = "MTP",
+	[9] = "Liquid",
+	[10] = "Dragon",
+	[11] = "QRD",
+	[13] = "HRD",
+	[14] = "DTV",
+	[21] = "RCM",
+	[23] = "STP",
+	[24] = "SBC",
+};
+
+static const char *qrd_hw_platform_subtype[] = {
+	[0] = "QRD",
+	[1] = "SKUAA",
+	[2] = "SKUF",
+	[3] = "SKUAB",
+	[5] = "SKUG",
+	[6] = "INVALID",
+};
+
+static const char *hw_platform_subtype[] = {
+	"Unknown", "charm", "strange", "strange_2a", "Invalid",
+};
+
+static const char *pmic_model[] = {
+	[0]  = "Unknown PMIC model",
+	[13] = "PMIC model: PM8058",
+	[14] = "PMIC model: PM8028",
+	[15] = "PMIC model: PM8901",
+	[16] = "PMIC model: PM8027",
+	[17] = "PMIC model: ISL9519",
+	[18] = "PMIC model: PM8921",
+	[19] = "PMIC model: PM8018",
+	[20] = "PMIC model: PM8015",
+	[21] = "PMIC model: PM8014",
+	[22] = "PMIC model: PM8821",
+	[23] = "PMIC model: PM8038",
+	[24] = "PMIC model: PM8922",
+	[25] = "PMIC model: PM8917",
+};
+
+struct smem_image_version {
+	char name[SMEM_IMAGE_VERSION_NAME_SIZE];
+	char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE];
+	char pad;
+	char oem[SMEM_IMAGE_VERSION_OEM_SIZE];
+};
+
+/* Used to parse shared memory. Must match the modem. */
+struct socinfo_v0_1 {
+	u32 format;
+	u32 id;
+	u32 version;
+	char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
+};
+
+struct socinfo_v0_2 {
+	struct socinfo_v0_1 v0_1;
+	u32 raw_version;
+};
+
+struct socinfo_v0_3 {
+	struct socinfo_v0_2 v0_2;
+	u32 hw_platform;
+};
+
+struct socinfo_v0_4 {
+	struct socinfo_v0_3 v0_3;
+	u32 platform_version;
+};
+
+struct socinfo_v0_5 {
+	struct socinfo_v0_4 v0_4;
+	u32 accessory_chip;
+};
+
+struct socinfo_v0_6 {
+	struct socinfo_v0_5 v0_5;
+	u32 hw_platform_subtype;
+};
+
+struct socinfo_v0_7 {
+	struct socinfo_v0_6 v0_6;
+	u32 pmic_model;
+	u32 pmic_die_revision;
+};
+
+struct socinfo_v0_8 {
+	struct socinfo_v0_7 v0_7;
+	u32 pmic_model_1;
+	u32 pmic_die_revision_1;
+	u32 pmic_model_2;
+	u32 pmic_die_revision_2;
+};
+
+struct socinfo_v0_9 {
+	struct socinfo_v0_8 v0_8;
+	u32 foundry_id;
+};
+
+struct socinfo_v0_10 {
+	struct socinfo_v0_9 v0_9;
+	u32 serial_number;
+};
+
+struct socinfo_v0_11 {
+	struct socinfo_v0_10 v0_10;
+	u32 num_pmics;
+	u32 pmic_array_offset;
+};
+
+struct socinfo_v0_12 {
+	struct socinfo_v0_11 v0_11;
+	u32 chip_family;
+	u32 raw_device_family;
+	u32 raw_device_number;
+};
+
+static union {
+	struct socinfo_v0_1 v0_1;
+	struct socinfo_v0_2 v0_2;
+	struct socinfo_v0_3 v0_3;
+	struct socinfo_v0_4 v0_4;
+	struct socinfo_v0_5 v0_5;
+	struct socinfo_v0_6 v0_6;

drivers/soc/qcom/socinfo.c line 345

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+	struct socinfo_v0_7 v0_7;
+	struct socinfo_v0_8 v0_8;
+	struct socinfo_v0_9 v0_9;
+	struct socinfo_v0_10 v0_10;
+	struct socinfo_v0_11 v0_11;
+	struct socinfo_v0_12 v0_12;
+} *socinfo;
+
+static struct smem_image_version *smem_image_version;
+static bool smem_img_tbl_avlbl = true;

You don't need to keep track of this separately, just test if smem_image_version is NULL or not (reset it to NULL if qcom_smem_get() fails).

drivers/soc/qcom/socinfo.c line 347

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+static bool hw_subtype_valid = true;
+static u32 hw_subtype;

Don't keep track of this in a global variable, it's perfectly fine to figure it out in qcom_get_platform_subtype()

drivers/soc/qcom/socinfo.c line 351

Quoted 4 lines
drivers/soc/qcom/socinfo.c new file +4 -0
+
+
+/* max socinfo format version supported */
+#define MAX_SOCINFO_FORMAT SOCINFO_FORMAT(12)

It's fine to drop SOCINFO_FORMAT and just put 12 here.

Quoted 66 lines
drivers/soc/qcom/socinfo.c new file +66 -0
+
+static struct qcom_soc_info cpu_of_id[] = {
+
+	[0] = {MSM_CPU_UNKNOWN, "Unknown CPU"},
+
+	/* 8x60 IDs */
+	[87] = {MSM_CPU_8960, "MSM8960"},
+
+	/* 8x64 IDs */
+	[109] = {MSM_CPU_8064, "APQ8064"},
+	[130] = {MSM_CPU_8064, "MPQ8064"},
+
+	/* 8x60A IDs */
+	[122] = {MSM_CPU_8960, "MSM8660A"},
+	[123] = {MSM_CPU_8960, "MSM8260A"},
+	[124] = {MSM_CPU_8960, "APQ8060A"},
+
+	/* 8x74 IDs */
+	[126] = {MSM_CPU_8974, "MSM8974"},
+	[184] = {MSM_CPU_8974, "APQ8074"},
+	[185] = {MSM_CPU_8974, "MSM8274"},
+	[186] = {MSM_CPU_8974, "MSM8674"},
+
+	/* 8x74AA IDs */
+	[208] = {MSM_CPU_8974PRO_AA, "APQ8074-AA"},
+	[211] = {MSM_CPU_8974PRO_AA, "MSM8274-AA"},
+	[214] = {MSM_CPU_8974PRO_AA, "MSM8674-AA"},
+	[217] = {MSM_CPU_8974PRO_AA, "MSM8974-AA"},
+
+	/* 8x74AB IDs */
+	[209] = {MSM_CPU_8974PRO_AB, "APQ8074-AB"},
+	[212] = {MSM_CPU_8974PRO_AB, "MSM8274-AB"},
+	[215] = {MSM_CPU_8974PRO_AB, "MSM8674-AB"},
+	[218] = {MSM_CPU_8974PRO_AB, "MSM8974-AB"},
+
+	/* 8x74AC IDs */
+	[194] = {MSM_CPU_8974PRO_AC, "MSM8974PRO"},
+	[210] = {MSM_CPU_8974PRO_AC, "APQ8074PRO"},
+	[213] = {MSM_CPU_8974PRO_AC, "MSM8274PRO"},
+	[216] = {MSM_CPU_8974PRO_AC, "MSM8674PRO"},
+
+	/* 8x60AB IDs */
+	[138] = {MSM_CPU_8960AB, "MSM8960AB"},
+	[139] = {MSM_CPU_8960AB, "APQ8060AB"},
+	[140] = {MSM_CPU_8960AB, "MSM8260AB"},
+	[141] = {MSM_CPU_8960AB, "MSM8660AB"},
+
+	/* 8x84 IDs */
+	[178] = {MSM_CPU_8084, "APQ8084"},
+
+	/* 8x16 IDs */
+	[206] = {MSM_CPU_8916, "MSM8916"},
+	[247] = {MSM_CPU_8916, "APQ8016"},
+	[248] = {MSM_CPU_8916, "MSM8216"},
+	[249] = {MSM_CPU_8916, "MSM8116"},
+	[250] = {MSM_CPU_8916, "MSM8616"},
+
+	/* 8x96 IDs */
+	[246] = {MSM_CPU_8996, "MSM8996"},
+	[310] = {MSM_CPU_8996, "MSM8996AU"},
+	[311] = {MSM_CPU_8996, "APQ8096AU"},
+	[291] = {MSM_CPU_8996, "APQ8096"},
+	[305] = {MSM_CPU_8996, "MSM8996SG"},
+	[312] = {MSM_CPU_8996, "APQ8096SG"},
+
+	/*

drivers/soc/qcom/socinfo.c line 427

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+	 * Uninitialized IDs are not known to run Linux.
+	 * MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
+	 * considered as unknown CPU.
+	 */
+};
+
+static u32 socinfo_format;
+
+static u32 socinfo_get_id(void);
+

Merge socinfo_init_sysfs() and qcom_socinfo_init() into one function and you don't need to declare this here.

drivers/soc/qcom/socinfo.c line 432

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+/* socinfo: sysfs functions */
+
+static char *socinfo_get_id_string(void)
+{
+	return (socinfo) ? cpu_of_id[socinfo->v0_1.id].soc_id_string : NULL;

socinfo can't be NULL anymore.

drivers/soc/qcom/socinfo.c line 435

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+}
+
+static char *socinfo_get_image_version_base_address(struct device *dev)

Inline this into qcom_socinfo_init() as described below.

Quoted 12 lines
drivers/soc/qcom/socinfo.c new file +12 -0
+{
+	size_t size, size_in;
+	void *ptr;
+
+	ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
+			&size);
+	if (IS_ERR(ptr))
+		return ptr;
+
+	size_in = SMEM_IMAGE_VERSION_SIZE;
+	if (size_in != size) {
+		dev_err(dev, "Wrong size for smem item\n");

drivers/soc/qcom/socinfo.c line 457

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+		return ERR_PTR(-EINVAL);
+	}
+
+	return ptr;
+}
+
+
+static u32 socinfo_get_version(void)
+{
+	return (socinfo) ? socinfo->v0_1.version : 0;

socinfo can't be NULL, so you can just inline "socinfo->v0_1.version" in the one place calling this.

drivers/soc/qcom/socinfo.c line 462

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+}
+
+static char *socinfo_get_build_id(void)
+{
+	return (socinfo) ? socinfo->v0_1.build_id : NULL;

socinfo can't be NULL, and this is only called from one place, so inline "socinfo->v0_1.build_id" there.

drivers/soc/qcom/socinfo.c line 467

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+}
+
+static u32 socinfo_get_raw_version(void)
+{
+	return socinfo ?

socinfo can't be NULL.

drivers/soc/qcom/socinfo.c line 468

Quoted 1 line
drivers/soc/qcom/socinfo.c new file +1 -0
+		(socinfo_format >= SOCINFO_FORMAT(2) ?

qcom_soc_attr_raw_version will not be created unless socinfo_format >= 2, so this can't be called if socinfo_format < 2, so you don't need this extra check.

drivers/soc/qcom/socinfo.c line 470

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+			socinfo->v0_2.raw_version : 0)
+		: 0;

And as this is then simplified to "return socinfo->v0_2.raw_version;" I think you should just inline it in the one place calling this function.

Quoted 53 lines
drivers/soc/qcom/socinfo.c new file +53 -0
+}
+
+static u32 socinfo_get_platform_type(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(3) ?
+			socinfo->v0_3.hw_platform : 0)
+		: 0;
+}
+
+static u32 socinfo_get_platform_version(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(4) ?
+			socinfo->v0_4.platform_version : 0)
+		: 0;
+}
+
+static u32 socinfo_get_platform_subtype(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(6) ?
+			socinfo->v0_6.hw_platform_subtype : 0)
+		: 0;
+}
+
+static u32 socinfo_get_serial_number(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(10) ?
+			socinfo->v0_10.serial_number : 0)
+		: 0;
+}
+
+static u32 socinfo_get_pmic_model(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(7) ?
+			socinfo->v0_7.pmic_model : PMIC_MODEL_UNKNOWN)
+		: PMIC_MODEL_UNKNOWN;
+}
+
+static u32 socinfo_get_pmic_die_revision(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(7) ?
+			socinfo->v0_7.pmic_die_revision : 0)
+		: 0;
+}
+
+
+static ssize_t
+qcom_get_vendor(struct device *dev,

drivers/soc/qcom/socinfo.c line 533

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+		struct device_attribute *attr,
+		char *buf)
+{
+	return sprintf(buf, "%s", "Qualcomm\n");
+}
+
+static ssize_t
+qcom_get_raw_version(struct device *dev,
+		     struct device_attribute *attr,
+		     char *buf)

This is the "show" function of an attr, so please drop the "get" and add "_show".

drivers/soc/qcom/socinfo.c line 536

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+{
+	return sprintf(buf, "%u\n",
+		socinfo_get_raw_version());

And please inline as much as you can of these, there's little point in having a helper function to wrap a single line accessing the element in the socinfo struct.

Quoted 122 lines
drivers/soc/qcom/socinfo.c new file +122 -0
+}
+
+static ssize_t
+qcom_get_build_id(struct device *dev,
+		   struct device_attribute *attr,
+		   char *buf)
+{
+	return scnprintf(buf, SMEM_SOCINFO_BUILD_ID_LENGTH, "%s\n",
+				socinfo_get_build_id());
+}
+
+static ssize_t
+qcom_get_hw_platform(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 hw_type;
+
+	hw_type = socinfo_get_platform_type();
+
+	return sprintf(buf, "%s\n", hw_platform[hw_type]);
+}
+
+static ssize_t
+qcom_get_platform_version(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return sprintf(buf, "%u\n", socinfo_get_platform_version());
+}
+
+static ssize_t
+qcom_get_accessory_chip(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	u32 acc_chip = socinfo ? (socinfo_format >= SOCINFO_FORMAT(5) ?
+		socinfo->v0_5.accessory_chip : 0) : 0;
+	return sprintf(buf, "%u\n", acc_chip);
+}
+
+static ssize_t
+qcom_get_platform_subtype(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	if (socinfo_get_platform_type() == HW_PLATFORM_QRD) {
+		return sprintf(buf, "%s\n",
+			qrd_hw_platform_subtype[hw_subtype]);
+	} else {
+		return sprintf(buf, "%s\n",
+			hw_platform_subtype[hw_subtype]);
+	}
+}
+
+static ssize_t
+qcom_get_platform_subtype_id(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return sprintf(buf, "%u\n", socinfo_get_platform_subtype());
+}
+
+static ssize_t
+qcom_get_foundry_id(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 foundry_id = socinfo ? (socinfo_format >= SOCINFO_FORMAT(9) ?
+		socinfo->v0_9.foundry_id : 0) : 0;
+	return sprintf(buf, "%u\n", foundry_id);
+}
+
+static ssize_t
+qcom_get_serial_number(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return sprintf(buf, "%u\n", socinfo_get_serial_number());
+}
+
+static ssize_t
+qcom_get_chip_family(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 chip_family = socinfo ? (socinfo_format >= SOCINFO_FORMAT(12) ?
+		socinfo->v0_12.chip_family : 0) : 0;
+	return sprintf(buf, "0x%x\n", chip_family);
+}
+
+static ssize_t
+qcom_get_raw_device_family(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 raw_dev_fam = socinfo ? (socinfo_format >= SOCINFO_FORMAT(12) ?
+		socinfo->v0_12.raw_device_family : 0) : 0;
+	return sprintf(buf, "0x%x\n", raw_dev_fam);
+}
+
+static ssize_t
+qcom_get_raw_device_number(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 raw_dev_num = socinfo ? (socinfo_format >= SOCINFO_FORMAT(12) ?
+		socinfo->v0_12.raw_device_number : 0) : 0;
+	return sprintf(buf, "0x%x\n", raw_dev_num);
+}
+
+static ssize_t
+qcom_get_pmic_model(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	u32 pmic_id = socinfo_get_pmic_model();
+
+	return sprintf(buf, "%s\n", pmic_model[pmic_id]);
+}
+
+static ssize_t

drivers/soc/qcom/socinfo.c line 668

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+qcom_get_pmic_die_revision(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return sprintf(buf, "%u\n", socinfo_get_pmic_die_revision());
+}
+
+static ssize_t
+qcom_get_image_version(int index, char *buf)
+{

Just inline these into the version show() and store() functions. And whenever you copy to the sysfs buffer, it's of size PAGE_SIZE.

Quoted 31 lines
drivers/soc/qcom/socinfo.c new file +31 -0
+	return scnprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%s\n",
+			smem_image_version[index].name);
+}
+
+static ssize_t
+qcom_set_image_version(int index, const char *buf)
+{
+	return strlcpy(smem_image_version[index].name, buf,
+			SMEM_IMAGE_VERSION_NAME_SIZE);
+}
+
+static ssize_t
+qcom_get_image_variant(int index, char *buf)
+{
+	return scnprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%s\n",
+			smem_image_version[index].variant);
+}
+
+static ssize_t
+qcom_set_image_variant(int index, const char *buf)
+{
+	return strlcpy(smem_image_version[index].variant, buf,
+			SMEM_IMAGE_VERSION_VARIANT_SIZE);
+}
+
+static ssize_t
+qcom_get_image_crm_version(int index, char *buf)
+{
+	return scnprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%s\n",
+			smem_image_version[index].oem);
+}

drivers/soc/qcom/socinfo.c line 709

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+
+static ssize_t
+qcom_set_image_crm_version(int index, const char *buf)
+{
+	return strlcpy(smem_image_version[index].oem, buf,
+			SMEM_IMAGE_VERSION_OEM_SIZE);
+}
+
+static struct device_attribute qcom_soc_attr_raw_version =
+	__ATTR(raw_version, 0444, qcom_get_raw_version,  NULL);

Rather than writing all these out here you can put them in an array of:

struct qcom_socinfo_attr {
	struct device_attribute attr;
	int min_version;
};
#define QCOM_SOCINFO_ATTR(_name, _show, _min_version) \
	{ __ATTR(_name, 0444, _show, NULL), _min_version) }

static const struct qcom_socinfo_attr qcom_socinfo_attrs[] = {
QCOM_SOCINFO_ATTR(raw_version, qcom_get_raw_version, 2),
};

And then socinfo_populate_sysfs_files() will be a matter of looping over this array and comparing min_version and registering the attr.

Quoted 85 lines
drivers/soc/qcom/socinfo.c new file +85 -0
+
+static struct device_attribute qcom_soc_attr_vendor =
+	__ATTR(vendor, 0444, qcom_get_vendor,  NULL);
+
+static struct device_attribute qcom_soc_attr_build_id =
+	__ATTR(build_id, 0444, qcom_get_build_id, NULL);
+
+static struct device_attribute qcom_soc_attr_hw_platform =
+	__ATTR(hw_platform, 0444, qcom_get_hw_platform, NULL);
+
+
+static struct device_attribute qcom_soc_attr_platform_version =
+	__ATTR(platform_version, 0444,
+			qcom_get_platform_version, NULL);
+
+static struct device_attribute qcom_soc_attr_accessory_chip =
+	__ATTR(accessory_chip, 0444,
+			qcom_get_accessory_chip, NULL);
+
+static struct device_attribute qcom_soc_attr_platform_subtype =
+	__ATTR(platform_subtype, 0444,
+			qcom_get_platform_subtype, NULL);
+
+static struct device_attribute qcom_soc_attr_platform_subtype_id =
+	__ATTR(platform_subtype_id, 0444,
+			qcom_get_platform_subtype_id, NULL);
+
+static struct device_attribute qcom_soc_attr_foundry_id =
+	__ATTR(foundry_id, 0444,
+			qcom_get_foundry_id, NULL);
+
+static struct device_attribute qcom_soc_attr_serial_number =
+	__ATTR(serial_number, 0444,
+			qcom_get_serial_number, NULL);
+
+static struct device_attribute qcom_soc_attr_chip_family =
+	__ATTR(chip_family, 0444,
+			qcom_get_chip_family, NULL);
+
+static struct device_attribute qcom_soc_attr_raw_device_family =
+	__ATTR(raw_device_family, 0444,
+			qcom_get_raw_device_family, NULL);
+
+static struct device_attribute qcom_soc_attr_raw_device_number =
+	__ATTR(raw_device_number, 0444,
+			qcom_get_raw_device_number, NULL);
+
+static struct device_attribute qcom_soc_attr_pmic_model =
+	__ATTR(pmic_model, 0444,
+			qcom_get_pmic_model, NULL);
+
+static struct device_attribute qcom_soc_attr_pmic_die_revision =
+	__ATTR(pmic_die_revision, 0444,
+			qcom_get_pmic_die_revision, NULL);
+
+SMEM_IMAGE_TABLE_RO_ATTR(boot, SMEM_IMAGE_TABLE_BOOT_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(tz, SMEM_IMAGE_TABLE_TZ_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(rpm, SMEM_IMAGE_TABLE_RPM_INDEX);
+SMEM_IMAGE_TABLE_ATTR(apps, SMEM_IMAGE_TABLE_APPS_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(mpss, SMEM_IMAGE_TABLE_MPSS_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(adsp, SMEM_IMAGE_TABLE_ADSP_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(cnss, SMEM_IMAGE_TABLE_CNSS_INDEX);
+SMEM_IMAGE_TABLE_RO_ATTR(video, SMEM_IMAGE_TABLE_VIDEO_INDEX);
+
+static struct attribute_group
+	*smem_image_table[SMEM_IMAGE_VERSION_BLOCKS_COUNT] = {
+		[SMEM_IMAGE_TABLE_BOOT_INDEX] = &boot_image_attr_group,
+		[SMEM_IMAGE_TABLE_TZ_INDEX] = &tz_image_attr_group,
+		[SMEM_IMAGE_TABLE_RPM_INDEX] = &rpm_image_attr_group,
+		[SMEM_IMAGE_TABLE_APPS_INDEX] = &apps_image_attr_group,
+		[SMEM_IMAGE_TABLE_MPSS_INDEX] = &mpss_image_attr_group,
+		[SMEM_IMAGE_TABLE_ADSP_INDEX] = &adsp_image_attr_group,
+		[SMEM_IMAGE_TABLE_CNSS_INDEX] = &cnss_image_attr_group,
+		[SMEM_IMAGE_TABLE_VIDEO_INDEX] = &video_image_attr_group,
+};
+
+static int socinfo_populate_sysfs_files(struct device *qcom_soc_device)
+{
+	int err, img_idx;
+
+	/*
+	 * Expose SMEM_IMAGE_TABLE to sysfs only when we have IMAGE_TABLE
+	 * available in SMEM. As IMAGE_TABLE and SOCINFO are two separate
+	 * items within SMEM, we expose the remaining soc information(i.e
+	 * only the SOCINFO item available in SMEM) to sysfs even in the

drivers/soc/qcom/socinfo.c line 804

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+	 * absence of an IMAGE_TABLE.
+	 */
+	if (smem_img_tbl_avlbl) {
+		for (img_idx = 0; img_idx < SMEM_IMAGE_VERSION_BLOCKS_COUNT;
+				img_idx++) {
+			if (smem_image_table[img_idx]) {
+				err = sysfs_create_group(&qcom_soc_device->kobj,
+					smem_image_table[img_idx]);
+				if (err)
+					break;

Should we just ignore this error?

drivers/soc/qcom/socinfo.c line 809

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+			}
+		}
+	}
+	err = device_create_file(qcom_soc_device, &qcom_soc_attr_vendor);
+	if (!err) {

Flip this conditional around and handle the error here, it saves you one indentation level for the rest of this function.

Quoted 64 lines
drivers/soc/qcom/socinfo.c new file +64 -0
+		switch (socinfo_format) {
+		case SOCINFO_FORMAT(12):
+			err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_chip_family);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_raw_device_family);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_raw_device_number);
+		case SOCINFO_FORMAT(11):
+		case SOCINFO_FORMAT(10):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_serial_number);
+		case SOCINFO_FORMAT(9):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_foundry_id);
+		case SOCINFO_FORMAT(8):
+		case SOCINFO_FORMAT(7):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_pmic_model);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_pmic_die_revision);
+		case SOCINFO_FORMAT(6):
+			if (hw_subtype_valid)
+				if (!err)
+					err = device_create_file(
+						qcom_soc_device,
+					&qcom_soc_attr_platform_subtype);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+				&qcom_soc_attr_platform_subtype_id);
+		case SOCINFO_FORMAT(5):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_accessory_chip);
+		case SOCINFO_FORMAT(4):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_platform_version);
+		case SOCINFO_FORMAT(3):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_hw_platform);
+		case SOCINFO_FORMAT(2):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+						&qcom_soc_attr_raw_version);
+		case SOCINFO_FORMAT(1):
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+						&qcom_soc_attr_build_id);
+			if (err) {
+				dev_err(qcom_soc_device,
+					"Could not create sysfs entry\n");
+				return err;
+			}
+			return 0;
+		default:
+			dev_err(qcom_soc_device, "Unknown socinfo format: v0.%u\n",

drivers/soc/qcom/socinfo.c line 883

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+					SOCINFO_VERSION_MINOR(socinfo_format));
+			return -EINVAL;
+		}
+	} else {
+		dev_err(qcom_soc_device, "Could not create sysfs entry\n");
+		return err;
+	}
+}
+
+static int socinfo_init_sysfs(struct device *dev)

This device * is specifically the smem device, so if you name it "smem_dev"...

drivers/soc/qcom/socinfo.c line 885

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+{
+	struct device *qcom_soc_device;

...then you can name this "dev" to shorten things.

drivers/soc/qcom/socinfo.c line 887

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;

"attr" would be long enough.

drivers/soc/qcom/socinfo.c line 898

Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+	u32 soc_version;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return -ENOMEM;
+
+	soc_version = socinfo_get_version();
+
+	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id());
+	soc_dev_attr->family = "Snapdragon";
+	soc_dev_attr->machine = socinfo_get_id_string();

Single use of socinfo_get_id_string() so you should just go:

unsigned int id = socinfo->v0_1.id;

and then use that for your soc_id print and use soc_id_string[id] here.

Quoted 8 lines
drivers/soc/qcom/socinfo.c new file +8 -0
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u",
+				SOC_VERSION_MAJOR(soc_version),
+				SOC_VERSION_MINOR(soc_version));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr);
+		return PTR_ERR(soc_dev);

drivers/soc/qcom/socinfo.c line 916

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+	}
+
+	qcom_soc_device = soc_device_to_device(soc_dev);
+	socinfo_populate_sysfs_files(qcom_soc_device);
+	return 0;
+}
+
+static u32 socinfo_get_id(void)
+{
+	return (socinfo) ? socinfo->v0_1.id : 0;

As we no longer expose the socinfo functions to external callers this will only ever be called if socinfo_init() succeeded, so no need to check for socinfo being NULL.

Quoted 8 lines
drivers/soc/qcom/socinfo.c new file +8 -0
+}
+
+static int socinfo_select_format(struct device *dev)
+{
+	u32 f_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.format);
+	u32 f_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.format);
+
+	if (f_maj != 0) {

drivers/soc/qcom/socinfo.c line 934

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+		dev_err(dev, "Unsupported format v%u.%u.\n",
+			f_maj, f_min);
+		return -EINVAL;
+	}
+
+	if (socinfo->v0_1.format > MAX_SOCINFO_FORMAT) {
+		dev_warn(dev, "Unsupported format v%u.%u. Falling back to v%u.%u.\n",
+			f_maj, f_min, SOCINFO_VERSION_MAJOR(MAX_SOCINFO_FORMAT),
+			SOCINFO_VERSION_MINOR(MAX_SOCINFO_FORMAT));
+		socinfo_format = MAX_SOCINFO_FORMAT;

Don't fall back, just print an error and fail.

drivers/soc/qcom/socinfo.c line 941

Quoted 7 lines
drivers/soc/qcom/socinfo.c new file +7 -0
+	} else {
+		socinfo_format = socinfo->v0_1.format;
+	}
+	return 0;
+}
+
+int qcom_socinfo_init(struct platform_device *pdev)

As smem doesn't care if we're failing here you can just have the return type void.

drivers/soc/qcom/socinfo.c line 950

Quoted 9 lines
drivers/soc/qcom/socinfo.c new file +9 -0
+{
+	size_t size;
+
+	socinfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
+			&size);
+	if (IS_ERR(socinfo) || (socinfo_select_format(&pdev->dev) < 0)) {
+		dev_warn(&pdev->dev,
+			"Coudn't find soc information; Unable to setup socinfo.\n");
+		return -ENOMEM;

"Couldn't find socinfo" and return -ENOENT if IS_ERR(socinfo).

drivers/soc/qcom/socinfo.c line 951

Quoted 1 line
drivers/soc/qcom/socinfo.c new file +1 -0
+	}

And then just move the rest of socinfo_select_format() here:

	if (socinfo->v0.1.format > MAX_SOCINFO_FORMAT) {
		dev_err(&pdev->dev, "Invalid socinfo version %d.%d\n",
			MAJOR(), MINOR());
		return -EINVAL;
	}

drivers/soc/qcom/socinfo.c line 962

Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+
+	if (!socinfo_get_id()) {
+		dev_err(&pdev->dev, "socinfo: Unknown SoC ID!\n");
+		return -EINVAL;
+	}
+
+	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
+		"New IDs added! ID => CPU mapping needs an update.\n");
+
+	smem_image_version = (struct smem_image_version *)
+			socinfo_get_image_version_base_address(&pdev->dev);

You could make socinfo_get_image_version_base_address() return void * and you don't have to do the type cast. But you can make this more compact by just inlining the qcom_smem_get() here directly.

	smem_image_version = qcom_smem_get(QCOM_SMEM_HOST_ANY,
					   SMEM_IMAGE_VERSION_TABLE,
					   &size);
	if (IS_ERR(smem_image_version) || size != SMEM_IMAGE_VERSION_SIZE) {
		...
	}

drivers/soc/qcom/socinfo.c line 964

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+	if (IS_ERR(smem_image_version)) {
+		dev_warn(&pdev->dev, "Unable to get address for image version table.\n");

"Image version table missing" should keep you < 80 characters.

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+		smem_img_tbl_avlbl = false;
+	}
+
+	hw_subtype = socinfo_get_platform_subtype();
+	if (socinfo_get_platform_type() == HW_PLATFORM_QRD) {

drivers/soc/qcom/socinfo.c line 979

Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+		if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) {
+			dev_err(&pdev->dev, "Invalid hardware platform sub type for qrd found\n");
+			hw_subtype_valid = false;
+		}
+	} else {
+		if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) {
+			dev_err(&pdev->dev, "Invalid hardware platform subtype\n");
+			hw_subtype_valid = false;
+		}
+	}

This will only matter if format >= 6 and hw_subtype is outside the array of strings, I think you should just be optimistic about this not being an issue and then in all cases where you dereference a lookup table check that you're within bounds, or fail with -EINVAL; to userspace.

drivers/soc/qcom/socinfo.c line 981

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+
+	socinfo_init_sysfs(&pdev->dev);

socinfo_init_sysfs() is just the second half of this function, so inline it here.

drivers/soc/qcom/socinfo.c line 989

Quoted 8 lines
drivers/soc/qcom/socinfo.c new file +8 -0
+
+	/* Feed the soc specific unique data into entropy pool */
+	add_device_randomness(socinfo, size);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_socinfo_init);
+

No empty lines at the end of the file, please.

Regards,
Bjorn

author
#2 lore raw
Quoted 2 lines · Bjorn Andersson

On Wed 16 Nov 05:22 PST 2016, Imran Khan wrote:

<snip>

Quoted 51 lines
Quoted 51 lines
drivers/soc/qcom/socinfo.c new file +44 -0
new file mode 100644
index 0000000..eca46df
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 2009-2016, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/soc/qcom/smem.h>
+
+#define PMIC_MODEL_UNKNOWN 0
+#define HW_PLATFORM_QRD 11
+#define PLATFORM_SUBTYPE_QRD_INVALID 6
+#define PLATFORM_SUBTYPE_INVALID 4
+/*
+ * SOC version type with major number in the upper 16 bits and minor
+ * number in the lower 16 bits.  For example:
+ *   1.0 -> 0x00010000
+ *   2.3 -> 0x00020003
+ */
+#define SOC_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16)
+#define SOC_VERSION_MINOR(ver) ((ver) & 0x0000ffff)
+#define SOCINFO_FORMAT(x)  (x)
+#define SOCINFO_VERSION_MAJOR	SOC_VERSION_MAJOR
+#define SOCINFO_VERSION_MINOR	SOC_VERSION_MINOR
+
+#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 50

Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
+#define SMEM_IMAGE_VERSION_SIZE 4096
+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
+#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
+#define SMEM_IMAGE_VERSION_OEM_SIZE 32
+#define SMEM_IMAGE_VERSION_PARTITION_APPS 10

Please indent the values evenly, making this slightly easier to read.

Done.

Quoted 6 lines
Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+
+/*
+ * Shared memory identifiers, used to acquire handles to respective memory
+ * region.
+ */
+#define SMEM_IMAGE_VERSION_TABLE	469
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 55

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+
+/*
+ * Shared memory identifiers, used to acquire handles to respective memory
+ * region.
+ */

Duplicating this comment doesn't add value, please just drop this second copy and replace the above comment with something like "SMEM item ids"

Done.

Quoted 5 lines
Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+#define SMEM_HW_SW_BUILD_ID		137
+
+/*
+ * SMEM Image table indices
+ */

<snip>

Quoted 11 lines

Rather than having this based on two huge macros take a look at DEVICE_INT_ATTR() and struct dev_ext_attribute in include/linux/device.h. It looks like if you just put the index in a struct and use container_of to reach that you can replace these with direct functions.

Also, it's perfectly fine to always specify a store operation and use 0444 vs 0644 to control it's availability. So you don't need two sets if you just expose the mode in your macro.

If I understood this correct, the main idea here is to use dev_ext_attribute and avoid wrapper macros. Have tried to implement this suggestion in the subsequent patch set. Please let me know if it looks okay or can be improved further.

Quoted 11 lines
Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+
+/*
+ * Qcom SoC types
+ */
+enum qcom_cpu {
+	MSM_CPU_UNKNOWN = 0,
+	MSM_CPU_8960,
+	MSM_CPU_8960AB,
+	MSM_CPU_8064,
+	MSM_CPU_8974,
+	MSM_CPU_8974PRO_AA,
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 195

Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+	MSM_CPU_8974PRO_AB,
+	MSM_CPU_8974PRO_AC,
+	MSM_CPU_8916,
+	MSM_CPU_8084,
+	MSM_CPU_8996
+};

These are now "unused" (per below comment).

Done. As these are no more needed.

Quoted 7 lines

drivers/soc/qcom/socinfo.c line 198

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+
+struct qcom_soc_info {
+	enum qcom_cpu generic_soc_type;

This enum is no longer used, seems like you can turn cpu_of_id into a simple char *[] array with with soc_id_string indexed by id.

True. Have implemented cpu_of_id as per this suggestion.

Quoted 3 lines
Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+	char *soc_id_string;
+};
+

<snip>

Quoted 8 lines

drivers/soc/qcom/socinfo.c line 345

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+
+static struct smem_image_version *smem_image_version;
+static bool smem_img_tbl_avlbl = true;

You don't need to keep track of this separately, just test if smem_image_version is NULL or not (reset it to NULL if qcom_smem_get() fails).

Done.

Quoted 6 lines

drivers/soc/qcom/socinfo.c line 347

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+static bool hw_subtype_valid = true;
+static u32 hw_subtype;

Don't keep track of this in a global variable, it's perfectly fine to figure it out in qcom_get_platform_subtype()

Done.

Quoted 7 lines

drivers/soc/qcom/socinfo.c line 351

Quoted 4 lines
drivers/soc/qcom/socinfo.c new file +4 -0
+
+
+/* max socinfo format version supported */
+#define MAX_SOCINFO_FORMAT SOCINFO_FORMAT(12)

It's fine to drop SOCINFO_FORMAT and just put 12 here.

Done.

Quoted 5 lines
Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+
+static struct qcom_soc_info cpu_of_id[] = {
+
+	[0] = {MSM_CPU_UNKNOWN, "Unknown CPU"},
+

<snip>

Quoted 8 lines

drivers/soc/qcom/socinfo.c line 427

Quoted 4 lines
drivers/soc/qcom/socinfo.c new file +4 -0
+static u32 socinfo_format;
+
+static u32 socinfo_get_id(void);
+

Merge socinfo_init_sysfs() and qcom_socinfo_init() into one function and you don't need to declare this here.

Done.

Quoted 8 lines

drivers/soc/qcom/socinfo.c line 432

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+/* socinfo: sysfs functions */
+
+static char *socinfo_get_id_string(void)
+{
+	return (socinfo) ? cpu_of_id[socinfo->v0_1.id].soc_id_string : NULL;

socinfo can't be NULL anymore.

True. This checking is redundant indeed. In the subsequent patch set I have removed redundant checking of socinfo being NULL or not.

Quoted 6 lines

drivers/soc/qcom/socinfo.c line 435

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+}
+
+static char *socinfo_get_image_version_base_address(struct device *dev)

Inline this into qcom_socinfo_init() as described below.

Done.

Quoted 17 lines
Quoted 17 lines
drivers/soc/qcom/socinfo.c new file +17 -0
+{
+	size_t size, size_in;
+	void *ptr;
+
+	ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
+			&size);
+	if (IS_ERR(ptr))
+		return ptr;
+
+	size_in = SMEM_IMAGE_VERSION_SIZE;
+	if (size_in != size) {
+		dev_err(dev, "Wrong size for smem item\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return ptr;
+}
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 457

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+
+
+static u32 socinfo_get_version(void)
+{
+	return (socinfo) ? socinfo->v0_1.version : 0;

socinfo can't be NULL, so you can just inline "socinfo->v0_1.version" in the one place calling this.

Done.

Quoted 9 lines

drivers/soc/qcom/socinfo.c line 462

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+}
+
+static char *socinfo_get_build_id(void)
+{
+	return (socinfo) ? socinfo->v0_1.build_id : NULL;

socinfo can't be NULL, and this is only called from one place, so inline "socinfo->v0_1.build_id" there.

Done.

Quoted 10 lines

drivers/soc/qcom/socinfo.c line 467

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+}
+
+static u32 socinfo_get_raw_version(void)
+{
+	return socinfo ?

socinfo can't be NULL.

drivers/soc/qcom/socinfo.c line 468

Quoted 1 line
drivers/soc/qcom/socinfo.c new file +1 -0
+		(socinfo_format >= SOCINFO_FORMAT(2) ?

As mentioned above, have taken care of this.

Quoted 10 lines

qcom_soc_attr_raw_version will not be created unless socinfo_format >= 2, so this can't be called if socinfo_format < 2, so you don't need this extra check.

drivers/soc/qcom/socinfo.c

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+			socinfo->v0_2.raw_version : 0)
+		: 0;

And as this is then simplified to "return socinfo->v0_2.raw_version;" I think you should just inline it in the one place calling this function.

Done. Have removed redundant checking of socinfo format version from this and other functions and also have made these functions as much inline as possible.

Quoted 9 lines
Quoted 9 lines
drivers/soc/qcom/socinfo.c new file +9 -0
+}
+
+static u32 socinfo_get_platform_type(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_FORMAT(3) ?
+			socinfo->v0_3.hw_platform : 0)
+		: 0;
+}

<snip>

Quoted 9 lines

drivers/soc/qcom/socinfo.c line 533

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+
+static ssize_t
+qcom_get_raw_version(struct device *dev,
+		     struct device_attribute *attr,
+		     char *buf)

This is the "show" function of an attr, so please drop the "get" and add "_show".

Done. Have renamed attr show and store functions properly.

Quoted 8 lines

drivers/soc/qcom/socinfo.c line 536

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+{
+	return sprintf(buf, "%u\n",
+		socinfo_get_raw_version());

And please inline as much as you can of these, there's little point in having a helper function to wrap a single line accessing the element in the socinfo struct.

Done. Have tried this but please let me know if you see any further scope in this regard.

Quoted 11 lines
Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+}
+
+static ssize_t
+qcom_get_build_id(struct device *dev,
+		   struct device_attribute *attr,
+		   char *buf)
+{
+	return scnprintf(buf, SMEM_SOCINFO_BUILD_ID_LENGTH, "%s\n",
+				socinfo_get_build_id());
+}
+

<snip>

Quoted 7 lines
Quoted 7 lines
drivers/soc/qcom/socinfo.c new file +7 -0
+
+static ssize_t
+qcom_get_pmic_die_revision(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return sprintf(buf, "%u\n", socinfo_get_pmic_die_revision());
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 668

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+}
+
+static ssize_t
+qcom_get_image_version(int index, char *buf)
+{

Just inline these into the version show() and store() functions. And whenever you copy to the sysfs buffer, it's of size PAGE_SIZE.

Done.

Quoted 4 lines
Quoted 4 lines
drivers/soc/qcom/socinfo.c new file +4 -0
+	return scnprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%s\n",
+			smem_image_version[index].name);
+}
+

<snip>

Quoted 20 lines

drivers/soc/qcom/socinfo.c line 709

Quoted 9 lines
drivers/soc/qcom/socinfo.c new file +9 -0
+static ssize_t
+qcom_set_image_crm_version(int index, const char *buf)
+{
+	return strlcpy(smem_image_version[index].oem, buf,
+			SMEM_IMAGE_VERSION_OEM_SIZE);
+}
+
+static struct device_attribute qcom_soc_attr_raw_version =
+	__ATTR(raw_version, 0444, qcom_get_raw_version,  NULL);

Rather than writing all these out here you can put them in an array of:

struct qcom_socinfo_attr {
	struct device_attribute attr;
	int min_version;
};
#define QCOM_SOCINFO_ATTR(_name, _show, _min_version) \
	{ __ATTR(_name, 0444, _show, NULL), _min_version) }
Quoted 7 lines

static const struct qcom_socinfo_attr qcom_socinfo_attrs[] = {
QCOM_SOCINFO_ATTR(raw_version, qcom_get_raw_version, 2),
};

And then socinfo_populate_sysfs_files() will be a matter of looping over this array and comparing min_version and registering the attr.

Done. This makes the implementation really neat and concise. Thanks for this suggestion.

Quoted 6 lines
Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+
+static struct device_attribute qcom_soc_attr_vendor =
+	__ATTR(vendor, 0444, qcom_get_vendor,  NULL);
+
+static struct device_attribute qcom_soc_attr_build_id =
+	__ATTR(build_id, 0444, qcom_get_build_id, NULL);

<snip>

Quoted 9 lines
Quoted 9 lines
drivers/soc/qcom/socinfo.c new file +9 -0
+	/*
+	 * Expose SMEM_IMAGE_TABLE to sysfs only when we have IMAGE_TABLE
+	 * available in SMEM. As IMAGE_TABLE and SOCINFO are two separate
+	 * items within SMEM, we expose the remaining soc information(i.e
+	 * only the SOCINFO item available in SMEM) to sysfs even in the
+	 * absence of an IMAGE_TABLE.
+	 */
+	if (smem_img_tbl_avlbl) {
+		for (img_idx = 0; img_idx < SMEM_IMAGE_VERSION_BLOCKS_COUNT;
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 804

Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+				img_idx++) {
+			if (smem_image_table[img_idx]) {
+				err = sysfs_create_group(&qcom_soc_device->kobj,
+					smem_image_table[img_idx]);
+				if (err)
+					break;

Should we just ignore this error?

Yeah. I think we can and should ignore this error. Failing to create sysfs entry for one item in image table should not deprive other SMEM image items.

Quoted 9 lines

drivers/soc/qcom/socinfo.c line 809

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+			}
+		}
+	}
+	err = device_create_file(qcom_soc_device, &qcom_soc_attr_vendor);
+	if (!err) {

Flip this conditional around and handle the error here, it saves you one indentation level for the rest of this function.

Done. No more needed in new implementation.

Quoted 10 lines
Quoted 10 lines
drivers/soc/qcom/socinfo.c new file +10 -0
+		switch (socinfo_format) {
+		case SOCINFO_FORMAT(12):
+			err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_chip_family);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_raw_device_family);
+			if (!err)
+				err = device_create_file(qcom_soc_device,
+					&qcom_soc_attr_raw_device_number);

<snip>

Quoted 8 lines
Quoted 8 lines
drivers/soc/qcom/socinfo.c new file +8 -0
+			return 0;
+		default:
+			dev_err(qcom_soc_device, "Unknown socinfo format: v0.%u\n",
+					SOCINFO_VERSION_MINOR(socinfo_format));
+			return -EINVAL;
+		}
+	} else {
+		dev_err(qcom_soc_device, "Could not create sysfs entry\n");
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 883

Quoted 5 lines
drivers/soc/qcom/socinfo.c new file +5 -0
+		return err;
+	}
+}
+
+static int socinfo_init_sysfs(struct device *dev)

This device * is specifically the smem device, so if you name it "smem_dev"...

Done.

Quoted 5 lines

drivers/soc/qcom/socinfo.c line 885

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+{
+	struct device *qcom_soc_device;

...then you can name this "dev" to shorten things.

Done.

Quoted 5 lines

drivers/soc/qcom/socinfo.c line 887

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;

"attr" would be long enough.

Done.

Quoted 14 lines

drivers/soc/qcom/socinfo.c line 898

Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+	u32 soc_version;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return -ENOMEM;
+
+	soc_version = socinfo_get_version();
+
+	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id());
+	soc_dev_attr->family = "Snapdragon";
+	soc_dev_attr->machine = socinfo_get_id_string();

Single use of socinfo_get_id_string() so you should just go:

Quoted 4 lines

unsigned int id = socinfo->v0_1.id;

and then use that for your soc_id print and use soc_id_string[id] here.

Done.

Quoted 14 lines
Quoted 14 lines
drivers/soc/qcom/socinfo.c new file +14 -0
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u",
+				SOC_VERSION_MAJOR(soc_version),
+				SOC_VERSION_MINOR(soc_version));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr);
+		return PTR_ERR(soc_dev);
+	}
+
+	qcom_soc_device = soc_device_to_device(soc_dev);
+	socinfo_populate_sysfs_files(qcom_soc_device);
+	return 0;
+}
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 916

Quoted 4 lines
drivers/soc/qcom/socinfo.c new file +4 -0
+
+static u32 socinfo_get_id(void)
+{
+	return (socinfo) ? socinfo->v0_1.id : 0;

As we no longer expose the socinfo functions to external callers this will only ever be called if socinfo_init() succeeded, so no need to check for socinfo being NULL.

Done.

Quoted 12 lines
Quoted 12 lines
drivers/soc/qcom/socinfo.c new file +12 -0
+}
+
+static int socinfo_select_format(struct device *dev)
+{
+	u32 f_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.format);
+	u32 f_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.format);
+
+	if (f_maj != 0) {
+		dev_err(dev, "Unsupported format v%u.%u.\n",
+			f_maj, f_min);
+		return -EINVAL;
+	}
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 934

Quoted 6 lines
drivers/soc/qcom/socinfo.c new file +6 -0
+
+	if (socinfo->v0_1.format > MAX_SOCINFO_FORMAT) {
+		dev_warn(dev, "Unsupported format v%u.%u. Falling back to v%u.%u.\n",
+			f_maj, f_min, SOCINFO_VERSION_MAJOR(MAX_SOCINFO_FORMAT),
+			SOCINFO_VERSION_MINOR(MAX_SOCINFO_FORMAT));
+		socinfo_format = MAX_SOCINFO_FORMAT;

Don't fall back, just print an error and fail.

Done.

Quoted 11 lines

drivers/soc/qcom/socinfo.c line 941

Quoted 7 lines
drivers/soc/qcom/socinfo.c new file +7 -0
+	} else {
+		socinfo_format = socinfo->v0_1.format;
+	}
+	return 0;
+}
+
+int qcom_socinfo_init(struct platform_device *pdev)

As smem doesn't care if we're failing here you can just have the return type void.

Done.

Quoted 12 lines

drivers/soc/qcom/socinfo.c line 950

Quoted 9 lines
drivers/soc/qcom/socinfo.c new file +9 -0
+{
+	size_t size;
+
+	socinfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
+			&size);
+	if (IS_ERR(socinfo) || (socinfo_select_format(&pdev->dev) < 0)) {
+		dev_warn(&pdev->dev,
+			"Coudn't find soc information; Unable to setup socinfo.\n");
+		return -ENOMEM;

"Couldn't find socinfo" and return -ENOENT if IS_ERR(socinfo).

Done

Quoted 10 lines

drivers/soc/qcom/socinfo.c

Quoted 1 line
drivers/soc/qcom/socinfo.c new file +1 -0
+	}

And then just move the rest of socinfo_select_format() here:

	if (socinfo->v0.1.format > MAX_SOCINFO_FORMAT) {
		dev_err(&pdev->dev, "Invalid socinfo version %d.%d\n",
			MAJOR(), MINOR());
		return -EINVAL;
	}

Done

Quoted 16 lines

drivers/soc/qcom/socinfo.c line 962

Quoted 11 lines
drivers/soc/qcom/socinfo.c new file +11 -0
+
+	if (!socinfo_get_id()) {
+		dev_err(&pdev->dev, "socinfo: Unknown SoC ID!\n");
+		return -EINVAL;
+	}
+
+	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
+		"New IDs added! ID => CPU mapping needs an update.\n");
+
+	smem_image_version = (struct smem_image_version *)
+			socinfo_get_image_version_base_address(&pdev->dev);

You could make socinfo_get_image_version_base_address() return void * and you don't have to do the type cast. But you can make this more compact by just inlining the qcom_smem_get() here directly.

Quoted 7 lines
	smem_image_version = qcom_smem_get(QCOM_SMEM_HOST_ANY,
					   SMEM_IMAGE_VERSION_TABLE,
					   &size);
	if (IS_ERR(smem_image_version) || size != SMEM_IMAGE_VERSION_SIZE) {
		...
	}

Done

Quoted 5 lines

drivers/soc/qcom/socinfo.c line 964

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+	if (IS_ERR(smem_image_version)) {
+		dev_warn(&pdev->dev, "Unable to get address for image version table.\n");

"Image version table missing" should keep you < 80 characters.

Done.

Quoted 12 lines
Quoted 12 lines
drivers/soc/qcom/socinfo.c new file +12 -0
+		smem_img_tbl_avlbl = false;
+	}
+
+	hw_subtype = socinfo_get_platform_subtype();
+	if (socinfo_get_platform_type() == HW_PLATFORM_QRD) {
+		if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) {
+			dev_err(&pdev->dev, "Invalid hardware platform sub type for qrd found\n");
+			hw_subtype_valid = false;
+		}
+	} else {
+		if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) {
+			dev_err(&pdev->dev, "Invalid hardware platform subtype\n");
Quoted 9 lines

drivers/soc/qcom/socinfo.c line 978

Quoted 3 lines
drivers/soc/qcom/socinfo.c new file +3 -0
+			hw_subtype_valid = false;
+		}
+	}

This will only matter if format >= 6 and hw_subtype is outside the array of strings, I think you should just be optimistic about this not being an issue and then in all cases where you dereference a lookup table check that you're within bounds, or fail with -EINVAL; to userspace.

True. Have taken care of this. No more tracking this with a global variable.

Quoted 6 lines

drivers/soc/qcom/socinfo.c line 981

Quoted 2 lines
drivers/soc/qcom/socinfo.c new file +2 -0
+
+	socinfo_init_sysfs(&pdev->dev);

socinfo_init_sysfs() is just the second half of this function, so inline it here.

Done. now this is inline.

Quoted 11 lines

drivers/soc/qcom/socinfo.c line 989

Quoted 8 lines
drivers/soc/qcom/socinfo.c new file +8 -0
+
+	/* Feed the soc specific unique data into entropy pool */
+	add_device_randomness(socinfo, size);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_socinfo_init);
+

No empty lines at the end of the file, please.

Done.

Quoted 3 lines

Regards,
Bjorn

Thanks Bjorn for review comments.
Regards,
Imran

Signature · 1 line
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a\nmember of the Code Aurora Forum, hosted by The Linux Foundation
#3 lore raw
Quoted 1 line · Imran Khan

On 12/5/2016 11:35 PM, Bjorn Andersson wrote:

[..]

Quoted 12 lines
Quoted 11 lines

Rather than having this based on two huge macros take a look at DEVICE_INT_ATTR() and struct dev_ext_attribute in include/linux/device.h. It looks like if you just put the index in a struct and use container_of to reach that you can replace these with direct functions.

Also, it's perfectly fine to always specify a store operation and use 0444 vs 0644 to control it's availability. So you don't need two sets if you just expose the mode in your macro.

Quoted 5 lines

If I understood this correct, the main idea here is to use dev_ext_attribute and avoid wrapper macros. Have tried to implement this suggestion in the subsequent patch set. Please let me know if it looks okay or can be improved further.

Not necessarily using dev_ext_attribute directly, but using the same design (a struct and container_of) allows you do parameterize these functions.

Looking forward to v6.

Regards,
Bjorn