From 60c87bc53178965aeb3dea798020e33900ab46f0 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 2 Jul 2019 14:07:05 +0930 Subject: [PATCH 1/3] MAINTAINERS: Add FSI subsystem The subsystem was merged some time ago but we did not have a maintainers entry. The mailing list exists to allow our patchwork to slurp up the patches. The tree will be co-maintained by myself and Jeremy. Acked-by: Jeremy Kerr Signed-off-by: Joel Stanley --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5cfbea4ce575..c37c14459759 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6477,6 +6477,19 @@ F: fs/crypto/ F: include/linux/fscrypt*.h F: Documentation/filesystems/fscrypt.rst +FSI SUBSYSTEM +M: Jeremy Kerr +M: Joel Stanley +R: Alistar Popple +R: Eddie James +L: linux-fsi@lists.ozlabs.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi.git +Q: http://patchwork.ozlabs.org/project/linux-fsi/list/ +S: Supported +F: drivers/fsi/ +F: include/linux/fsi*.h +F: include/trace/events/fsi*.h + FSI-ATTACHED I2C DRIVER M: Eddie James L: linux-i2c@vger.kernel.org From afd26118f0dcf29db031a213f6f95c46ff3bdcbe Mon Sep 17 00:00:00 2001 From: Eddie James Date: Tue, 2 Jul 2019 10:47:42 -0500 Subject: [PATCH 2/3] OCC: FSI and hwmon: Add sequence numbering Sequence numbering of the commands submitted to the OCC is required by the OCC interface specification. Add sequence numbering and check for the correct sequence number on the response. Signed-off-by: Eddie James Acked-by: Guenter Roeck Reviewed-by: Lei YU Signed-off-by: Joel Stanley --- drivers/fsi/fsi-occ.c | 15 ++++++++++++--- drivers/hwmon/occ/common.c | 4 ++-- drivers/hwmon/occ/common.h | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c index a2301cea1cbb..7da9c81759ac 100644 --- a/drivers/fsi/fsi-occ.c +++ b/drivers/fsi/fsi-occ.c @@ -412,6 +412,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS); struct occ *occ = dev_get_drvdata(dev); struct occ_response *resp = response; + u8 seq_no; u16 resp_data_length; unsigned long start; int rc; @@ -426,6 +427,8 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, mutex_lock(&occ->occ_lock); + /* Extract the seq_no from the command (first byte) */ + seq_no = *(const u8 *)request; rc = occ_putsram(occ, OCC_SRAM_CMD_ADDR, request, req_len); if (rc) goto done; @@ -441,11 +444,17 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, if (rc) goto done; - if (resp->return_status == OCC_RESP_CMD_IN_PRG) { + if (resp->return_status == OCC_RESP_CMD_IN_PRG || + resp->seq_no != seq_no) { rc = -ETIMEDOUT; - if (time_after(jiffies, start + timeout)) - break; + if (time_after(jiffies, start + timeout)) { + dev_err(occ->dev, "resp timeout status=%02x " + "resp seq_no=%d our seq_no=%d\n", + resp->return_status, resp->seq_no, + seq_no); + goto done; + } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(wait_time); diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 13a6290c8d25..cccf91742c1a 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -124,12 +124,12 @@ struct extended_sensor { static int occ_poll(struct occ *occ) { int rc; - u16 checksum = occ->poll_cmd_data + 1; + u16 checksum = occ->poll_cmd_data + occ->seq_no + 1; u8 cmd[8]; struct occ_poll_response_header *header; /* big endian */ - cmd[0] = 0; /* sequence number */ + cmd[0] = occ->seq_no++; /* sequence number */ cmd[1] = 0; /* cmd type */ cmd[2] = 0; /* data length msb */ cmd[3] = 1; /* data length lsb */ diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h index fc13f3c73c47..67e6968b8978 100644 --- a/drivers/hwmon/occ/common.h +++ b/drivers/hwmon/occ/common.h @@ -95,6 +95,7 @@ struct occ { struct occ_sensors sensors; int powr_sample_time_us; /* average power sample time */ + u8 seq_no; u8 poll_cmd_data; /* to perform OCC poll command */ int (*send_cmd)(struct occ *occ, u8 *cmd); From 371975b0b07520c85098652d561639837a60a905 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Fri, 28 Jun 2019 16:07:37 +0800 Subject: [PATCH 3/3] fsi/core: Fix error paths on CFAM init Change d1dcd67825 re-worked the struct fsi_slave initialisation in fsi_slave_init, but introduced a few inconsitencies: the slave->dev is now registered through cdev_device_add, but we may kfree() the device out from underneath the cdev registration. We may also leave an IDA allocated. This change fixes the error paths, so that we kfree() only before the device is registered with the core code. We also move the smode write to before we start creating proper devices, as it's the most likely to fail. We also remove the IDA-allocated minor on error, and properly clean up the of_node. Fixes: d1dcd6782576 ("fsi: Add cfam char devices") Reported-by: Lei YU Tested-by: John Wang Signed-off-by: Jeremy Kerr Signed-off-by: Joel Stanley --- drivers/fsi/fsi-core.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 2c31563fdcae..10e443b7f892 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -1037,6 +1037,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id) } + rc = fsi_slave_set_smode(slave); + if (rc) { + dev_warn(&master->dev, + "can't set smode on slave:%02x:%02x %d\n", + link, id, rc); + goto err_free; + } + /* Allocate a minor in the FSI space */ rc = __fsi_get_new_minor(slave, fsi_dev_cfam, &slave->dev.devt, &slave->cdev_idx); @@ -1048,17 +1056,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id) rc = cdev_device_add(&slave->cdev, &slave->dev); if (rc) { dev_err(&slave->dev, "Error %d creating slave device\n", rc); - goto err_free; + goto err_free_ida; } - rc = fsi_slave_set_smode(slave); - if (rc) { - dev_warn(&master->dev, - "can't set smode on slave:%02x:%02x %d\n", - link, id, rc); - kfree(slave); - return -ENODEV; - } + /* Now that we have the cdev registered with the core, any fatal + * failures beyond this point will need to clean up through + * cdev_device_del(). Fortunately though, nothing past here is fatal. + */ + if (master->link_config) master->link_config(master, link, slave->t_send_delay, @@ -1075,10 +1080,13 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id) dev_dbg(&master->dev, "failed during slave scan with: %d\n", rc); - return rc; + return 0; - err_free: - put_device(&slave->dev); +err_free_ida: + fsi_free_minor(slave->dev.devt); +err_free: + of_node_put(slave->dev.of_node); + kfree(slave); return rc; }