Skip to contentSkip to conversation

soc: qcom: smem: introduce qcom_smem_virt_to_phys()

PATCH In review Alex Elder 3 participants 5 messages Apr 25, 2018 – Apr 26, 2018

Subsystems (2)
lore
Share & tools
lore

Alex Elder

author
#0 lore raw

PATCH 1/1 soc: qcom: smem: introduce qcom_smem_virt_to_phys()

Create function qcom_smem_virt_to_phys(), which returns the physical address corresponding to a given SMEM item's virtual address. This feature is required for a driver that will soon be out for review.

---
 drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++
 include/linux/soc/qcom/smem.h |  2 ++
 2 files changed, 29 insertions(+)
drivers/soc/qcom/smem.c +27 -0
index 7d9a43da5084..70b2ee80d6bd 100644
@@ -655,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
 }
 EXPORT_SYMBOL(qcom_smem_get_free_space);
 
+/**
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p:	the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.
+ */
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+	unsigned i;
+
+	for (i = 0; i < __smem->num_regions; i++) {
+		struct smem_region *region = &__smem->regions[i];
+
+		if (p < region->virt_base)
+			continue;
+		if (p < region->virt_base + region->size) {
+			u64 offset = p - region->virt_base;
+
+			return (phys_addr_t)region->aux_base + offset;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);
+
 static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
 {
 	struct smem_header *header;
include/linux/soc/qcom/smem.h +2 -0
index c1657ed27b30..86e1b358688a 100644
@@ -9,4 +9,6 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size);
 
 int qcom_smem_get_free_space(unsigned host);
 
+phys_addr_t qcom_smem_virt_to_phys(void *p);
+
 #endif
Signature · 1 line
2.14.1
Reviewed-by on v1 1/1
#1 lore raw
Quoted 4 lines · Alex Elder

Create function qcom_smem_virt_to_phys(), which returns the physical address corresponding to a given SMEM item's virtual address. This feature is required for a driver that will soon be out for review.

It might be wise to turn the aux_base in smem_region into a phys_addr_t and then mask that with AUX_BASE_MASK before comparing with the entry's aux_base in qcom_smem_get_global(). But this will work fine until the day someone places smem above 4GB.

Regards,
Bjorn

Quoted 62 lines
---
 drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++
 include/linux/soc/qcom/smem.h |  2 ++
 2 files changed, 29 insertions(+)
drivers/soc/qcom/smem.c +27 -0
index 7d9a43da5084..70b2ee80d6bd 100644
@@ -655,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
 }
 EXPORT_SYMBOL(qcom_smem_get_free_space);
 
+/**
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p:	the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.
+ */
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+	unsigned i;
+
+	for (i = 0; i < __smem->num_regions; i++) {
+		struct smem_region *region = &__smem->regions[i];
+
+		if (p < region->virt_base)
+			continue;
+		if (p < region->virt_base + region->size) {
+			u64 offset = p - region->virt_base;
+
+			return (phys_addr_t)region->aux_base + offset;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);
+
 static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
 {
 	struct smem_header *header;
include/linux/soc/qcom/smem.h +2 -0
index c1657ed27b30..86e1b358688a 100644
@@ -9,4 +9,6 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size);
 
 int qcom_smem_get_free_space(unsigned host);
 
+phys_addr_t qcom_smem_virt_to_phys(void *p);
+
 #endif
Signature · 6 lines
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author
#2 lore raw
Quoted 11 lines · Bjorn Andersson
Quoted 4 lines · Alex Elder

Create function qcom_smem_virt_to_phys(), which returns the physical address corresponding to a given SMEM item's virtual address. This feature is required for a driver that will soon be out for review.

It might be wise to turn the aux_base in smem_region into a phys_addr_t and then mask that with AUX_BASE_MASK before comparing with the entry's aux_base in qcom_smem_get_global(). But this will work fine until the day someone places smem above 4GB.

I thought of that but went for this for now, because it made for a nice, concise change. I agree with you though.

Thanks a lot for the quick review.

-Alex

Quoted 67 lines

Regards,
Bjorn

Quoted 62 lines
---
 drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++
 include/linux/soc/qcom/smem.h |  2 ++
 2 files changed, 29 insertions(+)
drivers/soc/qcom/smem.c +27 -0
index 7d9a43da5084..70b2ee80d6bd 100644
@@ -655,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
 }
 EXPORT_SYMBOL(qcom_smem_get_free_space);
 
