[PATCH 2/5] usb: ulpi: change operations api to pass parent device directly

From: Tal Shorer
Date: Sat Jul 30 2016 - 19:23:01 EST


struct ulpi_ops is defined as follows:

struct ulpi_ops {
struct device *dev;
int (*read)(struct ulpi_ops *ops, u8 addr);
int (*write)(struct ulpi_ops *ops, u8 addr, u8 val);
};

Upon calling ulpi_register_interface(), the struct device argument is
put inside the struct ulpi_ops argument's dev field. Later, when
calling the actual read()/write() operations, the struct ulpi_ops is
passed to them and they use the stored device to access whatever
private data they need.

This means that if one wishes to reuse the same oprations for multiple
interfaces (e.g if we have multiple instances of the same controller),
any but the last interface registered will not operate properly (and
the one that does work will be at the mercy of the others to not mess
it up).

Fix this by passing the given struct device directly to the operation
functions (ulpi->dev.parent) in ulpi_read() and ulpi_write() instead
of via the ops argument

Signed-off-by: Tal Shorer <tal.shorer@xxxxxxxxx>
---
drivers/usb/common/ulpi.c | 4 ++--
drivers/usb/dwc3/ulpi.c | 8 ++++----
include/linux/ulpi/interface.h | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index d1f419c..fdaed7c 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -21,13 +21,13 @@

int ulpi_read(struct ulpi *ulpi, u8 addr)
{
- return ulpi->ops->read(ulpi->ops, addr);
+ return ulpi->ops->read(ulpi->dev.parent, addr);
}
EXPORT_SYMBOL_GPL(ulpi_read);

int ulpi_write(struct ulpi *ulpi, u8 addr, u8 val)
{
- return ulpi->ops->write(ulpi->ops, addr, val);
+ return ulpi->ops->write(ulpi->dev.parent, addr, val);
}
EXPORT_SYMBOL_GPL(ulpi_write);

diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c
index ec004c6..51ac939 100644
--- a/drivers/usb/dwc3/ulpi.c
+++ b/drivers/usb/dwc3/ulpi.c
@@ -35,9 +35,9 @@ static int dwc3_ulpi_busyloop(struct dwc3 *dwc)
return -ETIMEDOUT;
}

-static int dwc3_ulpi_read(struct ulpi_ops *ops, u8 addr)
+static int dwc3_ulpi_read(struct device *dev, u8 addr)
{
- struct dwc3 *dwc = dev_get_drvdata(ops->dev);
+ struct dwc3 *dwc = dev_get_drvdata(dev);
u32 reg;
int ret;

@@ -53,9 +53,9 @@ static int dwc3_ulpi_read(struct ulpi_ops *ops, u8 addr)
return DWC3_GUSB2PHYACC_DATA(reg);
}

-static int dwc3_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val)
+static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
{
- struct dwc3 *dwc = dev_get_drvdata(ops->dev);
+ struct dwc3 *dwc = dev_get_drvdata(dev);
u32 reg;

reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h
index 4de8ab4..ac3cd80 100644
--- a/include/linux/ulpi/interface.h
+++ b/include/linux/ulpi/interface.h
@@ -13,8 +13,8 @@ struct ulpi;
*/
struct ulpi_ops {
struct device *dev;
- int (*read)(struct ulpi_ops *ops, u8 addr);
- int (*write)(struct ulpi_ops *ops, u8 addr, u8 val);
+ int (*read)(struct device *dev, u8 addr);
+ int (*write)(struct device *dev, u8 addr, u8 val);
};

struct ulpi *ulpi_register_interface(struct device *, struct ulpi_ops *);
--
2.7.4