soc: qcom: smem: introduce qcom_smem_virt_to_phys()

Message ID 20180425151820.25595-1-elder@linaro.org
State Accepted
Commit 6d361c1db7b69fddf5748cf212169ab57bb13a6e
Headers show
Series
  • soc: qcom: smem: introduce qcom_smem_virt_to_phys()
Related show

Commit Message

Alex Elder April 25, 2018, 3:18 p.m.
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.

Signed-off-by: Alex Elder <elder@linaro.org>

---
 drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++
 include/linux/soc/qcom/smem.h |  2 ++
 2 files changed, 29 insertions(+)

-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Bjorn Andersson April 25, 2018, 11:14 p.m. | #1
On Wed 25 Apr 08:18 PDT 2018, Alex Elder wrote:

> 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.

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>


Regards,
Bjorn

> Signed-off-by: Alex Elder <elder@linaro.org>

> ---

>  drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++

>  include/linux/soc/qcom/smem.h |  2 ++

>  2 files changed, 29 insertions(+)

> 

> diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c

> index 7d9a43da5084..70b2ee80d6bd 100644

> --- a/drivers/soc/qcom/smem.c

> +++ b/drivers/soc/qcom/smem.c

> @@ -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;

> diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h

> index c1657ed27b30..86e1b358688a 100644

> --- a/include/linux/soc/qcom/smem.h

> +++ b/include/linux/soc/qcom/smem.h

> @@ -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

> -- 

> 2.14.1

> 

> --

> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in

> the body of a message to majordomo@vger.kernel.org

> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chris Lew April 25, 2018, 11:29 p.m. | #2
Hi Alex,

Minor comment.

On 4/25/2018 8:18 AM, Alex Elder wrote:
> 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.

> 

> Signed-off-by: Alex Elder <elder@linaro.org>

> ---

>   drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++

>   include/linux/soc/qcom/smem.h |  2 ++

>   2 files changed, 29 insertions(+)

> 

> diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c

> index 7d9a43da5084..70b2ee80d6bd 100644

> --- a/drivers/soc/qcom/smem.c

> +++ b/drivers/soc/qcom/smem.c

> @@ -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;

> +


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

> +	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);


Thanks,
Chris

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alex Elder April 26, 2018, 1:22 a.m. | #3
On 04/25/2018 06:14 PM, Bjorn Andersson wrote:
> On Wed 25 Apr 08:18 PDT 2018, Alex Elder wrote:

> 

>> 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

> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>

> 

> Regards,

> Bjorn

> 

>> Signed-off-by: Alex Elder <elder@linaro.org>

>> ---

>>  drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++

>>  include/linux/soc/qcom/smem.h |  2 ++

>>  2 files changed, 29 insertions(+)

>>

>> diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c

>> index 7d9a43da5084..70b2ee80d6bd 100644

>> --- a/drivers/soc/qcom/smem.c

>> +++ b/drivers/soc/qcom/smem.c

>> @@ -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;

>> diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h

>> index c1657ed27b30..86e1b358688a 100644

>> --- a/include/linux/soc/qcom/smem.h

>> +++ b/include/linux/soc/qcom/smem.h

>> @@ -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

>> -- 

>> 2.14.1

>>

>> --

>> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in

>> the body of a message to majordomo@vger.kernel.org

>> More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alex Elder April 26, 2018, 1:31 a.m. | #4
On 04/25/2018 06:29 PM, Chris Lew wrote:
> Hi Alex,

> 

> Minor comment.

> 

> On 4/25/2018 8:18 AM, Alex Elder wrote:

>> 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.

>>

>> Signed-off-by: Alex Elder <elder@linaro.org>

>> ---

>>   drivers/soc/qcom/smem.c       | 27 +++++++++++++++++++++++++++

>>   include/linux/soc/qcom/smem.h |  2 ++

>>   2 files changed, 29 insertions(+)

>>

>> diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c

>> index 7d9a43da5084..70b2ee80d6bd 100644

>> --- a/drivers/soc/qcom/smem.c

>> +++ b/drivers/soc/qcom/smem.c

>> @@ -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;

>> +

> 

> 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


>> +    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);

> 

> Thanks,

> Chris

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 7d9a43da5084..70b2ee80d6bd 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -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;
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
index c1657ed27b30..86e1b358688a 100644
--- a/include/linux/soc/qcom/smem.h
+++ b/include/linux/soc/qcom/smem.h
@@ -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