+/**
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p:	the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.
+ */
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+	unsigned i;
+
+	for (i = 0; i < __smem->num_regions; i++) {
+		struct smem_region *region = &__smem->regions[i];
+
+		if (p < region->virt_base)
+			continue;
+		if (p < region->virt_base + region->size) {
+			u64 offset = p - region->virt_base;
+
+			return (phys_addr_t)region->aux_base + offset;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);
+
 static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
 {
 	struct smem_header *header;
include/linux/soc/qcom/smem.h +2 -0
index c1657ed27b30..86e1b358688a 100644
@@ -9,4 +9,6 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size);
 
 int qcom_smem_get_free_space(unsigned host);
 
+phys_addr_t qcom_smem_virt_to_phys(void *p);
+
 #endif
Signature · 6 lines
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw
In reply to Alex Elder

Hi Alex,

Minor comment.

Quoted 19 lines · Alex Elder

Create function qcom_smem_virt_to_phys(), which returns the physical address corresponding to a given SMEM item's virtual address. This feature is required for a driver that will soon be out for review.

---
  drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++
  include/linux/soc/qcom/smem.h |  2 ++
  2 files changed, 29 insertions(+)
drivers/soc/qcom/smem.c +1 -0
index 7d9a43da5084..70b2ee80d6bd 100644
@@ -655,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
  }
  EXPORT_SYMBOL(qcom_smem_get_free_space);
 
+/**

drivers/soc/qcom/smem.c int qcom_smem_get_free_space(unsigned host) · line 668

Quoted 10 lines
drivers/soc/qcom/smem.c +10 -0
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p:	the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.
+ */
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+	unsigned i;
+

We have a null pointer check for __smem here since it is called by external clients. This case should probably never happen though.

Quoted 5 lines
drivers/soc/qcom/smem.c +5 -0
+	for (i = 0; i < __smem->num_regions; i++) {
+		struct smem_region *region = &__smem->regions[i];
+
+		if (p < region->virt_base)
+			continue;

drivers/soc/qcom/smem.c int qcom_smem_get_free_space(unsigned host) · line 683

Quoted 10 lines
drivers/soc/qcom/smem.c +10 -0
+		if (p < region->virt_base + region->size) {
+			u64 offset = p - region->virt_base;
+
+			return (phys_addr_t)region->aux_base + offset;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);

Thanks,
Chris

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author
#4 lore raw
Quoted 28 lines · Chris Lew

Hi Alex,

Minor comment.

Quoted 23 lines · Alex Elder

Create function qcom_smem_virt_to_phys(), which returns the physical address corresponding to a given SMEM item's virtual address.  This feature is required for a driver that will soon be out for review.

---
  drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++ include/linux/soc/qcom/smem.h |  2 ++

  2 files changed, 29 insertions(+)
drivers/soc/qcom/smem.c +0 -0
index 7d9a43da5084..70b2ee80d6bd 100644
@@ -655,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
   }
   EXPORT_SYMBOL(qcom_smem_get_free_space);

  +/**
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p:    the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.

Quoted 8 lines

drivers/soc/qcom/smem.c int qcom_smem_get_free_space(unsigned host) · line 668

Quoted 5 lines

+ */

drivers/soc/qcom/smem.c +4 -0
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+    unsigned i;
+

We have a null pointer check for __smem here since it is called by external clients. This case should probably never happen though.

I think you're suggesting that we should verify __smem is non-null first?

I'll make a few statements about that.
- This function can only be called with a pointer that was returned by qcom_smem_get(). That function won't return a valid pointer unless __smem was non-null.
- The only other way __smem would be null is if this were called after qcom_smem_remove(), which is erroneous.
- I think putting a null pointer check suggests that it's a condition that might be expected to occur. If anything, I'd put an assertion in there (e.g. BUG_ON(!__smem)) but I don't think it's warranted.

I do understand why you suggest this--and it's a relatively harmless
check. But I think it's better without it.

-Alex

Quoted 19 lines
Quoted 5 lines

+    for (i = 0; i < __smem->num_regions; i++) { +        struct smem_region *region = &__smem->regions[i];

drivers/soc/qcom/smem.c +3 -0
+
+        if (p < region->virt_base)
+            continue;

drivers/soc/qcom/smem.c int qcom_smem_get_free_space(unsigned host) · line 683

Quoted 10 lines
drivers/soc/qcom/smem.c +10 -0
+        if (p < region->virt_base + region->size) {
+            u64 offset = p - region->virt_base;
+
+            return (phys_addr_t)region->aux_base + offset;
+        }
+    }
+
+    return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);

Thanks,
Chris