This is a batch of cleanup patches picked from the ChromeOS 3.8 kernel
tree and applied to ToT. Most of these patches were authored by Bill
Richardson (CCed). Where appropriate I've squashed patches together,
though I have erred on the side of keeping patches logically distinct
rather than squashing into one big cleanup patch.
There is very little functionality added by this series, but this gets
us closer to how things look in the ChromeOS tree so we can add more
patches atop it. In general I took the oldest patches from our tree
and stopped picking when I got to a reasonable patch size (10
patches). There are about 5 more cleanup patches still in the
ChromeOS tree, then some more major functionality patches.
Note that I didn't take the "cros_ec_dev" userspace inteface, the
"LPC" implementation, the "vboot context" implementation, and patches
relating to exynos5250-spring when picking patches. These bits are
very separate (and big!) and can be added and debated separately after
we've got cleanup in. Whenever patches touched those pieces of the
code I ignored that part of the patch. In general I did take cleanup
code that was intended to make it easier to later add these bits.
I have tested basic functionality of these patches on exynos5250-snow
and exynos5420-peach-pit.
Bill Richardson (9):
mfd: cros_ec: Fix the comment on cros_ec_remove()
mfd: cros_ec: IRQs for cros_ec should be optional
mfd: cros_ec: Allow static din/dout buffers with cros_ec_register()
mfd: cros_ec: Tweak struct cros_ec_device for clarity
mfd: cros_ec: Use struct cros_ec_command to communicate with the EC
mfd: cros_ec: cleanup: remove unused fields from struct cros_ec_device
mfd: cros_ec: cleanup: Remove EC wrapper functions
mfd: cros_ec: Check result code from EC messages
mfd: cros_ec: ec_dev->cmd_xfer() returns number of bytes received from
EC
Simon Glass (1):
mdf: cros_ec: Detect in-progress commands
drivers/i2c/busses/i2c-cros-ec-tunnel.c | 17 ++++--
drivers/input/keyboard/cros_ec_keyb.c | 14 ++++-
drivers/mfd/cros_ec.c | 76 +++++++-----------------
drivers/mfd/cros_ec_i2c.c | 44 ++++++++------
drivers/mfd/cros_ec_spi.c | 43 ++++++++------
include/linux/mfd/cros_ec.h | 100 +++++++++++++++-----------------
6 files changed, 144 insertions(+), 150 deletions(-)
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
This comment was incorrect, so update it.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Simon Glass <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
include/linux/mfd/cros_ec.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 887ef4f..7e9fe6e 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -148,8 +148,7 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
/**
* cros_ec_remove - Remove a ChromeOS EC
*
- * Call this to deregister a ChromeOS EC. After this you should call
- * cros_ec_free().
+ * Call this to deregister a ChromeOS EC, then clean up any private data.
*
* @ec_dev: Device to register
* @return 0 if ok, -ve on error
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
Preparing the way for the LPC device, which is just a plaform_device without
interrupts.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 38fe9bf..bd6f936 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -119,17 +119,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return -ENOMEM;
}
- if (!ec_dev->irq) {
- dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
- return err;
- }
-
- err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "chromeos-ec", ec_dev);
- if (err) {
- dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
- return err;
+ if (ec_dev->irq) {
+ err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "chromeos-ec", ec_dev);
+ if (err) {
+ dev_err(dev, "request irq %d: error %d\n",
+ ec_dev->irq, err);
+ return err;
+ }
}
err = mfd_add_devices(dev, 0, cros_devs,
@@ -145,7 +143,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return 0;
fail_mfd:
- free_irq(ec_dev->irq, ec_dev);
+ if (ec_dev->irq)
+ free_irq(ec_dev->irq, ec_dev);
return err;
}
@@ -154,7 +153,8 @@ EXPORT_SYMBOL(cros_ec_register);
int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
- free_irq(ec_dev->irq, ec_dev);
+ if (ec_dev->irq)
+ free_irq(ec_dev->irq, ec_dev);
return 0;
}
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
The lower-level driver may want to provide its own buffers. If so,
there's no need to allocate new ones. This already happens to work
just fine (since we check for size of 0 and use devm allocation), but
it's good to document it.
[dianders: Resolved conflicts; documented that no code changes needed
on mainline]
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
include/linux/mfd/cros_ec.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 7e9fe6e..2ee3190 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -68,8 +68,8 @@ struct cros_ec_msg {
* We use this alignment to keep ARM and x86 happy. Probably word
* alignment would be OK, there might be a small performance advantage
* to using dword.
- * @din_size: size of din buffer
- * @dout_size: size of dout buffer
+ * @din_size: size of din buffer to allocate (zero to use static din)
+ * @dout_size: size of dout buffer to allocate (zero to use static dout)
* @command_send: send a command
* @command_recv: receive a command
* @ec_name: name of EC device (e.g. 'chromeos-ec')
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
The members of struct cros_ec_device were improperly commented, and
intermixed the private and public sections. This is just cleanup to make it
more obvious what goes with what.
[dianders: left lock in the structure but gave it the name that will
eventually be used.]
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec.c | 2 +-
drivers/mfd/cros_ec_i2c.c | 4 +--
drivers/mfd/cros_ec_spi.c | 10 +++----
include/linux/mfd/cros_ec.h | 65 ++++++++++++++++++++++++---------------------
4 files changed, 43 insertions(+), 38 deletions(-)
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index bd6f936..a9eede5 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -57,7 +57,7 @@ static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
msg.in_buf = in_buf;
msg.in_len = in_len;
- return ec_dev->command_xfer(ec_dev, &msg);
+ return ec_dev->cmd_xfer(ec_dev, &msg);
}
static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 4f71be9..777e529 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -29,7 +29,7 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
return i2c_get_clientdata(client);
}
-static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
+static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
struct cros_ec_msg *msg)
{
struct i2c_client *client = ec_dev->priv;
@@ -136,7 +136,7 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
ec_dev->dev = dev;
ec_dev->priv = client;
ec_dev->irq = client->irq;
- ec_dev->command_xfer = cros_ec_command_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
ec_dev->ec_name = client->name;
ec_dev->phys_name = client->adapter->name;
ec_dev->parent = &client->dev;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 0b8d328..52d4d7b 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -73,7 +73,7 @@
* if no record
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn off CS at the end of a transaction.
- * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
+ * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
*/
struct cros_ec_spi {
struct spi_device *spi;
@@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
}
/**
- * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
+ * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
*
* @ec_dev: ChromeOS EC device
* @ec_msg: Message to transfer
*/
-static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *ec_msg)
+static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
+ struct cros_ec_msg *ec_msg)
{
struct cros_ec_spi *ec_spi = ec_dev->priv;
struct spi_transfer trans;
@@ -372,7 +372,7 @@ static int cros_ec_spi_probe(struct spi_device *spi)
ec_dev->dev = dev;
ec_dev->priv = ec_spi;
ec_dev->irq = spi->irq;
- ec_dev->command_xfer = cros_ec_command_spi_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
ec_dev->ec_name = ec_spi->spi->modalias;
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
ec_dev->parent = &ec_spi->spi->dev;
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 2ee3190..79a3585 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -16,7 +16,9 @@
#ifndef __LINUX_MFD_CROS_EC_H
#define __LINUX_MFD_CROS_EC_H
+#include <linux/notifier.h>
#include <linux/mfd/cros_ec_commands.h>
+#include <linux/mutex.h>
/*
* Command interface between EC and AP, for LPC, I2C and SPI interfaces.
@@ -55,34 +57,53 @@ struct cros_ec_msg {
/**
* struct cros_ec_device - Information about a ChromeOS EC device
*
+ * @ec_name: name of EC device (e.g. 'chromeos-ec')
+ * @phys_name: name of physical comms layer (e.g. 'i2c-4')
+ * @dev: Device pointer
+ * @was_wake_device: true if this device was set to wake the system from
+ * sleep at the last suspend
+ * @event_notifier: interrupt event notifier for transport devices
+ * @command_send: send a command
+ * @command_recv: receive a response
+ * @command_sendrecv: send a command and receive a response
+ *
* @name: Name of this EC interface
* @priv: Private data
* @irq: Interrupt to use
- * @din: input buffer (from EC)
- * @dout: output buffer (to EC)
+ * @din: input buffer (for data from EC)
+ * @dout: output buffer (for data to EC)
* \note
* These two buffers will always be dword-aligned and include enough
* space for up to 7 word-alignment bytes also, so we can ensure that
* the body of the message is always dword-aligned (64-bit).
- *
* We use this alignment to keep ARM and x86 happy. Probably word
* alignment would be OK, there might be a small performance advantage
* to using dword.
* @din_size: size of din buffer to allocate (zero to use static din)
* @dout_size: size of dout buffer to allocate (zero to use static dout)
- * @command_send: send a command
- * @command_recv: receive a command
- * @ec_name: name of EC device (e.g. 'chromeos-ec')
- * @phys_name: name of physical comms layer (e.g. 'i2c-4')
* @parent: pointer to parent device (e.g. i2c or spi device)
- * @dev: Device pointer
- * dev_lock: Lock to prevent concurrent access
* @wake_enabled: true if this device can wake the system from sleep
- * @was_wake_device: true if this device was set to wake the system from
- * sleep at the last suspend
- * @event_notifier: interrupt event notifier for transport devices
+ * @lock: one transaction at a time
+ * @cmd_xfer: low-level channel to the EC
*/
struct cros_ec_device {
+
+ /* These are used by other drivers that want to talk to the EC */
+ const char *ec_name;
+ const char *phys_name;
+ struct device *dev;
+ bool was_wake_device;
+ struct class *cros_class;
+ struct blocking_notifier_head event_notifier;
+ int (*command_send)(struct cros_ec_device *ec,
+ uint16_t cmd, void *out_buf, int out_len);
+ int (*command_recv)(struct cros_ec_device *ec,
+ uint16_t cmd, void *in_buf, int in_len);
+ int (*command_sendrecv)(struct cros_ec_device *ec,
+ uint16_t cmd, void *out_buf, int out_len,
+ void *in_buf, int in_len);
+
+ /* These are used to implement the platform-specific interface */
const char *name;
void *priv;
int irq;
@@ -90,26 +111,10 @@ struct cros_ec_device {
uint8_t *dout;
int din_size;
int dout_size;
- int (*command_send)(struct cros_ec_device *ec,
- uint16_t cmd, void *out_buf, int out_len);
- int (*command_recv)(struct cros_ec_device *ec,
- uint16_t cmd, void *in_buf, int in_len);
- int (*command_sendrecv)(struct cros_ec_device *ec,
- uint16_t cmd, void *out_buf, int out_len,
- void *in_buf, int in_len);
- int (*command_xfer)(struct cros_ec_device *ec,
- struct cros_ec_msg *msg);
-
- const char *ec_name;
- const char *phys_name;
struct device *parent;
-
- /* These are --private-- fields - do not assign */
- struct device *dev;
- struct mutex dev_lock;
bool wake_enabled;
- bool was_wake_device;
- struct blocking_notifier_head event_notifier;
+ struct mutex lock;
+ int (*cmd_xfer)(struct cros_ec_device *ec, struct cros_ec_msg *msg);
};
/**
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
struct cros_ec_device has a superfluous "name" field. We can get all the
debugging info we need from the existing ec_name and phys_name fields, so
let's take out the extra field.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec.c | 2 +-
drivers/mfd/cros_ec_i2c.c | 1 -
drivers/mfd/cros_ec_spi.c | 1 -
include/linux/mfd/cros_ec.h | 2 --
4 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 9304056..d242714 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -138,7 +138,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
goto fail_mfd;
}
- dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
+ dev_info(dev, "Chrome EC device registered\n");
return 0;
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 37ed12f..5bb32f5 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -132,7 +132,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, ec_dev);
- ec_dev->name = "I2C";
ec_dev->dev = dev;
ec_dev->priv = client;
ec_dev->irq = client->irq;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 2d713fe..09ca789 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -374,7 +374,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
cros_ec_spi_dt_probe(ec_spi, dev);
spi_set_drvdata(spi, ec_dev);
- ec_dev->name = "SPI";
ec_dev->dev = dev;
ec_dev->priv = ec_spi;
ec_dev->irq = spi->irq;
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index f27c037..2b0c598 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -67,7 +67,6 @@ struct cros_ec_command {
* @command_recv: receive a response
* @command_sendrecv: send a command and receive a response
*
- * @name: Name of this EC interface
* @priv: Private data
* @irq: Interrupt to use
* @din: input buffer (for data from EC)
@@ -104,7 +103,6 @@ struct cros_ec_device {
void *in_buf, int in_len);
/* These are used to implement the platform-specific interface */
- const char *name;
void *priv;
int irq;
uint8_t *din;
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
Just because the host was able to talk to the EC doesn't mean that the EC
was happy with what it was told. Errors in communincation are not the same
as error messages from the EC itself.
This change lets the EC report its errors separately.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec_i2c.c | 15 +++++++++++----
drivers/mfd/cros_ec_spi.c | 26 ++++++++++++++------------
2 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 5bb32f5..2276096 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -92,11 +92,18 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
}
/* check response error code */
- if (i2c_msg[1].buf[0]) {
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- msg->command, i2c_msg[1].buf[0]);
- ret = -EINVAL;
+ msg->result = i2c_msg[1].buf[0];
+ switch (msg->result) {
+ case EC_RES_SUCCESS:
+ break;
+ case EC_RES_IN_PROGRESS:
+ ret = -EAGAIN;
+ dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+ msg->command);
goto done;
+ default:
+ dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
+ msg->command, msg->result);
}
/* copy response packet payload and compute checksum */
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 09ca789..4d34f1c 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -289,21 +289,23 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
goto exit;
}
- /* check response error code */
ptr = ec_dev->din;
- if (ptr[0]) {
- if (ptr[0] == EC_RES_IN_PROGRESS) {
- dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
- ec_msg->command);
- ret = -EAGAIN;
- goto exit;
- }
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- ec_msg->command, ptr[0]);
- debug_packet(ec_dev->dev, "in_err", ptr, len);
- ret = -EINVAL;
+
+ /* check response error code */
+ ec_msg->result = ptr[0];
+ switch (ec_msg->result) {
+ case EC_RES_SUCCESS:
+ break;
+ case EC_RES_IN_PROGRESS:
+ ret = -EAGAIN;
+ dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+ ec_msg->command);
goto exit;
+ default:
+ dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
+ ec_msg->command, ec_msg->result);
}
+
len = ptr[1];
sum = ptr[0] + ptr[1];
if (len > ec_msg->insize) {
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
Remove the three wrapper functions that talk to the EC without passing all
the desired arguments and just use the underlying communication function
that passes everything in a struct intead.
This is internal code refactoring only. Nothing should change.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/i2c/busses/i2c-cros-ec-tunnel.c | 15 +++++++++++----
drivers/input/keyboard/cros_ec_keyb.c | 14 ++++++++++++--
drivers/mfd/cros_ec.c | 32 --------------------------------
include/linux/mfd/cros_ec.h | 19 ++++++-------------
4 files changed, 29 insertions(+), 51 deletions(-)
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index 8e7a714..dd07818 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
u8 *request = NULL;
u8 *response = NULL;
int result;
+ struct cros_ec_command msg;
request_len = ec_i2c_count_message(i2c_msgs, num);
if (request_len < 0) {
@@ -218,9 +219,15 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
}
ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
- result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
- request, request_len,
- response, response_len);
+
+ msg.version = 0;
+ msg.command = EC_CMD_I2C_PASSTHRU;
+ msg.outdata = request;
+ msg.outsize = request_len;
+ msg.indata = response;
+ msg.insize = response_len;
+
+ result = bus->ec->cmd_xfer(bus->ec, &msg);
if (result)
goto exit;
@@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_device *pdev)
u32 remote_bus;
int err;
- if (!ec->command_sendrecv) {
+ if (!ec->cmd_xfer) {
dev_err(dev, "Missing sendrecv\n");
return -EINVAL;
}
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 4083796..dc37b6b 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -191,8 +191,18 @@ static void cros_ec_keyb_close(struct input_dev *dev)
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
{
- return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
- kb_state, ckdev->cols);
+ int ret;
+ struct cros_ec_command msg = {
+ .version = 0,
+ .command = EC_CMD_MKBP_STATE,
+ .outdata = NULL,
+ .outsize = 0,
+ .indata = kb_state,
+ .insize = ckdev->cols,
+ };
+
+ ret = ckdev->ec->cmd_xfer(ckdev->ec, &msg);
+ return ret;
}
static int cros_ec_keyb_work(struct notifier_block *nb,
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index d242714..6dd91e9 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -44,34 +44,6 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
}
EXPORT_SYMBOL(cros_ec_prepare_tx);
-static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *out_buf, int out_len,
- void *in_buf, int in_len)
-{
- struct cros_ec_command msg;
-
- msg.version = cmd >> 8;
- msg.command = cmd & 0xff;
- msg.outdata = out_buf;
- msg.outsize = out_len;
- msg.indata = in_buf;
- msg.insize = in_len;
-
- return ec_dev->cmd_xfer(ec_dev, &msg);
-}
-
-static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
-}
-
-static int cros_ec_command_send(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
-}
-
static irqreturn_t ec_irq_thread(int irq, void *data)
{
struct cros_ec_device *ec_dev = data;
@@ -104,10 +76,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
- ec_dev->command_send = cros_ec_command_send;
- ec_dev->command_recv = cros_ec_command_recv;
- ec_dev->command_sendrecv = cros_ec_command_sendrecv;
-
if (ec_dev->din_size) {
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 2b0c598..60c0880 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -63,9 +63,10 @@ struct cros_ec_command {
* @was_wake_device: true if this device was set to wake the system from
* sleep at the last suspend
* @event_notifier: interrupt event notifier for transport devices
- * @command_send: send a command
- * @command_recv: receive a response
- * @command_sendrecv: send a command and receive a response
+ * @cmd_xfer: send command to EC and get response
+ * Returns 0 if the communication succeeded, but that doesn't mean the EC
+ * was happy with the command it got. Caller should check msg.result for
+ * the EC's result code.
*
* @priv: Private data
* @irq: Interrupt to use
@@ -83,7 +84,6 @@ struct cros_ec_command {
* @parent: pointer to parent device (e.g. i2c or spi device)
* @wake_enabled: true if this device can wake the system from sleep
* @lock: one transaction at a time
- * @cmd_xfer: low-level channel to the EC
*/
struct cros_ec_device {
@@ -94,13 +94,8 @@ struct cros_ec_device {
bool was_wake_device;
struct class *cros_class;
struct blocking_notifier_head event_notifier;
- int (*command_send)(struct cros_ec_device *ec,
- uint16_t cmd, void *out_buf, int out_len);
- int (*command_recv)(struct cros_ec_device *ec,
- uint16_t cmd, void *in_buf, int in_len);
- int (*command_sendrecv)(struct cros_ec_device *ec,
- uint16_t cmd, void *out_buf, int out_len,
- void *in_buf, int in_len);
+ int (*cmd_xfer)(struct cros_ec_device *ec,
+ struct cros_ec_command *msg);
/* These are used to implement the platform-specific interface */
void *priv;
@@ -112,8 +107,6 @@ struct cros_ec_device {
struct device *parent;
bool wake_enabled;
struct mutex lock;
- int (*cmd_xfer)(struct cros_ec_device *ec,
- struct cros_ec_command *msg);
};
/**
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
When communicating with the EC, the cmd_xfer() function should return the
number of bytes it received from the EC, or negative on error.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/i2c/busses/i2c-cros-ec-tunnel.c | 2 +-
drivers/mfd/cros_ec_i2c.c | 2 +-
drivers/mfd/cros_ec_spi.c | 2 +-
include/linux/mfd/cros_ec.h | 8 ++++----
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index dd07818..05e033c 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -228,7 +228,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
msg.insize = response_len;
result = bus->ec->cmd_xfer(bus->ec, &msg);
- if (result)
+ if (result < 0)
goto exit;
result = ec_i2c_parse_response(response, i2c_msgs, &num);
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 2276096..dc0ba29 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -120,7 +120,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
goto done;
}
- ret = 0;
+ ret = i2c_msg[1].buf[1];
done:
kfree(in_buf);
kfree(out_buf);
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 4d34f1c..beba1bc 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -333,7 +333,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
goto exit;
}
- ret = 0;
+ ret = len;
exit:
mutex_unlock(&ec_spi->lock);
return ret;
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 60c0880..7b65a75 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -41,7 +41,7 @@ enum {
* @outdata: Outgoing data to EC
* @outsize: Outgoing length in bytes
* @indata: Where to put the incoming data from EC
- * @insize: Incoming length in bytes (filled in by EC)
+ * @insize: Max number of bytes to accept from EC
* @result: EC's response to the command (separate from communication failure)
*/
struct cros_ec_command {
@@ -64,9 +64,9 @@ struct cros_ec_command {
* sleep at the last suspend
* @event_notifier: interrupt event notifier for transport devices
* @cmd_xfer: send command to EC and get response
- * Returns 0 if the communication succeeded, but that doesn't mean the EC
- * was happy with the command it got. Caller should check msg.result for
- * the EC's result code.
+ * Returns the number of bytes received if the communication succeeded, but
+ * that doesn't mean the EC was happy with the command. The caller
+ * should check msg.result for the EC's result code.
*
* @priv: Private data
* @irq: Interrupt to use
--
2.0.0.526.g5318336
From: Simon Glass <[email protected]>
Some commands take a while to execute. Use -EAGAIN to signal this to the
caller.
Signed-off-by: Simon Glass <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec_spi.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 52d4d7b..c29a2d7 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -292,6 +292,12 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
/* check response error code */
ptr = ec_dev->din;
if (ptr[0]) {
+ if (ptr[0] == EC_RES_IN_PROGRESS) {
+ dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+ ec_msg->cmd);
+ ret = -EAGAIN;
+ goto exit;
+ }
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
ec_msg->cmd, ptr[0]);
debug_packet(ec_dev->dev, "in_err", ptr, len);
--
2.0.0.526.g5318336
From: Bill Richardson <[email protected]>
This is some internal structure reorganization / renaming to prepare
for future patches that will add a userspace API to cros_ec. There
should be no visible changes.
Signed-off-by: Bill Richardson <[email protected]>
Signed-off-by: Doug Anderson <[email protected]>
---
drivers/mfd/cros_ec.c | 28 ++++++++++++++--------------
drivers/mfd/cros_ec_i2c.c | 24 ++++++++++++------------
drivers/mfd/cros_ec_spi.c | 16 ++++++++--------
include/linux/mfd/cros_ec.h | 35 ++++++++++++++++++-----------------
4 files changed, 52 insertions(+), 51 deletions(-)
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index a9eede5..9304056 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -25,22 +25,22 @@
#include <linux/mfd/cros_ec_commands.h>
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+ struct cros_ec_command *msg)
{
uint8_t *out;
int csum, i;
- BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
+ BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
out = ec_dev->dout;
out[0] = EC_CMD_VERSION0 + msg->version;
- out[1] = msg->cmd;
- out[2] = msg->out_len;
+ out[1] = msg->command;
+ out[2] = msg->outsize;
csum = out[0] + out[1] + out[2];
- for (i = 0; i < msg->out_len; i++)
- csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
- out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
+ for (i = 0; i < msg->outsize; i++)
+ csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
+ out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
- return EC_MSG_TX_PROTO_BYTES + msg->out_len;
+ return EC_MSG_TX_PROTO_BYTES + msg->outsize;
}
EXPORT_SYMBOL(cros_ec_prepare_tx);
@@ -48,14 +48,14 @@ static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
uint16_t cmd, void *out_buf, int out_len,
void *in_buf, int in_len)
{
- struct cros_ec_msg msg;
+ struct cros_ec_command msg;
msg.version = cmd >> 8;
- msg.cmd = cmd & 0xff;
- msg.out_buf = out_buf;
- msg.out_len = out_len;
- msg.in_buf = in_buf;
- msg.in_len = in_len;
+ msg.command = cmd & 0xff;
+ msg.outdata = out_buf;
+ msg.outsize = out_len;
+ msg.indata = in_buf;
+ msg.insize = in_len;
return ec_dev->cmd_xfer(ec_dev, &msg);
}
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 777e529..37ed12f 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -30,7 +30,7 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
}
static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+ struct cros_ec_command *msg)
{
struct i2c_client *client = ec_dev->priv;
int ret = -ENOMEM;
@@ -50,7 +50,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one byte for
* length, and one for result code)
*/
- packet_len = msg->in_len + 3;
+ packet_len = msg->insize + 3;
in_buf = kzalloc(packet_len, GFP_KERNEL);
if (!in_buf)
goto done;
@@ -61,7 +61,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one for
* command code, one for length, and one for command version)
*/
- packet_len = msg->out_len + 4;
+ packet_len = msg->outsize + 4;
out_buf = kzalloc(packet_len, GFP_KERNEL);
if (!out_buf)
goto done;
@@ -69,16 +69,16 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
i2c_msg[0].buf = (char *)out_buf;
out_buf[0] = EC_CMD_VERSION0 + msg->version;
- out_buf[1] = msg->cmd;
- out_buf[2] = msg->out_len;
+ out_buf[1] = msg->command;
+ out_buf[2] = msg->outsize;
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2];
- for (i = 0; i < msg->out_len; i++) {
- out_buf[3 + i] = msg->out_buf[i];
+ for (i = 0; i < msg->outsize; i++) {
+ out_buf[3 + i] = msg->outdata[i];
sum += out_buf[3 + i];
}
- out_buf[3 + msg->out_len] = sum;
+ out_buf[3 + msg->outsize] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2);
@@ -94,20 +94,20 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
/* check response error code */
if (i2c_msg[1].buf[0]) {
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- msg->cmd, i2c_msg[1].buf[0]);
+ msg->command, i2c_msg[1].buf[0]);
ret = -EINVAL;
goto done;
}
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1];
- for (i = 0; i < msg->in_len; i++) {
- msg->in_buf[i] = in_buf[2 + i];
+ for (i = 0; i < msg->insize; i++) {
+ msg->indata[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
i2c_msg[1].len, in_buf, sum);
- if (sum != in_buf[2 + msg->in_len]) {
+ if (sum != in_buf[2 + msg->insize]) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG;
goto done;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index c29a2d7..2d713fe 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -216,7 +216,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
* @ec_msg: Message to transfer
*/
static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *ec_msg)
+ struct cros_ec_command *ec_msg)
{
struct cros_ec_spi *ec_spi = ec_dev->priv;
struct spi_transfer trans;
@@ -261,7 +261,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
/* Get the response */
if (!ret) {
ret = cros_ec_spi_receive_response(ec_dev,
- ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
+ ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
} else {
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
}
@@ -294,21 +294,21 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
if (ptr[0]) {
if (ptr[0] == EC_RES_IN_PROGRESS) {
dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
- ec_msg->cmd);
+ ec_msg->command);
ret = -EAGAIN;
goto exit;
}
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- ec_msg->cmd, ptr[0]);
+ ec_msg->command, ptr[0]);
debug_packet(ec_dev->dev, "in_err", ptr, len);
ret = -EINVAL;
goto exit;
}
len = ptr[1];
sum = ptr[0] + ptr[1];
- if (len > ec_msg->in_len) {
+ if (len > ec_msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
- len, ec_msg->in_len);
+ len, ec_msg->insize);
ret = -ENOSPC;
goto exit;
}
@@ -316,8 +316,8 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
/* copy response packet payload and compute checksum */
for (i = 0; i < len; i++) {
sum += ptr[i + 2];
- if (ec_msg->in_len)
- ec_msg->in_buf[i] = ptr[i + 2];
+ if (ec_msg->insize)
+ ec_msg->indata[i] = ptr[i + 2];
}
sum &= 0xff;
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 79a3585..f27c037 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -35,23 +35,23 @@ enum {
EC_MSG_TX_PROTO_BYTES,
};
-/**
- * struct cros_ec_msg - A message sent to the EC, and its reply
- *
+/*
* @version: Command version number (often 0)
- * @cmd: Command to send (EC_CMD_...)
- * @out_buf: Outgoing payload (to EC)
- * @outlen: Outgoing length
- * @in_buf: Incoming payload (from EC)
- * @in_len: Incoming length
+ * @command: Command to send (EC_CMD_...)
+ * @outdata: Outgoing data to EC
+ * @outsize: Outgoing length in bytes
+ * @indata: Where to put the incoming data from EC
+ * @insize: Incoming length in bytes (filled in by EC)
+ * @result: EC's response to the command (separate from communication failure)
*/
-struct cros_ec_msg {
- u8 version;
- u8 cmd;
- uint8_t *out_buf;
- int out_len;
- uint8_t *in_buf;
- int in_len;
+struct cros_ec_command {
+ uint32_t version;
+ uint32_t command;
+ uint8_t *outdata;
+ uint32_t outsize;
+ uint8_t *indata;
+ uint32_t insize;
+ uint32_t result;
};
/**
@@ -114,7 +114,8 @@ struct cros_ec_device {
struct device *parent;
bool wake_enabled;
struct mutex lock;
- int (*cmd_xfer)(struct cros_ec_device *ec, struct cros_ec_msg *msg);
+ int (*cmd_xfer)(struct cros_ec_device *ec,
+ struct cros_ec_command *msg);
};
/**
@@ -148,7 +149,7 @@ int cros_ec_resume(struct cros_ec_device *ec_dev);
* @msg: Message to write
*/
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg);
+ struct cros_ec_command *msg);
/**
* cros_ec_remove - Remove a ChromeOS EC
--
2.0.0.526.g5318336
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> Preparing the way for the LPC device, which is just a plaform_device without
> interrupts.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> The lower-level driver may want to provide its own buffers. If so,
> there's no need to allocate new ones. This already happens to work
> just fine (since we check for size of 0 and use devm allocation), but
> it's good to document it.
>
> [dianders: Resolved conflicts; documented that no code changes needed
> on mainline]
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
Hi Doug,
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> The members of struct cros_ec_device were improperly commented, and
> intermixed the private and public sections. This is just cleanup to make it
> more obvious what goes with what.
>
> [dianders: left lock in the structure but gave it the name that will
> eventually be used.]
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec.c | 2 +-
> drivers/mfd/cros_ec_i2c.c | 4 +--
> drivers/mfd/cros_ec_spi.c | 10 +++----
> include/linux/mfd/cros_ec.h | 65 ++++++++++++++++++++++++---------------------
> 4 files changed, 43 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index bd6f936..a9eede5 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -57,7 +57,7 @@ static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
> msg.in_buf = in_buf;
> msg.in_len = in_len;
>
> - return ec_dev->command_xfer(ec_dev, &msg);
> + return ec_dev->cmd_xfer(ec_dev, &msg);
Why do this rename? It makes it different from the other members.
Regards,
Simon
Hi Doug,
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> struct cros_ec_device has a superfluous "name" field. We can get all the
> debugging info we need from the existing ec_name and phys_name fields, so
> let's take out the extra field.
Except that it no longer prints I2C/SPI - i.e. the transport that is
used. Is that not considered important?
Anyway:
Reviewed-by: Simon Glass <[email protected]>
Regards,
Simon
Hi Doug,
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> Remove the three wrapper functions that talk to the EC without passing all
> the desired arguments and just use the underlying communication function
> that passes everything in a struct intead.
>
> This is internal code refactoring only. Nothing should change.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/i2c/busses/i2c-cros-ec-tunnel.c | 15 +++++++++++----
> drivers/input/keyboard/cros_ec_keyb.c | 14 ++++++++++++--
> drivers/mfd/cros_ec.c | 32 --------------------------------
> include/linux/mfd/cros_ec.h | 19 ++++++-------------
> 4 files changed, 29 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index 8e7a714..dd07818 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
> u8 *request = NULL;
> u8 *response = NULL;
> int result;
> + struct cros_ec_command msg;
>
> request_len = ec_i2c_count_message(i2c_msgs, num);
> if (request_len < 0) {
> @@ -218,9 +219,15 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
> }
>
> ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
> - result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
> - request, request_len,
> - response, response_len);
> +
> + msg.version = 0;
> + msg.command = EC_CMD_I2C_PASSTHRU;
> + msg.outdata = request;
> + msg.outsize = request_len;
> + msg.indata = response;
> + msg.insize = response_len;
> +
> + result = bus->ec->cmd_xfer(bus->ec, &msg);
> if (result)
> goto exit;
>
> @@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_device *pdev)
> u32 remote_bus;
> int err;
>
> - if (!ec->command_sendrecv) {
> + if (!ec->cmd_xfer) {
> dev_err(dev, "Missing sendrecv\n");
> return -EINVAL;
> }
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
> index 4083796..dc37b6b 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -191,8 +191,18 @@ static void cros_ec_keyb_close(struct input_dev *dev)
>
> static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
> {
> - return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
> - kb_state, ckdev->cols);
> + int ret;
> + struct cros_ec_command msg = {
> + .version = 0,
> + .command = EC_CMD_MKBP_STATE,
> + .outdata = NULL,
> + .outsize = 0,
> + .indata = kb_state,
> + .insize = ckdev->cols,
> + };
> +
> + ret = ckdev->ec->cmd_xfer(ckdev->ec, &msg);
Do we need ret?
> + return ret;
> }
>
> static int cros_ec_keyb_work(struct notifier_block *nb,
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index d242714..6dd91e9 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -44,34 +44,6 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
> }
> EXPORT_SYMBOL(cros_ec_prepare_tx);
>
> -static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
> - uint16_t cmd, void *out_buf, int out_len,
> - void *in_buf, int in_len)
> -{
> - struct cros_ec_command msg;
> -
> - msg.version = cmd >> 8;
> - msg.command = cmd & 0xff;
> - msg.outdata = out_buf;
> - msg.outsize = out_len;
> - msg.indata = in_buf;
> - msg.insize = in_len;
> -
> - return ec_dev->cmd_xfer(ec_dev, &msg);
> -}
> -
> -static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
> - uint16_t cmd, void *buf, int buf_len)
> -{
> - return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
> -}
> -
> -static int cros_ec_command_send(struct cros_ec_device *ec_dev,
> - uint16_t cmd, void *buf, int buf_len)
> -{
> - return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
> -}
> -
> static irqreturn_t ec_irq_thread(int irq, void *data)
> {
> struct cros_ec_device *ec_dev = data;
> @@ -104,10 +76,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
>
> BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
>
> - ec_dev->command_send = cros_ec_command_send;
> - ec_dev->command_recv = cros_ec_command_recv;
> - ec_dev->command_sendrecv = cros_ec_command_sendrecv;
> -
> if (ec_dev->din_size) {
> ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
> if (!ec_dev->din)
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 2b0c598..60c0880 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -63,9 +63,10 @@ struct cros_ec_command {
> * @was_wake_device: true if this device was set to wake the system from
> * sleep at the last suspend
> * @event_notifier: interrupt event notifier for transport devices
> - * @command_send: send a command
> - * @command_recv: receive a response
> - * @command_sendrecv: send a command and receive a response
> + * @cmd_xfer: send command to EC and get response
> + * Returns 0 if the communication succeeded, but that doesn't mean the EC
> + * was happy with the command it got. Caller should check msg.result for
> + * the EC's result code.
> *
> * @priv: Private data
> * @irq: Interrupt to use
> @@ -83,7 +84,6 @@ struct cros_ec_command {
> * @parent: pointer to parent device (e.g. i2c or spi device)
> * @wake_enabled: true if this device can wake the system from sleep
> * @lock: one transaction at a time
> - * @cmd_xfer: low-level channel to the EC
> */
> struct cros_ec_device {
>
> @@ -94,13 +94,8 @@ struct cros_ec_device {
> bool was_wake_device;
> struct class *cros_class;
> struct blocking_notifier_head event_notifier;
> - int (*command_send)(struct cros_ec_device *ec,
> - uint16_t cmd, void *out_buf, int out_len);
> - int (*command_recv)(struct cros_ec_device *ec,
> - uint16_t cmd, void *in_buf, int in_len);
> - int (*command_sendrecv)(struct cros_ec_device *ec,
> - uint16_t cmd, void *out_buf, int out_len,
> - void *in_buf, int in_len);
> + int (*cmd_xfer)(struct cros_ec_device *ec,
> + struct cros_ec_command *msg);
>
> /* These are used to implement the platform-specific interface */
> void *priv;
> @@ -112,8 +107,6 @@ struct cros_ec_device {
> struct device *parent;
> bool wake_enabled;
> struct mutex lock;
> - int (*cmd_xfer)(struct cros_ec_device *ec,
> - struct cros_ec_command *msg);
Seems odd - maybe this line move of cmd_xfer() should be in an earlier patch?
Regards,
Simon
Hi Doug,
On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> Just because the host was able to talk to the EC doesn't mean that the EC
> was happy with what it was told. Errors in communincation are not the same
> as error messages from the EC itself.
>
> This change lets the EC report its errors separately.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec_i2c.c | 15 +++++++++++----
> drivers/mfd/cros_ec_spi.c | 26 ++++++++++++++------------
> 2 files changed, 25 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
> index 5bb32f5..2276096 100644
> --- a/drivers/mfd/cros_ec_i2c.c
> +++ b/drivers/mfd/cros_ec_i2c.c
> @@ -92,11 +92,18 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
> }
>
> /* check response error code */
> - if (i2c_msg[1].buf[0]) {
> - dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
> - msg->command, i2c_msg[1].buf[0]);
> - ret = -EINVAL;
> + msg->result = i2c_msg[1].buf[0];
> + switch (msg->result) {
> + case EC_RES_SUCCESS:
> + break;
> + case EC_RES_IN_PROGRESS:
> + ret = -EAGAIN;
> + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> + msg->command);
> goto done;
> + default:
> + dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
> + msg->command, msg->result);
> }
>
> /* copy response packet payload and compute checksum */
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 09ca789..4d34f1c 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -289,21 +289,23 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> goto exit;
> }
>
> - /* check response error code */
> ptr = ec_dev->din;
> - if (ptr[0]) {
> - if (ptr[0] == EC_RES_IN_PROGRESS) {
> - dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> - ec_msg->command);
> - ret = -EAGAIN;
> - goto exit;
> - }
> - dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
> - ec_msg->command, ptr[0]);
> - debug_packet(ec_dev->dev, "in_err", ptr, len);
> - ret = -EINVAL;
> +
> + /* check response error code */
> + ec_msg->result = ptr[0];
> + switch (ec_msg->result) {
> + case EC_RES_SUCCESS:
> + break;
> + case EC_RES_IN_PROGRESS:
> + ret = -EAGAIN;
> + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> + ec_msg->command);
> goto exit;
> + default:
> + dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
> + ec_msg->command, ec_msg->result);
> }
Since this code is the same as the above, should it go in a common
function in cros_ec?
> +
> len = ptr[1];
> sum = ptr[0] + ptr[1];
> if (len > ec_msg->insize) {
> --
> 2.0.0.526.g5318336
>
Regards,
Simon
Hi,
On 16 June 2014 14:40, Doug Anderson <[email protected]> wrote:
> From: Bill Richardson <[email protected]>
>
> When communicating with the EC, the cmd_xfer() function should return the
> number of bytes it received from the EC, or negative on error.
This is just for the I2C tunnel feature, right? If so, I think this
should be mentioned here. It seems to be affecting ec_i2c_xfer(), not
cmd_xfer().
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/i2c/busses/i2c-cros-ec-tunnel.c | 2 +-
> drivers/mfd/cros_ec_i2c.c | 2 +-
> drivers/mfd/cros_ec_spi.c | 2 +-
> include/linux/mfd/cros_ec.h | 8 ++++----
> 4 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index dd07818..05e033c 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -228,7 +228,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
> msg.insize = response_len;
>
> result = bus->ec->cmd_xfer(bus->ec, &msg);
> - if (result)
> + if (result < 0)
> goto exit;
>
> result = ec_i2c_parse_response(response, i2c_msgs, &num);
> diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
> index 2276096..dc0ba29 100644
> --- a/drivers/mfd/cros_ec_i2c.c
> +++ b/drivers/mfd/cros_ec_i2c.c
> @@ -120,7 +120,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
> goto done;
> }
>
> - ret = 0;
> + ret = i2c_msg[1].buf[1];
> done:
> kfree(in_buf);
> kfree(out_buf);
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 4d34f1c..beba1bc 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -333,7 +333,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> goto exit;
> }
>
> - ret = 0;
> + ret = len;
> exit:
> mutex_unlock(&ec_spi->lock);
> return ret;
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 60c0880..7b65a75 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -41,7 +41,7 @@ enum {
> * @outdata: Outgoing data to EC
> * @outsize: Outgoing length in bytes
> * @indata: Where to put the incoming data from EC
> - * @insize: Incoming length in bytes (filled in by EC)
> + * @insize: Max number of bytes to accept from EC
> * @result: EC's response to the command (separate from communication failure)
> */
> struct cros_ec_command {
> @@ -64,9 +64,9 @@ struct cros_ec_command {
> * sleep at the last suspend
> * @event_notifier: interrupt event notifier for transport devices
> * @cmd_xfer: send command to EC and get response
> - * Returns 0 if the communication succeeded, but that doesn't mean the EC
> - * was happy with the command it got. Caller should check msg.result for
> - * the EC's result code.
> + * Returns the number of bytes received if the communication succeeded, but
> + * that doesn't mean the EC was happy with the command. The caller
> + * should check msg.result for the EC's result code.
> *
> * @priv: Private data
> * @irq: Interrupt to use
> --
> 2.0.0.526.g5318336
>
Regards,
Simon
Simon,
On Tue, Jun 17, 2014 at 8:35 PM, Simon Glass <[email protected]> wrote:
> Hi Doug,
>
> On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
>> From: Bill Richardson <[email protected]>
>>
>> The members of struct cros_ec_device were improperly commented, and
>> intermixed the private and public sections. This is just cleanup to make it
>> more obvious what goes with what.
>>
>> [dianders: left lock in the structure but gave it the name that will
>> eventually be used.]
>>
>> Signed-off-by: Bill Richardson <[email protected]>
>> Signed-off-by: Doug Anderson <[email protected]>
>> ---
>> drivers/mfd/cros_ec.c | 2 +-
>> drivers/mfd/cros_ec_i2c.c | 4 +--
>> drivers/mfd/cros_ec_spi.c | 10 +++----
>> include/linux/mfd/cros_ec.h | 65 ++++++++++++++++++++++++---------------------
>> 4 files changed, 43 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
>> index bd6f936..a9eede5 100644
>> --- a/drivers/mfd/cros_ec.c
>> +++ b/drivers/mfd/cros_ec.c
>> @@ -57,7 +57,7 @@ static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
>> msg.in_buf = in_buf;
>> msg.in_len = in_len;
>>
>> - return ec_dev->command_xfer(ec_dev, &msg);
>> + return ec_dev->cmd_xfer(ec_dev, &msg);
>
> Why do this rename? It makes it different from the other members.
All I know of the history of this change is at
<http://crosreview.com/57061>. My best guess is that Bill was trying
to differentiate public vs. private function pointers. Perhaps he
will chime in.
If it helps the other command_xxx() function pointers are removed in
the later "mfd: cros_ec: cleanup: Remove EC wrapper functions"
If you wish I can skip this rename, just let me know and it won't be
too much trouble.
-Doug
Simon,
On Tue, Jun 17, 2014 at 8:39 PM, Simon Glass <[email protected]> wrote:
> Hi Doug,
>
> On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
>> From: Bill Richardson <[email protected]>
>>
>> struct cros_ec_device has a superfluous "name" field. We can get all the
>> debugging info we need from the existing ec_name and phys_name fields, so
>> let's take out the extra field.
>
> Except that it no longer prints I2C/SPI - i.e. the transport that is
> used. Is that not considered important?
Before this change:
[ 1.895472] cros-ec-spi spi2.0: Chrome EC (SPI)
After this change:
[ 1.910671] cros-ec-spi spi2.0: Chrome EC device registered
I think having SPI in the name twice is probably enough. ;)
-Doug
Hi Doug,
On 17 June 2014 21:22, Doug Anderson <[email protected]> wrote:
>
> Simon,
>
> On Tue, Jun 17, 2014 at 8:39 PM, Simon Glass <[email protected]> wrote:
> > Hi Doug,
> >
> > On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
> >> From: Bill Richardson <[email protected]>
> >>
> >> struct cros_ec_device has a superfluous "name" field. We can get all the
> >> debugging info we need from the existing ec_name and phys_name fields, so
> >> let's take out the extra field.
> >
> > Except that it no longer prints I2C/SPI - i.e. the transport that is
> > used. Is that not considered important?
>
> Before this change:
> [ 1.895472] cros-ec-spi spi2.0: Chrome EC (SPI)
>
> After this change:
> [ 1.910671] cros-ec-spi spi2.0: Chrome EC device registered
>
>
> I think having SPI in the name twice is probably enough. ;)
Ah that helps! Could have been in the commit message.
Reviewed-by: Simon Glass <[email protected]>
Regards,
Simon
Simon,
On Tue, Jun 17, 2014 at 8:42 PM, Simon Glass <[email protected]> wrote:
>> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
>> index 4083796..dc37b6b 100644
>> --- a/drivers/input/keyboard/cros_ec_keyb.c
>> +++ b/drivers/input/keyboard/cros_ec_keyb.c
>> @@ -191,8 +191,18 @@ static void cros_ec_keyb_close(struct input_dev *dev)
>>
>> static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
>> {
>> - return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
>> - kb_state, ckdev->cols);
>> + int ret;
>> + struct cros_ec_command msg = {
>> + .version = 0,
>> + .command = EC_CMD_MKBP_STATE,
>> + .outdata = NULL,
>> + .outsize = 0,
>> + .indata = kb_state,
>> + .insize = ckdev->cols,
>> + };
>> +
>> + ret = ckdev->ec->cmd_xfer(ckdev->ec, &msg);
>
> Do we need ret?
No. If you wish I will spin without it. Let me know.
Note that locally this code includes a comment between the above and the return:
/* FIXME: This assumes msg.result == EC_RES_SUCCESS */
Given that this is not a new problem introduced in this code, that it
still hasn't been fixed locally in the ChromeOS tree, and that
generally FIXMEs don't seem to be left in the code upstream, I left it
out.
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index 2b0c598..60c0880 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -63,9 +63,10 @@ struct cros_ec_command {
>> * @was_wake_device: true if this device was set to wake the system from
>> * sleep at the last suspend
>> * @event_notifier: interrupt event notifier for transport devices
>> - * @command_send: send a command
>> - * @command_recv: receive a response
>> - * @command_sendrecv: send a command and receive a response
>> + * @cmd_xfer: send command to EC and get response
>> + * Returns 0 if the communication succeeded, but that doesn't mean the EC
>> + * was happy with the command it got. Caller should check msg.result for
>> + * the EC's result code.
>> *
>> * @priv: Private data
>> * @irq: Interrupt to use
>> @@ -83,7 +84,6 @@ struct cros_ec_command {
>> * @parent: pointer to parent device (e.g. i2c or spi device)
>> * @wake_enabled: true if this device can wake the system from sleep
>> * @lock: one transaction at a time
>> - * @cmd_xfer: low-level channel to the EC
>> */
>> struct cros_ec_device {
>>
>> @@ -94,13 +94,8 @@ struct cros_ec_device {
>> bool was_wake_device;
>> struct class *cros_class;
>> struct blocking_notifier_head event_notifier;
>> - int (*command_send)(struct cros_ec_device *ec,
>> - uint16_t cmd, void *out_buf, int out_len);
>> - int (*command_recv)(struct cros_ec_device *ec,
>> - uint16_t cmd, void *in_buf, int in_len);
>> - int (*command_sendrecv)(struct cros_ec_device *ec,
>> - uint16_t cmd, void *out_buf, int out_len,
>> - void *in_buf, int in_len);
>> + int (*cmd_xfer)(struct cros_ec_device *ec,
>> + struct cros_ec_command *msg);
>>
>> /* These are used to implement the platform-specific interface */
>> void *priv;
>> @@ -112,8 +107,6 @@ struct cros_ec_device {
>> struct device *parent;
>> bool wake_enabled;
>> struct mutex lock;
>> - int (*cmd_xfer)(struct cros_ec_device *ec,
>> - struct cros_ec_command *msg);
>
> Seems odd - maybe this line move of cmd_xfer() should be in an earlier patch?
It got moved from "private" to public. Bill reorganized all the
public stuff at the top and the private at the bottom.
-Doug
Simon,
On Tue, Jun 17, 2014 at 9:25 PM, Simon Glass <[email protected]> wrote:
> Hi Doug,
>
> On 17 June 2014 21:22, Doug Anderson <[email protected]> wrote:
>>
>> Simon,
>>
>> On Tue, Jun 17, 2014 at 8:39 PM, Simon Glass <[email protected]> wrote:
>> > Hi Doug,
>> >
>> > On 16 June 2014 14:39, Doug Anderson <[email protected]> wrote:
>> >> From: Bill Richardson <[email protected]>
>> >>
>> >> struct cros_ec_device has a superfluous "name" field. We can get all the
>> >> debugging info we need from the existing ec_name and phys_name fields, so
>> >> let's take out the extra field.
>> >
>> > Except that it no longer prints I2C/SPI - i.e. the transport that is
>> > used. Is that not considered important?
>>
>> Before this change:
>> [ 1.895472] cros-ec-spi spi2.0: Chrome EC (SPI)
>>
>> After this change:
>> [ 1.910671] cros-ec-spi spi2.0: Chrome EC device registered
>>
>>
>> I think having SPI in the name twice is probably enough. ;)
>
> Ah that helps! Could have been in the commit message.
>
> Reviewed-by: Simon Glass <[email protected]>
If I re-spin the series I'll add it. I think the new message was in
the original commit in the "TEST=" clause and I left it out. I
probably should have added it in with the proper wording...
-Doug
Simon,
On Tue, Jun 17, 2014 at 8:43 PM, Simon Glass <[email protected]> wrote:
>> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
>> index 09ca789..4d34f1c 100644
>> --- a/drivers/mfd/cros_ec_spi.c
>> +++ b/drivers/mfd/cros_ec_spi.c
>> @@ -289,21 +289,23 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
>> goto exit;
>> }
>>
>> - /* check response error code */
>> ptr = ec_dev->din;
>> - if (ptr[0]) {
>> - if (ptr[0] == EC_RES_IN_PROGRESS) {
>> - dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
>> - ec_msg->command);
>> - ret = -EAGAIN;
>> - goto exit;
>> - }
>> - dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
>> - ec_msg->command, ptr[0]);
>> - debug_packet(ec_dev->dev, "in_err", ptr, len);
>> - ret = -EINVAL;
>> +
>> + /* check response error code */
>> + ec_msg->result = ptr[0];
>> + switch (ec_msg->result) {
>> + case EC_RES_SUCCESS:
>> + break;
>> + case EC_RES_IN_PROGRESS:
>> + ret = -EAGAIN;
>> + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
>> + ec_msg->command);
>> goto exit;
>> + default:
>> + dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
>> + ec_msg->command, ec_msg->result);
>> }
>
> Since this code is the same as the above, should it go in a common
> function in cros_ec?
So you are thinking it should be written like:
ec_msg->result = ptr[0];
ret = cros_ec_check_result(ec_dev, ec_msg);
if (ret)
goto exit;
---
int cros_ec_check_result(struct cros_ec_device *ec_dev, struct
cros_ec_command *ec_msg)
{
switch (ec_msg->result) {
case EC_RES_SUCCESS:
return 0;
case EC_RES_IN_PROGRESS:
dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
ec_msg->command);
return -EAGAIN;
default:
dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
ec_msg->command, ec_msg->result);
return 0;
}
OK, that seems reasonable. I'll plan to spin tomorrow with that.
-Doug
Simon,
On Tue, Jun 17, 2014 at 8:46 PM, Simon Glass <[email protected]> wrote:
> Hi,
>
> On 16 June 2014 14:40, Doug Anderson <[email protected]> wrote:
>> From: Bill Richardson <[email protected]>
>>
>> When communicating with the EC, the cmd_xfer() function should return the
>> number of bytes it received from the EC, or negative on error.
>
> This is just for the I2C tunnel feature, right? If so, I think this
> should be mentioned here. It seems to be affecting ec_i2c_xfer(), not
> cmd_xfer().
No, the tunnel feature is implemented just fine without this (and is
already landed and working). It looks like the (not yet upstreamed)
ec_i2c_limited_xfer for spring returns this new value directly but I'm
not convinced that's technicall correct.
Bill can correct me if I'm wrong, but I think this is primarily
interesting once we add in cros_ec_dev (the userspace API) which needs
this info. Until that happens this patch doesn't hurt and just
returns some extra info.
-Doug
Hi Doug,
On 17 June 2014 21:27, Doug Anderson <[email protected]> wrote:
> Simon,
>
> On Tue, Jun 17, 2014 at 8:42 PM, Simon Glass <[email protected]> wrote:
>>> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
>>> index 4083796..dc37b6b 100644
>>> --- a/drivers/input/keyboard/cros_ec_keyb.c
>>> +++ b/drivers/input/keyboard/cros_ec_keyb.c
>>> @@ -191,8 +191,18 @@ static void cros_ec_keyb_close(struct input_dev *dev)
>>>
>>> static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
>>> {
>>> - return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
>>> - kb_state, ckdev->cols);
>>> + int ret;
>>> + struct cros_ec_command msg = {
>>> + .version = 0,
>>> + .command = EC_CMD_MKBP_STATE,
>>> + .outdata = NULL,
>>> + .outsize = 0,
>>> + .indata = kb_state,
>>> + .insize = ckdev->cols,
>>> + };
>>> +
>>> + ret = ckdev->ec->cmd_xfer(ckdev->ec, &msg);
>>
>> Do we need ret?
>
> No. If you wish I will spin without it. Let me know.
>
> Note that locally this code includes a comment between the above and the return:
> /* FIXME: This assumes msg.result == EC_RES_SUCCESS */
It's not important to me, and you've explained the other question.
Reviewed-by: Simon Glass <[email protected]>
Hi Doug,
On 17 June 2014 21:54, Doug Anderson <[email protected]> wrote:
> Simon,
>
> On Tue, Jun 17, 2014 at 8:46 PM, Simon Glass <[email protected]> wrote:
>> Hi,
>>
>> On 16 June 2014 14:40, Doug Anderson <[email protected]> wrote:
>>> From: Bill Richardson <[email protected]>
>>>
>>> When communicating with the EC, the cmd_xfer() function should return the
>>> number of bytes it received from the EC, or negative on error.
>>
>> This is just for the I2C tunnel feature, right? If so, I think this
>> should be mentioned here. It seems to be affecting ec_i2c_xfer(), not
>> cmd_xfer().
>
> No, the tunnel feature is implemented just fine without this (and is
> already landed and working). It looks like the (not yet upstreamed)
> ec_i2c_limited_xfer for spring returns this new value directly but I'm
> not convinced that's technicall correct.
>
> Bill can correct me if I'm wrong, but I think this is primarily
> interesting once we add in cros_ec_dev (the userspace API) which needs
> this info. Until that happens this patch doesn't hurt and just
> returns some extra info.
Agreed.
Reviewed-by: Simon Glass <[email protected]>
Regards,
Simon
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> When communicating with the EC, the cmd_xfer() function should return the
> number of bytes it received from the EC, or negative on error.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/i2c/busses/i2c-cros-ec-tunnel.c | 2 +-
> drivers/mfd/cros_ec_i2c.c | 2 +-
> drivers/mfd/cros_ec_spi.c | 2 +-
> include/linux/mfd/cros_ec.h | 8 ++++----
> 4 files changed, 7 insertions(+), 7 deletions(-)
For the re-spin:
Acked-by: Lee Jones <[email protected]>
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index dd07818..05e033c 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -228,7 +228,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
> msg.insize = response_len;
>
> result = bus->ec->cmd_xfer(bus->ec, &msg);
> - if (result)
> + if (result < 0)
> goto exit;
>
> result = ec_i2c_parse_response(response, i2c_msgs, &num);
> diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
> index 2276096..dc0ba29 100644
> --- a/drivers/mfd/cros_ec_i2c.c
> +++ b/drivers/mfd/cros_ec_i2c.c
> @@ -120,7 +120,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
> goto done;
> }
>
> - ret = 0;
> + ret = i2c_msg[1].buf[1];
> done:
> kfree(in_buf);
> kfree(out_buf);
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 4d34f1c..beba1bc 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -333,7 +333,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> goto exit;
> }
>
> - ret = 0;
> + ret = len;
> exit:
> mutex_unlock(&ec_spi->lock);
> return ret;
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 60c0880..7b65a75 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -41,7 +41,7 @@ enum {
> * @outdata: Outgoing data to EC
> * @outsize: Outgoing length in bytes
> * @indata: Where to put the incoming data from EC
> - * @insize: Incoming length in bytes (filled in by EC)
> + * @insize: Max number of bytes to accept from EC
> * @result: EC's response to the command (separate from communication failure)
> */
> struct cros_ec_command {
> @@ -64,9 +64,9 @@ struct cros_ec_command {
> * sleep at the last suspend
> * @event_notifier: interrupt event notifier for transport devices
> * @cmd_xfer: send command to EC and get response
> - * Returns 0 if the communication succeeded, but that doesn't mean the EC
> - * was happy with the command it got. Caller should check msg.result for
> - * the EC's result code.
> + * Returns the number of bytes received if the communication succeeded, but
> + * that doesn't mean the EC was happy with the command. The caller
> + * should check msg.result for the EC's result code.
> *
> * @priv: Private data
> * @irq: Interrupt to use
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Tue, 17 Jun 2014, Doug Anderson wrote:
> Simon,
>
> On Tue, Jun 17, 2014 at 8:43 PM, Simon Glass <[email protected]> wrote:
> >> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> >> index 09ca789..4d34f1c 100644
> >> --- a/drivers/mfd/cros_ec_spi.c
> >> +++ b/drivers/mfd/cros_ec_spi.c
> >> @@ -289,21 +289,23 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> >> goto exit;
> >> }
> >>
> >> - /* check response error code */
> >> ptr = ec_dev->din;
> >> - if (ptr[0]) {
> >> - if (ptr[0] == EC_RES_IN_PROGRESS) {
> >> - dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> >> - ec_msg->command);
> >> - ret = -EAGAIN;
> >> - goto exit;
> >> - }
> >> - dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
> >> - ec_msg->command, ptr[0]);
> >> - debug_packet(ec_dev->dev, "in_err", ptr, len);
> >> - ret = -EINVAL;
> >> +
> >> + /* check response error code */
> >> + ec_msg->result = ptr[0];
> >> + switch (ec_msg->result) {
> >> + case EC_RES_SUCCESS:
> >> + break;
> >> + case EC_RES_IN_PROGRESS:
> >> + ret = -EAGAIN;
> >> + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> >> + ec_msg->command);
> >> goto exit;
> >> + default:
> >> + dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
> >> + ec_msg->command, ec_msg->result);
> >> }
> >
> > Since this code is the same as the above, should it go in a common
> > function in cros_ec?
>
> So you are thinking it should be written like:
>
> ec_msg->result = ptr[0];
> ret = cros_ec_check_result(ec_dev, ec_msg);
> if (ret)
> goto exit;
>
> ---
>
> int cros_ec_check_result(struct cros_ec_device *ec_dev, struct
> cros_ec_command *ec_msg)
> {
> switch (ec_msg->result) {
> case EC_RES_SUCCESS:
> return 0;
> case EC_RES_IN_PROGRESS:
> dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> ec_msg->command);
> return -EAGAIN;
> default:
> dev_warn(ec_dev->dev, "command 0x%02x returned %d\n",
> ec_msg->command, ec_msg->result);
> return 0;
> }
>
> OK, that seems reasonable. I'll plan to spin tomorrow with that.
+1
I'll do a proper review when you re-spin the patch.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
> >> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
> >> index 4083796..dc37b6b 100644
> >> --- a/drivers/input/keyboard/cros_ec_keyb.c
> >> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> >> @@ -191,8 +191,18 @@ static void cros_ec_keyb_close(struct input_dev *dev)
> >>
> >> static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
> >> {
> >> - return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
> >> - kb_state, ckdev->cols);
> >> + int ret;
> >> + struct cros_ec_command msg = {
> >> + .version = 0,
> >> + .command = EC_CMD_MKBP_STATE,
> >> + .outdata = NULL,
> >> + .outsize = 0,
> >> + .indata = kb_state,
> >> + .insize = ckdev->cols,
> >> + };
> >> +
> >> + ret = ckdev->ec->cmd_xfer(ckdev->ec, &msg);
> >
> > Do we need ret?
>
> No. If you wish I will spin without it. Let me know.
>
> Note that locally this code includes a comment between the above and the return:
> /* FIXME: This assumes msg.result == EC_RES_SUCCESS */
>
> Given that this is not a new problem introduced in this code, that it
> still hasn't been fixed locally in the ChromeOS tree, and that
> generally FIXMEs don't seem to be left in the code upstream, I left it
> out.
As you're re-spinning anyway, please fix this and add my:
Acked-by: Lee Jones <[email protected]>
> >> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> >> index 2b0c598..60c0880 100644
> >> --- a/include/linux/mfd/cros_ec.h
> >> +++ b/include/linux/mfd/cros_ec.h
> >> @@ -63,9 +63,10 @@ struct cros_ec_command {
> >> * @was_wake_device: true if this device was set to wake the system from
> >> * sleep at the last suspend
> >> * @event_notifier: interrupt event notifier for transport devices
> >> - * @command_send: send a command
> >> - * @command_recv: receive a response
> >> - * @command_sendrecv: send a command and receive a response
> >> + * @cmd_xfer: send command to EC and get response
> >> + * Returns 0 if the communication succeeded, but that doesn't mean the EC
> >> + * was happy with the command it got. Caller should check msg.result for
> >> + * the EC's result code.
> >> *
> >> * @priv: Private data
> >> * @irq: Interrupt to use
> >> @@ -83,7 +84,6 @@ struct cros_ec_command {
> >> * @parent: pointer to parent device (e.g. i2c or spi device)
> >> * @wake_enabled: true if this device can wake the system from sleep
> >> * @lock: one transaction at a time
> >> - * @cmd_xfer: low-level channel to the EC
> >> */
> >> struct cros_ec_device {
> >>
> >> @@ -94,13 +94,8 @@ struct cros_ec_device {
> >> bool was_wake_device;
> >> struct class *cros_class;
> >> struct blocking_notifier_head event_notifier;
> >> - int (*command_send)(struct cros_ec_device *ec,
> >> - uint16_t cmd, void *out_buf, int out_len);
> >> - int (*command_recv)(struct cros_ec_device *ec,
> >> - uint16_t cmd, void *in_buf, int in_len);
> >> - int (*command_sendrecv)(struct cros_ec_device *ec,
> >> - uint16_t cmd, void *out_buf, int out_len,
> >> - void *in_buf, int in_len);
> >> + int (*cmd_xfer)(struct cros_ec_device *ec,
> >> + struct cros_ec_command *msg);
> >>
> >> /* These are used to implement the platform-specific interface */
> >> void *priv;
> >> @@ -112,8 +107,6 @@ struct cros_ec_device {
> >> struct device *parent;
> >> bool wake_enabled;
> >> struct mutex lock;
> >> - int (*cmd_xfer)(struct cros_ec_device *ec,
> >> - struct cros_ec_command *msg);
> >
> > Seems odd - maybe this line move of cmd_xfer() should be in an earlier patch?
>
> It got moved from "private" to public. Bill reorganized all the
> public stuff at the top and the private at the bottom.
>
> -Doug
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> struct cros_ec_device has a superfluous "name" field. We can get all the
> debugging info we need from the existing ec_name and phys_name fields, so
> let's take out the extra field.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec.c | 2 +-
> drivers/mfd/cros_ec_i2c.c | 1 -
> drivers/mfd/cros_ec_spi.c | 1 -
> include/linux/mfd/cros_ec.h | 2 --
> 4 files changed, 1 insertion(+), 5 deletions(-)
For the re-spin:
Acked-by: Lee Jones <[email protected]>
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index 9304056..d242714 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -138,7 +138,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
> goto fail_mfd;
> }
>
> - dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
> + dev_info(dev, "Chrome EC device registered\n");
>
> return 0;
>
> diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
> index 37ed12f..5bb32f5 100644
> --- a/drivers/mfd/cros_ec_i2c.c
> +++ b/drivers/mfd/cros_ec_i2c.c
> @@ -132,7 +132,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
> return -ENOMEM;
>
> i2c_set_clientdata(client, ec_dev);
> - ec_dev->name = "I2C";
> ec_dev->dev = dev;
> ec_dev->priv = client;
> ec_dev->irq = client->irq;
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 2d713fe..09ca789 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -374,7 +374,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
> cros_ec_spi_dt_probe(ec_spi, dev);
>
> spi_set_drvdata(spi, ec_dev);
> - ec_dev->name = "SPI";
> ec_dev->dev = dev;
> ec_dev->priv = ec_spi;
> ec_dev->irq = spi->irq;
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index f27c037..2b0c598 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -67,7 +67,6 @@ struct cros_ec_command {
> * @command_recv: receive a response
> * @command_sendrecv: send a command and receive a response
> *
> - * @name: Name of this EC interface
> * @priv: Private data
> * @irq: Interrupt to use
> * @din: input buffer (for data from EC)
> @@ -104,7 +103,6 @@ struct cros_ec_device {
> void *in_buf, int in_len);
>
> /* These are used to implement the platform-specific interface */
> - const char *name;
> void *priv;
> int irq;
> uint8_t *din;
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> This is some internal structure reorganization / renaming to prepare
> for future patches that will add a userspace API to cros_ec. There
> should be no visible changes.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec.c | 28 ++++++++++++++--------------
> drivers/mfd/cros_ec_i2c.c | 24 ++++++++++++------------
> drivers/mfd/cros_ec_spi.c | 16 ++++++++--------
> include/linux/mfd/cros_ec.h | 35 ++++++++++++++++++-----------------
> 4 files changed, 52 insertions(+), 51 deletions(-)
> */
> -struct cros_ec_msg {
> - u8 version;
> - u8 cmd;
> - uint8_t *out_buf;
> - int out_len;
> - uint8_t *in_buf;
> - int in_len;
> +struct cros_ec_command {
> + uint32_t version;
> + uint32_t command;
> + uint8_t *outdata;
> + uint32_t outsize;
> + uint8_t *indata;
> + uint32_t insize;
> + uint32_t result;
If you're sure these type changed do not cause you any bother:
Acked-by: Lee Jones <[email protected]>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Simon Glass <[email protected]>
>
> Some commands take a while to execute. Use -EAGAIN to signal this to the
> caller.
>
> Signed-off-by: Simon Glass <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec_spi.c | 6 ++++++
> 1 file changed, 6 insertions(+)
For the re-spin:
Acked-by: Lee Jones <[email protected]>
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 52d4d7b..c29a2d7 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -292,6 +292,12 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> /* check response error code */
> ptr = ec_dev->din;
> if (ptr[0]) {
> + if (ptr[0] == EC_RES_IN_PROGRESS) {
> + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
> + ec_msg->cmd);
> + ret = -EAGAIN;
> + goto exit;
> + }
> dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
> ec_msg->cmd, ptr[0]);
> debug_packet(ec_dev->dev, "in_err", ptr, len);
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> The members of struct cros_ec_device were improperly commented, and
> intermixed the private and public sections. This is just cleanup to make it
> more obvious what goes with what.
>
> [dianders: left lock in the structure but gave it the name that will
> eventually be used.]
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec.c | 2 +-
> drivers/mfd/cros_ec_i2c.c | 4 +--
> drivers/mfd/cros_ec_spi.c | 10 +++----
> include/linux/mfd/cros_ec.h | 65 ++++++++++++++++++++++++---------------------
> 4 files changed, 43 insertions(+), 38 deletions(-)
For the re-spin:
Acked-by: Lee Jones <[email protected]>
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index bd6f936..a9eede5 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -57,7 +57,7 @@ static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
> msg.in_buf = in_buf;
> msg.in_len = in_len;
>
> - return ec_dev->command_xfer(ec_dev, &msg);
> + return ec_dev->cmd_xfer(ec_dev, &msg);
> }
>
> static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
> diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
> index 4f71be9..777e529 100644
> --- a/drivers/mfd/cros_ec_i2c.c
> +++ b/drivers/mfd/cros_ec_i2c.c
> @@ -29,7 +29,7 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
> return i2c_get_clientdata(client);
> }
>
> -static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
> +static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
> struct cros_ec_msg *msg)
> {
> struct i2c_client *client = ec_dev->priv;
> @@ -136,7 +136,7 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
> ec_dev->dev = dev;
> ec_dev->priv = client;
> ec_dev->irq = client->irq;
> - ec_dev->command_xfer = cros_ec_command_xfer;
> + ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
> ec_dev->ec_name = client->name;
> ec_dev->phys_name = client->adapter->name;
> ec_dev->parent = &client->dev;
> diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
> index 0b8d328..52d4d7b 100644
> --- a/drivers/mfd/cros_ec_spi.c
> +++ b/drivers/mfd/cros_ec_spi.c
> @@ -73,7 +73,7 @@
> * if no record
> * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
> * is sent when we want to turn off CS at the end of a transaction.
> - * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
> + * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
> */
> struct cros_ec_spi {
> struct spi_device *spi;
> @@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
> }
>
> /**
> - * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
> + * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
> *
> * @ec_dev: ChromeOS EC device
> * @ec_msg: Message to transfer
> */
> -static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
> - struct cros_ec_msg *ec_msg)
> +static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
> + struct cros_ec_msg *ec_msg)
> {
> struct cros_ec_spi *ec_spi = ec_dev->priv;
> struct spi_transfer trans;
> @@ -372,7 +372,7 @@ static int cros_ec_spi_probe(struct spi_device *spi)
> ec_dev->dev = dev;
> ec_dev->priv = ec_spi;
> ec_dev->irq = spi->irq;
> - ec_dev->command_xfer = cros_ec_command_spi_xfer;
> + ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
> ec_dev->ec_name = ec_spi->spi->modalias;
> ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
> ec_dev->parent = &ec_spi->spi->dev;
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 2ee3190..79a3585 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -16,7 +16,9 @@
> #ifndef __LINUX_MFD_CROS_EC_H
> #define __LINUX_MFD_CROS_EC_H
>
> +#include <linux/notifier.h>
> #include <linux/mfd/cros_ec_commands.h>
> +#include <linux/mutex.h>
>
> /*
> * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
> @@ -55,34 +57,53 @@ struct cros_ec_msg {
> /**
> * struct cros_ec_device - Information about a ChromeOS EC device
> *
> + * @ec_name: name of EC device (e.g. 'chromeos-ec')
> + * @phys_name: name of physical comms layer (e.g. 'i2c-4')
> + * @dev: Device pointer
> + * @was_wake_device: true if this device was set to wake the system from
> + * sleep at the last suspend
> + * @event_notifier: interrupt event notifier for transport devices
> + * @command_send: send a command
> + * @command_recv: receive a response
> + * @command_sendrecv: send a command and receive a response
> + *
> * @name: Name of this EC interface
> * @priv: Private data
> * @irq: Interrupt to use
> - * @din: input buffer (from EC)
> - * @dout: output buffer (to EC)
> + * @din: input buffer (for data from EC)
> + * @dout: output buffer (for data to EC)
> * \note
> * These two buffers will always be dword-aligned and include enough
> * space for up to 7 word-alignment bytes also, so we can ensure that
> * the body of the message is always dword-aligned (64-bit).
> - *
> * We use this alignment to keep ARM and x86 happy. Probably word
> * alignment would be OK, there might be a small performance advantage
> * to using dword.
> * @din_size: size of din buffer to allocate (zero to use static din)
> * @dout_size: size of dout buffer to allocate (zero to use static dout)
> - * @command_send: send a command
> - * @command_recv: receive a command
> - * @ec_name: name of EC device (e.g. 'chromeos-ec')
> - * @phys_name: name of physical comms layer (e.g. 'i2c-4')
> * @parent: pointer to parent device (e.g. i2c or spi device)
> - * @dev: Device pointer
> - * dev_lock: Lock to prevent concurrent access
> * @wake_enabled: true if this device can wake the system from sleep
> - * @was_wake_device: true if this device was set to wake the system from
> - * sleep at the last suspend
> - * @event_notifier: interrupt event notifier for transport devices
> + * @lock: one transaction at a time
> + * @cmd_xfer: low-level channel to the EC
> */
> struct cros_ec_device {
> +
> + /* These are used by other drivers that want to talk to the EC */
> + const char *ec_name;
> + const char *phys_name;
> + struct device *dev;
> + bool was_wake_device;
> + struct class *cros_class;
> + struct blocking_notifier_head event_notifier;
> + int (*command_send)(struct cros_ec_device *ec,
> + uint16_t cmd, void *out_buf, int out_len);
> + int (*command_recv)(struct cros_ec_device *ec,
> + uint16_t cmd, void *in_buf, int in_len);
> + int (*command_sendrecv)(struct cros_ec_device *ec,
> + uint16_t cmd, void *out_buf, int out_len,
> + void *in_buf, int in_len);
> +
> + /* These are used to implement the platform-specific interface */
> const char *name;
> void *priv;
> int irq;
> @@ -90,26 +111,10 @@ struct cros_ec_device {
> uint8_t *dout;
> int din_size;
> int dout_size;
> - int (*command_send)(struct cros_ec_device *ec,
> - uint16_t cmd, void *out_buf, int out_len);
> - int (*command_recv)(struct cros_ec_device *ec,
> - uint16_t cmd, void *in_buf, int in_len);
> - int (*command_sendrecv)(struct cros_ec_device *ec,
> - uint16_t cmd, void *out_buf, int out_len,
> - void *in_buf, int in_len);
> - int (*command_xfer)(struct cros_ec_device *ec,
> - struct cros_ec_msg *msg);
> -
> - const char *ec_name;
> - const char *phys_name;
> struct device *parent;
> -
> - /* These are --private-- fields - do not assign */
> - struct device *dev;
> - struct mutex dev_lock;
> bool wake_enabled;
> - bool was_wake_device;
> - struct blocking_notifier_head event_notifier;
> + struct mutex lock;
> + int (*cmd_xfer)(struct cros_ec_device *ec, struct cros_ec_msg *msg);
> };
>
> /**
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> The lower-level driver may want to provide its own buffers. If so,
> there's no need to allocate new ones. This already happens to work
> just fine (since we check for size of 0 and use devm allocation), but
> it's good to document it.
>
> [dianders: Resolved conflicts; documented that no code changes needed
> on mainline]
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> include/linux/mfd/cros_ec.h | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 7e9fe6e..2ee3190 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -68,8 +68,8 @@ struct cros_ec_msg {
> * We use this alignment to keep ARM and x86 happy. Probably word
> * alignment would be OK, there might be a small performance advantage
> * to using dword.
> - * @din_size: size of din buffer
> - * @dout_size: size of dout buffer
> + * @din_size: size of din buffer to allocate (zero to use static din)
> + * @dout_size: size of dout buffer to allocate (zero to use static dout)
Why don't these use your new format i.e. doutsize, etc?
> * @command_send: send a command
> * @command_recv: receive a command
> * @ec_name: name of EC device (e.g. 'chromeos-ec')
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> Preparing the way for the LPC device, which is just a plaform_device without
> interrupts.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> drivers/mfd/cros_ec.c | 26 +++++++++++++-------------
> 1 file changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index 38fe9bf..bd6f936 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -119,17 +119,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
> return -ENOMEM;
> }
>
> - if (!ec_dev->irq) {
> - dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
> - return err;
> - }
> -
> - err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
> - IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> - "chromeos-ec", ec_dev);
> - if (err) {
> - dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
> - return err;
> + if (ec_dev->irq) {
> + err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + "chromeos-ec", ec_dev);
Is there anything stopping you using the devm_* version?
> + if (err) {
> + dev_err(dev, "request irq %d: error %d\n",
> + ec_dev->irq, err);
> + return err;
> + }
> }
>
> err = mfd_add_devices(dev, 0, cros_devs,
> @@ -145,7 +143,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
> return 0;
>
> fail_mfd:
> - free_irq(ec_dev->irq, ec_dev);
> + if (ec_dev->irq)
> + free_irq(ec_dev->irq, ec_dev);
>
> return err;
> }
> @@ -154,7 +153,8 @@ EXPORT_SYMBOL(cros_ec_register);
> int cros_ec_remove(struct cros_ec_device *ec_dev)
> {
> mfd_remove_devices(ec_dev->dev);
> - free_irq(ec_dev->irq, ec_dev);
> + if (ec_dev->irq)
> + free_irq(ec_dev->irq, ec_dev);
>
> return 0;
> }
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Mon, 16 Jun 2014, Doug Anderson wrote:
> From: Bill Richardson <[email protected]>
>
> This comment was incorrect, so update it.
>
> Signed-off-by: Bill Richardson <[email protected]>
> Signed-off-by: Simon Glass <[email protected]>
How many people did it take to write this patch? ;)
Acked-by: Lee Jones <[email protected]>
> Signed-off-by: Doug Anderson <[email protected]>
> ---
> include/linux/mfd/cros_ec.h | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 887ef4f..7e9fe6e 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -148,8 +148,7 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
> /**
> * cros_ec_remove - Remove a ChromeOS EC
> *
> - * Call this to deregister a ChromeOS EC. After this you should call
> - * cros_ec_free().
> + * Call this to deregister a ChromeOS EC, then clean up any private data.
> *
> * @ec_dev: Device to register
> * @return 0 if ok, -ve on error
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Lee,
On Wed, Jun 18, 2014 at 12:55 AM, Lee Jones <[email protected]> wrote:
> On Mon, 16 Jun 2014, Doug Anderson wrote:
>
>> From: Bill Richardson <[email protected]>
>>
>> Preparing the way for the LPC device, which is just a plaform_device without
>> interrupts.
>>
>> Signed-off-by: Bill Richardson <[email protected]>
>> Signed-off-by: Doug Anderson <[email protected]>
>> ---
>> drivers/mfd/cros_ec.c | 26 +++++++++++++-------------
>> 1 file changed, 13 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
>> index 38fe9bf..bd6f936 100644
>> --- a/drivers/mfd/cros_ec.c
>> +++ b/drivers/mfd/cros_ec.c
>> @@ -119,17 +119,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
>> return -ENOMEM;
>> }
>>
>> - if (!ec_dev->irq) {
>> - dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
>> - return err;
>> - }
>> -
>> - err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
>> - IRQF_TRIGGER_LOW | IRQF_ONESHOT,
>> - "chromeos-ec", ec_dev);
>> - if (err) {
>> - dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
>> - return err;
>> + if (ec_dev->irq) {
>> + err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
>> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
>> + "chromeos-ec", ec_dev);
>
> Is there anything stopping you using the devm_* version?
I'm generally quite hesitant about using the devm_ IRQ functions.
Requesting an IRQ enables the IRQ at the time of request and freeing
it disables it, right? Leaving it up to the the devm subsystem to
disable your IRQ tends to be a race waiting to happen if an IRQ
happens after you've freed all your memory / cleaned up all your
state.
Looking at cros_ec in particular though:
* Right now the last thing done in cros_ec_remove() (which is the last
thing in both cros_ec_i2c_remove and cros_ec_spi_remove) is to free
the IRQ. That means that you're right: we could switch to devm_ in
this case and it wouldn't introduce any new bugs.
* ...but I'm not convinced that the location of the free_irq() today
is quite right. I couldn't actually get it to crash or hang, but
there is a time period where we've called mfd_remove_devices() and the
IRQ is still active. That doesn't seem like a super great situation
to be in. I'll add a move of the irq_free to the patch series.
-Doug
Lee,
On Wed, Jun 18, 2014 at 12:57 AM, Lee Jones <[email protected]> wrote:
> On Mon, 16 Jun 2014, Doug Anderson wrote:
>
>> From: Bill Richardson <[email protected]>
>>
>> This comment was incorrect, so update it.
>>
>> Signed-off-by: Bill Richardson <[email protected]>
>> Signed-off-by: Simon Glass <[email protected]>
>
> How many people did it take to write this patch? ;)
>
> Acked-by: Lee Jones <[email protected]>
There's gotta be a joke here about how many Google engineers it takes
to fix a comment. In this case I think the answer is 3: one to fix
the comment, one to clean it up, and one to send it upstream. ;)
-Doug
Lee,
On Wed, Jun 18, 2014 at 12:53 AM, Lee Jones <[email protected]> wrote:
> On Mon, 16 Jun 2014, Doug Anderson wrote:
>
>> From: Bill Richardson <[email protected]>
>>
>> The lower-level driver may want to provide its own buffers. If so,
>> there's no need to allocate new ones. This already happens to work
>> just fine (since we check for size of 0 and use devm allocation), but
>> it's good to document it.
>>
>> [dianders: Resolved conflicts; documented that no code changes needed
>> on mainline]
>>
>> Signed-off-by: Bill Richardson <[email protected]>
>> Signed-off-by: Doug Anderson <[email protected]>
>> ---
>> include/linux/mfd/cros_ec.h | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index 7e9fe6e..2ee3190 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -68,8 +68,8 @@ struct cros_ec_msg {
>> * We use this alignment to keep ARM and x86 happy. Probably word
>> * alignment would be OK, there might be a small performance advantage
>> * to using dword.
>> - * @din_size: size of din buffer
>> - * @dout_size: size of dout buffer
>> + * @din_size: size of din buffer to allocate (zero to use static din)
>> + * @dout_size: size of dout buffer to allocate (zero to use static dout)
>
> Why don't these use your new format i.e. doutsize, etc?
Ah, you mean like the new "struct cros_ec_command" that's switched to
in (mfd: cros_ec: Use struct cros_ec_command to communicate with the
EC)? I don't know--it seems rather arbitrary. Personally I like
having the underscore (thus if we have to change I'd advocate changing
"struct cros_ec_command").
The inconsistency doesn't bother me terribly and it will be more work
to cherry-pick future patches. Since it didn't sound like you are
insisting then I won't change this, but if you say that you want me to
change it I'm more than happy to.
-Doug
On Wed, 18 Jun 2014, Doug Anderson wrote:
> Lee,
>
> On Wed, Jun 18, 2014 at 12:57 AM, Lee Jones <[email protected]> wrote:
> > On Mon, 16 Jun 2014, Doug Anderson wrote:
> >
> >> From: Bill Richardson <[email protected]>
> >>
> >> This comment was incorrect, so update it.
> >>
> >> Signed-off-by: Bill Richardson <[email protected]>
> >> Signed-off-by: Simon Glass <[email protected]>
> >
> > How many people did it take to write this patch? ;)
> >
> > Acked-by: Lee Jones <[email protected]>
>
> There's gotta be a joke here about how many Google engineers it takes
> to fix a comment. In this case I think the answer is 3: one to fix
> the comment, one to clean it up, and one to send it upstream. ;)
... and one to hold the ladder. No, wait! ;)
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Wed, 18 Jun 2014, Doug Anderson wrote:
> Lee,
>
> On Wed, Jun 18, 2014 at 12:55 AM, Lee Jones <[email protected]> wrote:
> > On Mon, 16 Jun 2014, Doug Anderson wrote:
> >
> >> From: Bill Richardson <[email protected]>
> >>
> >> Preparing the way for the LPC device, which is just a plaform_device without
> >> interrupts.
> >>
> >> Signed-off-by: Bill Richardson <[email protected]>
> >> Signed-off-by: Doug Anderson <[email protected]>
> >> ---
> >> drivers/mfd/cros_ec.c | 26 +++++++++++++-------------
> >> 1 file changed, 13 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> >> index 38fe9bf..bd6f936 100644
> >> --- a/drivers/mfd/cros_ec.c
> >> +++ b/drivers/mfd/cros_ec.c
> >> @@ -119,17 +119,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
> >> return -ENOMEM;
> >> }
> >>
> >> - if (!ec_dev->irq) {
> >> - dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
> >> - return err;
> >> - }
> >> -
> >> - err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
> >> - IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> >> - "chromeos-ec", ec_dev);
> >> - if (err) {
> >> - dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
> >> - return err;
> >> + if (ec_dev->irq) {
> >> + err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
> >> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> >> + "chromeos-ec", ec_dev);
> >
> > Is there anything stopping you using the devm_* version?
>
> I'm generally quite hesitant about using the devm_ IRQ functions.
> Requesting an IRQ enables the IRQ at the time of request and freeing
> it disables it, right? Leaving it up to the the devm subsystem to
> disable your IRQ tends to be a race waiting to happen if an IRQ
> happens after you've freed all your memory / cleaned up all your
> state.
>
> Looking at cros_ec in particular though:
>
> * Right now the last thing done in cros_ec_remove() (which is the last
> thing in both cros_ec_i2c_remove and cros_ec_spi_remove) is to free
> the IRQ. That means that you're right: we could switch to devm_ in
> this case and it wouldn't introduce any new bugs.
>
> * ...but I'm not convinced that the location of the free_irq() today
> is quite right. I couldn't actually get it to crash or hang, but
> there is a time period where we've called mfd_remove_devices() and the
> IRQ is still active. That doesn't seem like a super great situation
> to be in. I'll add a move of the irq_free to the patch series.
I guess if you're concerned about ordering you could always use
devm_free_irq() in the places where you think it should be freed
earlier than release. I'm pretty sure that discludes the failure
patch in probe() though, so we'd still be able to rid a few lines.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Lee,
On Wed, Jun 18, 2014 at 9:46 AM, Lee Jones <[email protected]> wrote:
> On Wed, 18 Jun 2014, Doug Anderson wrote:
>
>> Lee,
>>
>> On Wed, Jun 18, 2014 at 12:55 AM, Lee Jones <[email protected]> wrote:
>> > On Mon, 16 Jun 2014, Doug Anderson wrote:
>> >
>> >> From: Bill Richardson <[email protected]>
>> >>
>> >> Preparing the way for the LPC device, which is just a plaform_device without
>> >> interrupts.
>> >>
>> >> Signed-off-by: Bill Richardson <[email protected]>
>> >> Signed-off-by: Doug Anderson <[email protected]>
>> >> ---
>> >> drivers/mfd/cros_ec.c | 26 +++++++++++++-------------
>> >> 1 file changed, 13 insertions(+), 13 deletions(-)
>> >>
>> >> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
>> >> index 38fe9bf..bd6f936 100644
>> >> --- a/drivers/mfd/cros_ec.c
>> >> +++ b/drivers/mfd/cros_ec.c
>> >> @@ -119,17 +119,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
>> >> return -ENOMEM;
>> >> }
>> >>
>> >> - if (!ec_dev->irq) {
>> >> - dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
>> >> - return err;
>> >> - }
>> >> -
>> >> - err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
>> >> - IRQF_TRIGGER_LOW | IRQF_ONESHOT,
>> >> - "chromeos-ec", ec_dev);
>> >> - if (err) {
>> >> - dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
>> >> - return err;
>> >> + if (ec_dev->irq) {
>> >> + err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
>> >> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
>> >> + "chromeos-ec", ec_dev);
>> >
>> > Is there anything stopping you using the devm_* version?
>>
>> I'm generally quite hesitant about using the devm_ IRQ functions.
>> Requesting an IRQ enables the IRQ at the time of request and freeing
>> it disables it, right? Leaving it up to the the devm subsystem to
>> disable your IRQ tends to be a race waiting to happen if an IRQ
>> happens after you've freed all your memory / cleaned up all your
>> state.
>>
>> Looking at cros_ec in particular though:
>>
>> * Right now the last thing done in cros_ec_remove() (which is the last
>> thing in both cros_ec_i2c_remove and cros_ec_spi_remove) is to free
>> the IRQ. That means that you're right: we could switch to devm_ in
>> this case and it wouldn't introduce any new bugs.
>>
>> * ...but I'm not convinced that the location of the free_irq() today
>> is quite right. I couldn't actually get it to crash or hang, but
>> there is a time period where we've called mfd_remove_devices() and the
>> IRQ is still active. That doesn't seem like a super great situation
>> to be in. I'll add a move of the irq_free to the patch series.
>
> I guess if you're concerned about ordering you could always use
> devm_free_irq() in the places where you think it should be freed
> earlier than release. I'm pretty sure that discludes the failure
> patch in probe() though, so we'd still be able to rid a few lines.
Hmmm, I'd even vote to move the IRQ request to be the last thing in
probe (which would also mean that the devm wouldn't be used but would
then require us to call mfd_remove_devices()). ...but I can't find
any good reason that we need to do that.
Oh, dang. I just looked at the next local patch in the list of local
ones. ...it totally rips this code out and moves the IRQ to
cros_ec_keyboard where it belongs (the infrastructure didn't really
allow more than one person to use this anyway). I'll just squash this
patch there and we're done. Sorry for the noise! :(
-Doug