Explorar o código

greybus: spilib: make spilib independent of gbphy

spilib is used by multiple users currently (spi.c and fw-core.c) but
commit aa52b62a0556 broke that hierarchy and introduced gbphy dependent
code in spilib.

This may have unreliable consequences as we are doing following
operation unconditionally now:

	gbphy_dev = to_gbphy_dev(spi->parent);
	gbphy_runtime_get_sync(gbphy_dev);

which may not go well when the parent is of type &bundle->dev
(fw-core.c).

This patch introduces spilib_ops and lets the users of the core register
them. This shall have no functional change for the spi.c usecase and
shall fix the unreliable results for the fw-core.c usecase.

Tested by writing to mtd0 dev and verifying (with print messages) that
the below routines are getting called for a gpbridge-test module.

Fixes: aa52b62a0556 ("spi: Add runtime_pm support")
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Viresh Kumar %!s(int64=9) %!d(string=hai) anos
pai
achega
92bcaddea3

+ 1 - 1
drivers/staging/greybus/fw-core.c

@@ -38,7 +38,7 @@ static int gb_fw_spi_connection_init(struct gb_connection *connection)
 	if (ret)
 		return ret;
 
-	ret = gb_spilib_master_init(connection, &connection->bundle->dev);
+	ret = gb_spilib_master_init(connection, &connection->bundle->dev, NULL);
 	if (ret) {
 		gb_connection_disable(connection);
 		return ret;

+ 22 - 1
drivers/staging/greybus/spi.c

@@ -13,6 +13,27 @@
 #include "gbphy.h"
 #include "spilib.h"
 
+#ifndef SPI_CORE_SUPPORT_PM
+static int gbphy_spi_prepare_transfer_hardware(struct device *dev)
+{
+	return gbphy_runtime_get_sync(to_gbphy_dev(dev));
+}
+
+static void gbphy_spi_unprepare_transfer_hardware(struct device *dev)
+{
+	gbphy_runtime_put_autosuspend(to_gbphy_dev(dev));
+}
+
+static struct spilib_ops __spilib_ops = {
+	.prepare_transfer_hardware = gbphy_spi_prepare_transfer_hardware,
+	.unprepare_transfer_hardware = gbphy_spi_unprepare_transfer_hardware,
+};
+
+static struct spilib_ops *spilib_ops = &__spilib_ops;
+#else
+static struct spilib_ops *spilib_ops = NULL;
+#endif
+
 static int gb_spi_probe(struct gbphy_device *gbphy_dev,
 			const struct gbphy_device_id *id)
 {
@@ -29,7 +50,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev,
 	if (ret)
 		goto exit_connection_destroy;
 
-	ret = gb_spilib_master_init(connection, &gbphy_dev->dev);
+	ret = gb_spilib_master_init(connection, &gbphy_dev->dev, spilib_ops);
 	if (ret)
 		goto exit_connection_disable;
 

+ 16 - 12
drivers/staging/greybus/spilib.c

@@ -15,13 +15,13 @@
 
 #include "greybus.h"
 #include "spilib.h"
-#include "gbphy.h"
 
 struct gb_spilib {
 	struct gb_connection	*connection;
 	struct device		*parent;
 	struct spi_transfer	*first_xfer;
 	struct spi_transfer	*last_xfer;
+	struct spilib_ops	*ops;
 	u32			rx_xfer_offset;
 	u32			tx_xfer_offset;
 	u32			last_xfer_size;
@@ -373,25 +373,21 @@ out:
 	return ret;
 }
 
-#ifndef SPI_CORE_SUPPORT_PM
 static int gb_spi_prepare_transfer_hardware(struct spi_master *master)
 {
 	struct gb_spilib *spi = spi_master_get_devdata(master);
-	struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent);
 
-	return gbphy_runtime_get_sync(gbphy_dev);
+	return spi->ops->prepare_transfer_hardware(spi->parent);
 }
 
 static int gb_spi_unprepare_transfer_hardware(struct spi_master *master)
 {
 	struct gb_spilib *spi = spi_master_get_devdata(master);
-	struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent);
 
-	gbphy_runtime_put_autosuspend(gbphy_dev);
+	spi->ops->unprepare_transfer_hardware(spi->parent);
 
 	return 0;
 }
-#endif
 
 static int gb_spi_setup(struct spi_device *spi)
 {
@@ -483,7 +479,8 @@ static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs)
 	return 0;
 }
 
-int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
+int gb_spilib_master_init(struct gb_connection *connection, struct device *dev,
+			  struct spilib_ops *ops)
 {
 	struct gb_spilib *spi;
 	struct spi_master *master;
@@ -501,6 +498,7 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
 	spi->connection = connection;
 	gb_connection_set_data(connection, master);
 	spi->parent = dev;
+	spi->ops = ops;
 
 	/* get master configuration */
 	ret = gb_spi_get_master_config(spi);
@@ -518,11 +516,17 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
 	master->setup = gb_spi_setup;
 	master->transfer_one_message = gb_spi_transfer_one_message;
 
-#ifndef SPI_CORE_SUPPORT_PM
-	master->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware;
-	master->unprepare_transfer_hardware =
+	if (ops && ops->prepare_transfer_hardware) {
+		master->prepare_transfer_hardware =
+			gb_spi_prepare_transfer_hardware;
+	}
+
+	if (ops && ops->unprepare_transfer_hardware) {
+		master->unprepare_transfer_hardware =
 			gb_spi_unprepare_transfer_hardware;
-#else
+	}
+
+#ifdef SPI_CORE_SUPPORT_PM
 	master->auto_runtime_pm = true;
 #endif
 

+ 7 - 1
drivers/staging/greybus/spilib.h

@@ -10,9 +10,15 @@
 #ifndef __SPILIB_H
 #define __SPILIB_H
 
+struct device;
 struct gb_connection;
 
-int gb_spilib_master_init(struct gb_connection *connection, struct device *dev);
+struct spilib_ops {
+	int (*prepare_transfer_hardware)(struct device *dev);
+	void (*unprepare_transfer_hardware)(struct device *dev);
+};
+
+int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops);
 void gb_spilib_master_exit(struct gb_connection *connection);
 
 #endif /* __SPILIB_H */