Skip to contentSkip to conversation

mfd: Fetch cell pointer from platform_device->mfd_cell

RFC PATCH In review Samuel Ortiz 4 participants 8 messages Apr 8, 2011 – Apr 11, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 mfd: Fetch cell pointer from platform_device->mfd_cell

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is added to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

---
 drivers/base/platform.c         |    1 +
 drivers/mfd/mfd-core.c          |   16 ++++++++++++++--
 include/linux/mfd/core.h        |    8 ++++++--
 include/linux/platform_device.h |    5 +++++
 4 files changed, 26 insertions(+), 4 deletions(-)
drivers/base/platform.c +1 -0
index f051cff..6c3a2bd 100644
@@ -149,6 +149,7 @@ static void platform_device_release(struct device *dev)
 
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
drivers/mfd/mfd-core.c +14 -2
index d01574d..f4c8c84 100644
@@ -55,6 +55,19 @@ int mfd_cell_disable(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(mfd_cell_disable);
 
+static int mfd_platform_add_cell(struct platform_device *pdev,
+				 const struct mfd_cell *cell)
+{
+	if (!cell)
+		return 0;
+
+	pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
+	if (!pdev->mfd_cell)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int mfd_add_device(struct device *parent, int id,
 			  const struct mfd_cell *cell,
 			  struct resource *mem_base,
@@ -75,7 +88,7 @@ static int mfd_add_device(struct device *parent, int id,
 
 	pdev->dev.parent = parent;
 
-	ret = platform_device_add_data(pdev, cell, sizeof(*cell));
+	ret = mfd_platform_add_cell(pdev, cell);
 	if (ret)
 		goto fail_res;
 
@@ -123,7 +136,6 @@ static int mfd_add_device(struct device *parent, int id,
 
 	return 0;
 
-/*	platform_device_del(pdev); */
 fail_res:
 	kfree(res);
 fail_device:
include/linux/mfd/core.h +6 -2
index ad1b19a..ee4731b 100644
@@ -86,16 +86,20 @@ extern int mfd_clone_cell(const char *cell, const char **clones,
  */
 static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
 {
-	return pdev->dev.platform_data;
+	return pdev->mfd_cell;
 }
 
 /*
  * Given a platform device that's been created by mfd_add_devices(), fetch
  * the .mfd_data entry from the mfd_cell that created it.
+ * Otherwise just return the platform_data pointer.
  */
 static inline void *mfd_get_data(struct platform_device *pdev)
 {
-	return mfd_get_cell(pdev)->mfd_data;
+	if (pdev->mfd_cell)
+		return mfd_get_cell(pdev)->mfd_data;
+	else
+		return pdev->dev.platform_data;
 }
 
 extern int mfd_add_devices(struct device *parent, int id,
include/linux/platform_device.h +5 -0
index d96db98..744942c 100644
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+struct mfd_cell;
+
 struct platform_device {
 	const char	* name;
 	int		id;
@@ -23,6 +25,9 @@ struct platform_device {
 
 	const struct platform_device_id	*id_entry;
 
+	/* MFD cell pointer */
+	struct mfd_cell *mfd_cell;
+
 	/* arch specific additions */
 	struct pdev_archdata	archdata;
 };
Signature · 5 lines
1.7.2.3

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
#1 lore raw

This looks fine to me; just some minor points below.

On
Fri, 8 Apr 2011 02:40:09 +0200 Samuel Ortiz <[email protected]>

Quoted 23 lines · wrote:

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is t aed to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

---
 drivers/base/platform.c         |    1 +
 drivers/mfd/mfd-core.c          |   16 ++++++++++++++--
 include/linux/mfd/core.h        |    8 ++++++--
 include/linux/platform_device.h |    5 +++++
 4 files changed, 26 insertions(+), 4 deletions(-)
drivers/base/platform.c +0 -0
index f051cff..6c3a2bd 100644

drivers/base/platform.c static void platform_device_release(struct device · line 152

Quoted 4 lines
drivers/base/platform.c +1 -0
@@ -149,6 +149,7 @@ static void platform_device_release(struct device
 *dev) 
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);

Hm, given that most platform devices won't be mfd devices (and thus mfd_cell will be NULL), is it better to rely on kfree's unlikely(ZERO_OR_NULL_PTR(...)), or have this be "if (pa->pdev.mfd_cell) kfree(pa->pdev.mfd_cell);"?

Quoted 58 lines
drivers/base/platform.c +0 -0
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
drivers/mfd/mfd-core.c +14 -2
index d01574d..f4c8c84 100644
@@ -55,6 +55,19 @@ int mfd_cell_disable(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(mfd_cell_disable);
 
+static int mfd_platform_add_cell(struct platform_device *pdev,
+				 const struct mfd_cell *cell)
+{
+	if (!cell)
+		return 0;
+
+	pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
+	if (!pdev->mfd_cell)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int mfd_add_device(struct device *parent, int id,
 			  const struct mfd_cell *cell,
 			  struct resource *mem_base,
@@ -75,7 +88,7 @@ static int mfd_add_device(struct device *parent,
 int id, 
 	pdev->dev.parent = parent;
 
-	ret = platform_device_add_data(pdev, cell, sizeof(*cell));
+	ret = mfd_platform_add_cell(pdev, cell);
 	if (ret)
 		goto fail_res;
 
@@ -123,7 +136,6 @@ static int mfd_add_device(struct device *parent,
 int id, 
 	return 0;
 
-/*	platform_device_del(pdev); */
 fail_res:
 	kfree(res);
 fail_device:
include/linux/mfd/core.h +0 -0
index ad1b19a..ee4731b 100644
@@ -86,16 +86,20 @@ extern int mfd_clone_cell(const char *cell, const

char **clones, */
static inline const struct mfd_cell *mfd_get_cell(struct
platform_device *pdev) {

include/linux/mfd/core.h +1 -1
-	return pdev->dev.platform_data;
+	return pdev->mfd_cell;
 }
 
 /*
  * Given a platform device that's been created by mfd_add_devices(),
Quoted 3 lines

fetch
* the .mfd_data entry from the mfd_cell that created it.
+ * Otherwise just return the platform_data pointer.

I'd also suggest describing why we fall back to platform_data; to the casual reader, it would be confusing. Perhaps something to the effect of, "This maintains compatibility with platform drivers whose devices aren't created by the mfd layer, and expect platform_data to contain what would've otherwise been in mfd_data."

include/linux/mfd/core.h extern int mfd_clone_cell(const char *cell, const char **clones, · line 102

Quoted 8 lines

*/
static inline void *mfd_get_data(struct platform_device *pdev) {

include/linux/mfd/core.h +4 -1
-	return mfd_get_cell(pdev)->mfd_data;
+	if (pdev->mfd_cell)
+		return mfd_get_cell(pdev)->mfd_data;
+	else
+		return pdev->dev.platform_data;

Not much point checking pdev->mfd_cell and then using an abstraction. I'd just do "const struct mfd_cell *cell = mfd_get_cell(pdev); if (cell) return cell->mfd_data;" or "if (pdev->mfd_cell) return pdev->mfd_cell->mfd_data;"

Quoted 26 lines

}

extern int mfd_add_devices(struct device *parent, int id,

(quoted diff) +0 -0

b/include/linux/platform_device.h index d96db98..744942c 100644

include/linux/platform_device.h +5 -0
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+struct mfd_cell;
+
 struct platform_device {
 	const char	* name;
 	int		id;
@@ -23,6 +25,9 @@ struct platform_device {
 
 	const struct platform_device_id	*id_entry;
 
+	/* MFD cell pointer */
+	struct mfd_cell *mfd_cell;
+
 	/* arch specific additions */
 	struct pdev_archdata	archdata;
 };
#2 lore raw

Hi Andres,

Quoted 6 lines · Andres Salomon
Quoted 6 lines
drivers/base/platform.c +0 -0
index f051cff..6c3a2bd 100644
@@ -149,6 +149,7 @@ static void platform_device_release(struct device
 *dev) 
Quoted 8 lines

drivers/base/platform.c static void platform_device_release(struct device *dev) · line 152

Quoted 3 lines
drivers/base/platform.c +1 -0
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);

Hm, given that most platform devices won't be mfd devices (and thus mfd_cell will be NULL), is it better to rely on kfree's unlikely(ZERO_OR_NULL_PTR(...)), or have this be "if (pa->pdev.mfd_cell) kfree(pa->pdev.mfd_cell);"?

I'd say the former (obviously), unless Greg wants it to be otherwise.

Quoted 10 lines
Quoted 10 lines
include/linux/mfd/core.h +0 -0
@@ -86,16 +86,20 @@ extern int mfd_clone_cell(const char *cell, const

char **clones, */
static inline const struct mfd_cell *mfd_get_cell(struct
platform_device *pdev) {

include/linux/mfd/core.h +1 -1
-	return pdev->dev.platform_data;
+	return pdev->mfd_cell;
 }
Quoted 12 lines
Quoted 5 lines

/*
* Given a platform device that's been created by mfd_add_devices(),
fetch
* the .mfd_data entry from the mfd_cell that created it.
+ * Otherwise just return the platform_data pointer.

I'd also suggest describing why we fall back to platform_data; to the casual reader, it would be confusing. Perhaps something to the effect of, "This maintains compatibility with platform drivers whose devices aren't created by the mfd layer, and expect platform_data to contain what would've otherwise been in mfd_data."

Right. I'll add that.

Quoted 10 lines

include/linux/mfd/core.h extern int mfd_clone_cell(const char *cell, const char **clones, · line 102

Quoted 8 lines

*/
static inline void *mfd_get_data(struct platform_device *pdev) {

include/linux/mfd/core.h +4 -1
-	return mfd_get_cell(pdev)->mfd_data;
+	if (pdev->mfd_cell)
+		return mfd_get_cell(pdev)->mfd_data;
+	else
+		return pdev->dev.platform_data;

Not much point checking pdev->mfd_cell and then using an abstraction.

That's right as well. I'll send v1 next with those 2 fixes.

Thanks for the review.

Cheers,
Samuel.

Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/
#3 lore raw
Quoted 17 lines · Samuel Ortiz

Hi Andres,

Quoted 6 lines · Andres Salomon
Quoted 6 lines
drivers/base/platform.c +0 -0
index f051cff..6c3a2bd 100644
@@ -149,6 +149,7 @@ static void platform_device_release(struct device
 *dev) 
Quoted 8 lines

drivers/base/platform.c static void platform_device_release(struct device *dev) · line 152

Quoted 3 lines
drivers/base/platform.c +1 -0
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);

Hm, given that most platform devices won't be mfd devices (and thus mfd_cell will be NULL), is it better to rely on kfree's unlikely(ZERO_OR_NULL_PTR(...)), or have this be "if (pa->pdev.mfd_cell) kfree(pa->pdev.mfd_cell);"?

Quoted 1 line

I'd say the former (obviously), unless Greg wants it to be otherwise.

Yes, as the patch was originally written is fine with me.

thanks,

greg k-h

#4 lore raw

PATCH 1/1 mfd: Fetch cell pointer from platform_device->mfd_cell

In reply to Andres Salomon

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is added to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

---

RFC -> v1:
- Add more mfd_get_data() comments.
- Cleaned up mfd_get_data()

---
 drivers/base/platform.c         |    1 +
 drivers/mfd/mfd-core.c          |   16 ++++++++++++++--
 include/linux/mfd/core.h        |   13 +++++++++++--
 include/linux/platform_device.h |    5 +++++
 4 files changed, 31 insertions(+), 4 deletions(-)
drivers/base/platform.c +1 -0
index f051cff..6c3a2bd 100644
@@ -149,6 +149,7 @@ static void platform_device_release(struct device *dev)
 
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
drivers/mfd/mfd-core.c +14 -2
index d01574d..f4c8c84 100644
@@ -55,6 +55,19 @@ int mfd_cell_disable(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(mfd_cell_disable);
 
+static int mfd_platform_add_cell(struct platform_device *pdev,
+				 const struct mfd_cell *cell)
+{
+	if (!cell)
+		return 0;
+
+	pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
+	if (!pdev->mfd_cell)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int mfd_add_device(struct device *parent, int id,
 			  const struct mfd_cell *cell,
 			  struct resource *mem_base,
@@ -75,7 +88,7 @@ static int mfd_add_device(struct device *parent, int id,
 
 	pdev->dev.parent = parent;
 
-	ret = platform_device_add_data(pdev, cell, sizeof(*cell));
+	ret = mfd_platform_add_cell(pdev, cell);
 	if (ret)
 		goto fail_res;
 
@@ -123,7 +136,6 @@ static int mfd_add_device(struct device *parent, int id,
 
 	return 0;
 
-/*	platform_device_del(pdev); */
 fail_res:
 	kfree(res);
 fail_device:
include/linux/mfd/core.h +11 -2
index ad1b19a..aef23309 100644
@@ -86,16 +86,25 @@ extern int mfd_clone_cell(const char *cell, const char **clones,
  */
 static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
 {
-	return pdev->dev.platform_data;
+	return pdev->mfd_cell;
 }
 
 /*
  * Given a platform device that's been created by mfd_add_devices(), fetch
  * the .mfd_data entry from the mfd_cell that created it.
+ * Otherwise just return the platform_data pointer.
+ * This maintains compatibility with platform drivers whose devices aren't
+ * created by the mfd layer, and expect platform_data to contain what would've
+ * otherwise been in mfd_data.
  */
 static inline void *mfd_get_data(struct platform_device *pdev)
 {
-	return mfd_get_cell(pdev)->mfd_data;
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+
+	if (cell)
+		return cell->mfd_data;
+	else
+		return pdev->dev.platform_data;
 }
 
 extern int mfd_add_devices(struct device *parent, int id,
include/linux/platform_device.h +5 -0
index d96db98..744942c 100644
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+struct mfd_cell;
+
 struct platform_device {
 	const char	* name;
 	int		id;
@@ -23,6 +25,9 @@ struct platform_device {
 
 	const struct platform_device_id	*id_entry;
 
+	/* MFD cell pointer */
+	struct mfd_cell *mfd_cell;
+
 	/* arch specific additions */
 	struct pdev_archdata	archdata;
 };
Signature · 5 lines
1.7.2.3

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
Acked-by on v1 1/1
#5 lore raw
Quoted 11 lines · Samuel Ortiz

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is added to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

I'm guesing this will go through someone elses tree than mine?

thanks,

greg k-h

#6 lore raw
Quoted 9 lines · Greg KH
Quoted 8 lines · Samuel Ortiz

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is added to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

Quoted 7 lines
Quoted 3 lines

I'm guesing this will go through someone elses tree than mine?

I'd say so. Samuel, please get this out to Linus,

thanks,
g.

#7 lore raw
In reply to Greg KH
Quoted 9 lines · Greg KH
Quoted 8 lines · Samuel Ortiz

In order for MFD drivers to fetch their cell pointer but also their platform data one, an mfd cell pointer is added to the platform_device structure.
That allows all MFD sub devices drivers to be MFD agnostic, unless they really need to access their MFD cell data. Most of them don't, especially the ones for IPs used by both MFD and non MFD SoCs.

Quoted 5 lines
Quoted 3 lines

Thanks.

Quoted 1 line

I'm guesing this will go through someone elses tree than mine?

Yes, I'll push it through my MFD tree.

Cheers,
Samuel.

Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/