[PATCH linux dev-4.10] drivers/i2c: FSI: Fix bug on remove() and reset to upstream state
Eddie James
eajames at linux.vnet.ibm.com
Tue Aug 8 13:01:42 AEST 2017
From: "Edward A. James" <eajames at us.ibm.com>
Deleting entries in list on remove() even if the list was empty...
Also a few other fixes just to get it in line with what I've sent
upstream.
Resolves openbmc/linux#138
Signed-off-by: Edward A. James <eajames at us.ibm.com>
---
drivers/i2c/busses/i2c-fsi.c | 57 +++++++++++++++++++++++++-------------------
1 file changed, 32 insertions(+), 25 deletions(-)
diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index 7f59ec0..1af9c01 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -9,16 +9,20 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/device.h>
+#include <linux/errno.h>
#include <linux/fsi.h>
#include <linux/i2c.h>
#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/wait.h>
-#define FSI_ENGID_I2C_FSI 0x7
+#define FSI_ENGID_I2C 0x7
/* Find left shift from first set bit in m */
#define MASK_TO_LSH(m) (__builtin_ffsll(m) - 1ULL)
@@ -30,7 +34,6 @@
#define SETFIELD(m, v, val) \
(((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
-#define I2C_MASTER_NR_OFFSET 100
#define I2C_DEFAULT_CLK_DIV 6
/* i2c registers */
@@ -150,13 +153,13 @@ static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
u32 *data)
{
int rc;
- u32 raw_data;
+ __be32 data_be;
- rc = fsi_device_read(fsi, reg, &raw_data, sizeof(raw_data));
+ rc = fsi_device_read(fsi, reg, &data_be, sizeof(data_be));
if (rc)
return rc;
- *data = be32_to_cpu(raw_data);
+ *data = be32_to_cpu(data_be);
return 0;
}
@@ -164,9 +167,9 @@ static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
u32 *data)
{
- u32 raw_data = cpu_to_be32(*data);
+ __be32 data_be = cpu_to_be32(*data);
- return fsi_device_write(fsi, reg, &raw_data, sizeof(raw_data));
+ return fsi_device_write(fsi, reg, &data_be, sizeof(data_be));
}
static int fsi_i2c_lock_master(struct fsi_i2c_master *i2c, int timeout)
@@ -351,12 +354,12 @@ static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
static int fsi_i2c_handle_status(struct fsi_i2c_port *port,
struct i2c_msg *msg, u32 status)
{
- struct fsi_i2c_master *i2c = port->master;
- u8 fifo_count;
int rc;
+ u8 fifo_count;
+ struct fsi_i2c_master *i2c = port->master;
+ u32 dummy = 0;
if (status & I2C_STAT_ERR) {
- u32 dummy = 0;
rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy);
if (rc)
return rc;
@@ -383,11 +386,10 @@ static int fsi_i2c_handle_status(struct fsi_i2c_port *port,
rc = -ENODATA;
else
rc = msg->len;
+
return rc;
}
- dev_warn(&port->adapter.dev, "no status to handle\n");
-
return 0;
}
@@ -563,7 +565,11 @@ static int fsi_i2c_probe(struct device *dev)
i2c->fsi = to_fsi_dev(dev);
INIT_LIST_HEAD(&i2c->ports);
- /* Add adapter for each i2c port of the master */
+ rc = fsi_i2c_dev_init(i2c);
+ if (rc)
+ return rc;
+
+ /* Add adapter for each i2c port of the master. */
for_each_available_child_of_node(dev->of_node, np) {
rc = of_property_read_u32(np, "reg", &port_no);
if (rc || port_no > USHRT_MAX)
@@ -571,7 +577,7 @@ static int fsi_i2c_probe(struct device *dev)
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
if (!port)
- return -ENOMEM;
+ break;
port->master = i2c;
port->port = port_no;
@@ -584,19 +590,18 @@ static int fsi_i2c_probe(struct device *dev)
port->adapter.algo_data = port;
snprintf(port->adapter.name, sizeof(port->adapter.name),
- "fsi_i2c-%u", port_no);
+ "i2c_bus-%u", port_no);
rc = i2c_add_adapter(&port->adapter);
- if (rc < 0)
- return rc;
+ if (rc < 0) {
+ dev_err(dev, "Failed to register adapter: %d\n", rc);
+ devm_kfree(dev, port);
+ continue;
+ }
list_add(&port->list, &i2c->ports);
}
- rc = fsi_i2c_dev_init(i2c);
- if (rc)
- return rc;
-
dev_set_drvdata(dev, i2c);
return 0;
@@ -607,22 +612,24 @@ static int fsi_i2c_remove(struct device *dev)
struct fsi_i2c_master *i2c = dev_get_drvdata(dev);
struct fsi_i2c_port *port;
- list_for_each_entry(port, &i2c->ports, list) {
- i2c_del_adapter(&port->adapter);
+ if (!list_empty(&i2c->ports)) {
+ list_for_each_entry(port, &i2c->ports, list) {
+ i2c_del_adapter(&port->adapter);
+ }
}
return 0;
}
static const struct fsi_device_id fsi_i2c_ids[] = {
- { FSI_ENGID_I2C_FSI, FSI_VERSION_ANY },
+ { FSI_ENGID_I2C, FSI_VERSION_ANY },
{ 0 }
};
static struct fsi_driver fsi_i2c_driver = {
.id_table = fsi_i2c_ids,
.drv = {
- .name = "fsi_i2c_master",
+ .name = "i2c-fsi",
.bus = &fsi_bus_type,
.probe = fsi_i2c_probe,
.remove = fsi_i2c_remove,
--
1.8.3.1
More information about the openbmc
mailing list