All of lore.kernel.org
 help / color / mirror / Atom feed
* [tpmdd-devel] ST19NP18 I2C driver submission + possible bug found in the last TPM kernel core
       [not found]               ` <35E2570B-DD77-4CDB-9B13-7211E18E7000@linux.vnet.ibm.com>
@ 2010-09-03 19:54                 ` Christophe Henri RICARD
  2010-09-03 23:28                   ` [PATCH 0/2] tpm_stm_st19+i2c: use pr_<level> and cleanups Joe Perches
  0 siblings, 1 reply; 10+ messages in thread
From: Christophe Henri RICARD @ 2010-09-03 19:54 UTC (permalink / raw)
  To: linux-kernel
  Cc: 'Marcel Selhorst', debora, tpmdd-devel, Rajiv Andrade, jmorris

[-- Attachment #1: Type: text/plain, Size: 604 bytes --]

Hi,

Please find in attached file the tpm driver for the ST19NP18 device working on a I2C bus.
This driver use the Linux I2C cores, TPM cores and generic gpio interfaces.

It has been tested with the latest stable kernel 2.6.35.4 available on kernel.org.

Let me know of your feedback.
Best Regards
Christophe RICARD.


--------------------- Previous Message --------------------------------------------------

Hi Chris,

Just submit it to LKML with us on CC, so I'll then ack and CC James Morris.

Thanks
---
Rajiv Andrade
Security Development
IBM Linux Technology Center





[-- Attachment #2: tpm_stm_st19_i2c.patch --]
[-- Type: application/octet-stream, Size: 36725 bytes --]

diff -uNr linux-2.6.35.4/Documentation/tpm/tpm_stm_st19_i2c.txt linux-tpm/Documentation/tpm/tpm_stm_st19_i2c.txt
--- linux-2.6.35.4/Documentation/tpm/tpm_stm_st19_i2c.txt	1969-12-31 18:00:00.000000000 -0600
+++ linux-tpm/Documentation/tpm/tpm_stm_st19_i2c.txt	2010-09-02 07:22:36.315076374 -0500
@@ -0,0 +1,168 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010 STMicroelectronics
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ */
+
+PURPOSE OF THE DOCUMENT
+------------------------
+This document is intend to describe how to install the TPM driver for
+TPM ST19NP18 using I2C protocols.
+
+
+PLATFORM USED FOR TESTING
+--------------------------
+During the development, several embedded platforms running ARM CPU have been
+used.
+Validated platforms listing:
+- TI Beagleboard
+- STMicroelectronics Spear 300
+- STMicroelectronics Spear 600
+
+REQUIREMENTS
+-------------
+Software
+=========
+This TPM driver could be install under a kernel which implement at least the
+following features:
+- Linux GENERIC_GPIO programming interfaces.
+- I2C new style programming interface base (with probe & remove functions)
+- 1 I2C adapter (I2C Linux controller driver) or use of I2C_GPIO driver for I2C
+bitbanging.
+
+
+Hardware
+=========
+To run a TPM the platform needs  at least:
+- 2 Power supply (3.3V).
+- 1 I2C controller or 2 GPIOs used for SDA & SCL (I2C bit bang method).
+- 2 GPIOs for signals accept_command & data_available.
+
+TPM I2C speed is 100Khz (Maximum)
+
+All TPM signals work at 3.3V
+
+HOW TO INSTALL
+---------------
+Platform installation file
+===========================
+(N.B: platform file in arch/<processor_type>/mach-<platform-name>/
+
+
+1 - Software integration
+=========================
+<processor_type> could be: alpha, arm, avr32, blackfin, cris, frv, h8300, ia64,
+m32r, m68k, m68knommu, parisc, powerpc, s390, sh, sparc, sparc64, um, x86,
+xtensa...
+<platform-name> corresponds to your platform
+
+In the file where the machine_init() function exists, the developer must
+declare:
+- 1 struct st19np18_platform_data to provide which gpio the driver will use.
+	* The accept_pin and data_avail_pin gpio are configured as input only.
+	* This gpio management is under the platform developer responsability.
+
+Finally in the machine_init() function provided in the same file, the developer
+should use the well known function i2c_register_board_info() from the I2C Linux
+API Core.
+
+2- Hardware integration
+========================
+- ST recommends connecting VPS1 and VPS2 to board power supply and at least two
+GNDs (on each side of TSSOP28 package). (See datasheet for further informations)
+
+- As the ST19NP18 has no internal pull up, ST recommands to had:
+  * 2 external pull up on SDA & SCL signals (RpSDA/RpSCL) with value according
+to the abacus on page 40 or the "I2C Bus specification", version 2.1 January
+2000.
+
+
+Platform integration advises
+=============================
+
+For power management purposes, the kernel will send a TPM_SaveState command in the
+suspend tpm driver function.
+If the platform generate a TPM Init event on wakeup, the first TPM command that should
+be executed before the Linux kernel is back (resume function execution) is
+TPM_Startup(ST_STATE).
+
+Here is an example with beagleboard:
+====================================
+Depending on the platform, the developper should specify in
+the platform init file the following informations:
+- The platform gpio's used to managed the tpm's accept_pin/data_avail_pin
+(in a struct st19np18_platform_data declaration).
+- The TPM I2C 7 bits address (TPM_I2C_ST19_ADDR_WR) (in a struct i2c_board_info).
+
+Then the developper should add  the TPM slave device to the good i2c adapter with the
+i2c_register_board_info function (Assuming that the gpio and the i2c bus are well configured).
+
+file arch\arm\mach-omap2\board-omap3beagle.c
+add the following:
+-----------------------------------------------------------------------
+
+static struct st19np18_platform_data tpm_data = {
+        .accept_pin = 135,
+        .data_avail_pin = 143,
+};
+
+static struct i2c_board_info __initdata tpm_st19_i2c_board_info[] = {
+        {
+         I2C_BOARD_INFO(TPM_DRIVER_NAME, TPM_I2C_ST19_ADDR_WR),
+         .platform_data = &tpm_data,
+         },
+};
+
+------------------------------------------------------------------------
+Then complete the beagleboard init to be like that:
+------------------------------------------------------------------------
+static void __init omap3_beagle_init(void)
+{
+        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+        omap3_beagle_i2c_init();
+        platform_add_devices(omap3_beagle_devices,
+                        ARRAY_SIZE(omap3_beagle_devices));
+        omap_serial_init();
+
+        omap_mux_init_gpio(170, OMAP_PIN_INPUT);
+        gpio_request(170, "DVI_nPD");
+        /* REVISIT leave DVI powered down until it's needed ... */
+        gpio_direction_output(170, true);
+
+        usb_musb_init(&musb_board_data);
+        usb_ehci_init(&ehci_pdata);
+        omap3beagle_flash_init();
+
+        beagle_display_init();
+
+        /* Ensure SDRC pins are mux'd for self-refresh */
+        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+        omap_mux_init_gpio(((struct st19np18_platform_data *)
+                           tpm_st19_i2c_board_info[0].platform_data)->data_avail_pin,
+                           OMAP_PIN_INPUT);
+	omap_mux_init_gpio(((struct st19np18_platform_data *)
+                           tpm_st19_i2c_board_info[0].platform_data)->accept_pin,
+                           OMAP_PIN_INPUT);
+
+	i2c_register_board_info(3, tpm_st19_i2c_board_info, ARRAY_SIZE(tpm_st19_i2c_board_info));
+}
diff -uNr linux-2.6.35.4/drivers/char/tpm/Kconfig linux-tpm/drivers/char/tpm/Kconfig
--- linux-2.6.35.4/drivers/char/tpm/Kconfig	2010-08-26 18:47:12.000000000 -0500
+++ linux-tpm/drivers/char/tpm/Kconfig	2010-08-31 12:51:02.944407763 -0500
@@ -60,4 +60,13 @@
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.prosec.rub.de/tpm
 
+config TCG_ST19_I2C
+        tristate "STMicroelectronics ST19 I2C TPM"
+        depends on I2C
+        depends on GPIOLIB
+        ---help---
+        If you have a TPM security chip from STMicroelectronics working with
+        an I2C bus say Yes and it will be accessible from within Linux.
+        To compile this driver as a module, choose M here; the module will be
+        called tpm_stm_st19_i2c.
 endif # TCG_TPM
diff -uNr linux-2.6.35.4/drivers/char/tpm/Makefile linux-tpm/drivers/char/tpm/Makefile
--- linux-2.6.35.4/drivers/char/tpm/Makefile	2010-08-26 18:47:12.000000000 -0500
+++ linux-tpm/drivers/char/tpm/Makefile	2010-08-31 12:51:02.964407690 -0500
@@ -9,3 +9,4 @@
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_ST19_I2C) += tpm_stm_st19_i2c.o
diff -uNr linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.c linux-tpm/drivers/char/tpm/tpm_stm_st19_i2c.c
--- linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-tpm/drivers/char/tpm/tpm_stm_st19_i2c.c	2010-09-02 06:17:52.544451599 -0500
@@ -0,0 +1,822 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010  STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: tpm_stm_st19_i2c.c
+ *
+ * @Synopsis:
+ * ----------------------------------------------------------------------
+ *	02/12/2008
+ *	- Stand alone implementation (without any TPM api)
+ * ----------------------------------------------------------------------
+ *	03/02/2010
+ *	- Power management (suspend and resume functions)
+ *	implementation
+ * ----------------------------------------------------------------------
+ *	03/19/2010
+ *	- Use of the linux kernel TPM api --> driver/char/tpm
+ * ----------------------------------------------------------------------
+ *	05/26/2010
+ *	- Update code for code submission and bug fixes:
+ *	- Comments spelling fixes
+ *	- Lindent script execution
+ *	- checkpatch.pl script execution
+ *	- fix syslog error when loaded as a module:
+ *	 "release() function missing and must be fixed"
+ *	- name files change from
+ *	  stm_st19_tpm_i2c to tpm_stm_st19_i2c
+ * ----------------------------------------------------------------------
+ *	06/15/2010
+ *	- Update for new tpm core device.
+ *	num_opens --> is_open
+ * ----------------------------------------------------------------------
+ *	07/08/2010
+ *	- Update probe, resume suspend functions
+ *	- Fix issue suspend buffer and work around related to the
+ *	chip->data_buffer not allocated.
+ * ----------------------------------------------------------------------
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/tpm_stm_st19_i2c.h>
+
+#include "tpm.h"
+
+#include "tpm_stm_st19_i2c.h"
+
+/*
+ * @Comments: tpm_stm_st19_platform_specific.h deliver shows a platform specific
+ * file example.
+ * It has been created to split TPM datas and platform.
+ * This example could be used when the driver is built as a module.
+ * In case of other platform, please add a struct i2c_board_info in your arch/
+ * platform file.
+ */
+static struct st19np18_platform_data *pin_infos;
+
+/*
+ * gpio_readpin is a wrapper to read a gpio value.
+ * Use generic gpio APIs
+ * @param: pin_id, the pin identifier where the value will be read.
+ * @return: the gpio value (should be 0 or 1) or negative errno
+ */
+static int gpio_readpin(int pin_id)
+{
+	int ret;
+	ret = gpio_direction_input(pin_id);
+	if (ret == 0)
+		return gpio_get_value(pin_id);
+	return ret;
+}
+
+/*
+ * gpio_writepin is a wrapper to write a gpio value.
+ * Use generic gpio APIs.
+ * @param: pin_id, the pin identifier where the value will be wrote.
+ * @param: value, the value that will be written.
+ * @return: 0 in case of success
+ */
+#ifdef DEBUG
+static int gpio_writepin(int pin_id, int value)
+{
+	int ret;
+	ret = gpio_direction_output(pin_id, value);
+
+	if (ret == 0)
+		gpio_set_value(pin_id, value);
+	return ret;
+}
+#endif
+
+static int wait_until_good_shape(void)
+{
+	int state_data = 0;
+	int state_command = 0;
+	int timeout = msecs_to_jiffies(STARTUP_WAIT_INTERVAL);
+	int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
+	int ret = 0;
+	wait_queue_head_t queue;
+
+	int wait_time = 0;
+	DEFINE_WAIT(__wait);
+	init_waitqueue_head(&queue);
+
+	do {
+		prepare_to_wait(&queue, &__wait, TASK_INTERRUPTIBLE);
+		state_data = gpio_readpin(pin_infos->data_avail_pin);
+		state_command = gpio_readpin(pin_infos->accept_pin);
+
+		if (state_data == 0 && state_command > 0)
+			return 0;
+		else if (wait_time >= timeout)
+			return -EIO;
+		else if (!signal_pending(current)) {
+			ret = schedule_timeout(time);
+			wait_time += time;
+		} else
+			ret = -ERESTARTSYS;
+	} while (1);
+	finish_wait(&queue, &__wait);
+
+	return ret;
+}
+
+/*
+ * wait_event_interruptible_on_gpio is a function that poll on
+ * GPIO dataavailable and GPIO acceptcommand
+ * @param: queue, the queue where the work will be stored
+ * @param: timeout, maximal pooling time.
+ * @return: DATA_ON in case of data_available pin goes high (logical value 1).
+ * COMMAND_ON in case of accept_command pin goes high (logical value 1).
+ * -EIO in case of data_available & accept_command pin goes high
+ *		(logical value 1).
+ * -EPERM in case of data_available & accept_command pin still low
+ *		(logical value 0).
+ */
+static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
+					    int timeout)
+{
+	int state_data = 0;
+	int state_command = 0;
+	int ret = msecs_to_jiffies(TICK_GPIO_SPOOLING);
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int long_timeout =
+	    tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG);
+	int wait_time = 0;
+	DEFINE_WAIT(__wait);
+
+	if (timeout > long_timeout)
+		timeout = long_timeout;
+
+	do {
+		prepare_to_wait(&queue, &__wait, TASK_INTERRUPTIBLE);
+		state_data = gpio_readpin(pin_infos->data_avail_pin);
+		state_command = gpio_readpin(pin_infos->accept_pin);
+
+		if (state_data > 0 || state_command > 0)
+			break;
+		else if (wait_time >= timeout)
+			break;
+		else if (!signal_pending(current)) {
+			ret =
+			    schedule_timeout(msecs_to_jiffies
+					     (TICK_GPIO_SPOOLING));
+			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
+		} else {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	} while (1);
+	finish_wait(&queue, &__wait);
+
+	return (state_data && state_command) ? -EIO : state_data ? DATA_ON :
+	    state_command ? COMMAND_ON : -EPERM;
+}
+
+/*
+ * responseSize return the command size
+ * @param: buffer, command buffer.
+ * @param: size, the buffer size.
+ * @return: the command size.
+ */
+static int responseSize(const char *buffer, size_t size)
+{
+	size_t val = 0;
+	if (size >= TPM_HEADER_SIZE) {
+		val = (size_t) (((unsigned)buffer[2]) << 24
+				| ((unsigned)buffer[3]) << 16
+				| ((unsigned)buffer[4]) << 8 | (unsigned)
+				buffer[5]);
+	}
+
+	if (val < TPM_BUFSIZE)
+		return val;
+	else
+		return TPM_BUFSIZE;
+}
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ * Before sending any TPM commands, tpm_stm_i2c_send poll data_available and
+ * accept_command TPM GPIOs.
+ *
+ * In case the data_available is high (logical value 1), tpm_stm_i2c_send will
+ * empty the TPM FIFO by reading all the datas stored inside the TPM.
+ *
+ * Then, if the accept_command TPM GPIO is high(logical value 1)
+ * tpm_stm_i2c_send will first send the 10 bytes header of the TCG commands and
+ * then send the others bytes by 40 bytes blocks.
+ *
+ * data_available and accept_command TPM GPIOs will goes low when the TPM
+ * compute the command.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to send.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes sent.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	u32 ret = 0, i, size, ordinal, pin = 0;
+	struct i2c_client *client;
+
+#ifdef DEBUG
+	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_send\n");
+#endif
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (count < TPM_HEADER_SIZE)
+		return -EBUSY;
+	client = (struct i2c_client *)pin_infos->client;
+
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+	/* i2c_client initialization */
+	client->flags = 0;
+
+	/* Wait for AcceptCmd signal high */
+	/* Check if data are available before */
+	/* sending data (data_avail_pin hight) */
+	/* If data are available, we read the data */
+	init_waitqueue_head(&pin_infos->write_queue);
+	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
+					       tpm_calc_ordinal_duration
+					       (chip, ordinal));
+	if (pin < 0) {
+		ret = pin;
+		goto end;
+	}
+
+	client->flags = I2C_M_RD;
+
+	size = TPM_HEADER_SIZE;
+	for (i = 0; pin == DATA_ON && i < size;) {
+		ret = i2c_master_recv(client,
+				      pin_infos->tpm_i2c_buffer[1],
+				      (i == 0) ? TPM_HEADER_SIZE :
+				      count - i > TPM_I2C_BLOCK_SIZE ?
+				      TPM_I2C_BLOCK_SIZE : count - i);
+		if (ret < 0)
+			goto end;
+		if (i == 0)
+			size =
+			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
+		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+
+		if (i < size)
+			pin =
+			    wait_event_interruptible_on_gpio(pin_infos->
+							     write_queue,
+							     msecs_to_jiffies
+							     (TPM_I2C_SHORT));
+	}
+
+	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
+					       msecs_to_jiffies(TPM_I2C_SHORT));
+
+	/* i2c_client initialization */
+	client->flags = 0;
+
+	size = TPM_HEADER_SIZE;
+	for (i = 0; i < size && pin == COMMAND_ON;) {
+		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
+		       (i == 0) ? TPM_HEADER_SIZE : count - i >
+		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
+
+		if (i == 0) {
+			size = responseSize(buf, count);
+			size = (size < count ? size : count);
+		}
+		ret =
+		    i2c_master_send(client,
+				    pin_infos->tpm_i2c_buffer[0],
+				    count >= TPM_HEADER_SIZE ? (i ==
+								0) ?
+				    TPM_HEADER_SIZE : count - i >
+				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
+				    count - i : count);
+		if (ret < 0) {
+			printk(KERN_INFO "tpm_st19_i2c: Failed to send data\n");
+			goto end;
+		}
+
+		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+		/* Wait for AcceptCmd signal hight */
+		if (i < size)
+			pin =
+			    wait_event_interruptible_on_gpio(pin_infos->
+							     write_queue,
+							     msecs_to_jiffies
+							     (TPM_I2C_SHORT));
+
+		if (pin != COMMAND_ON) {
+			printk(KERN_INFO
+			       "tpm_st19_i2c:"
+			       " Failed to read gpio pin (AcceptCmd)\n");
+			ret = -EIO;
+			goto end;
+		}
+	}
+	if (i == 0) {
+		printk(KERN_INFO
+		       "tpm_st19_i2c: Failed to read gpio pin (AcceptCmd)\n");
+		ret = -EIO;
+	}
+end:
+	return ret ? ret : count;
+}
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * Before receiving any TPM response, tpm_stm_i2c_recv poll data_available and
+ * accept_command TPM GPIOs.
+ *
+ * In case the accept_command is high (logical value 1), tpm_stm_i2c_recv will
+ * do nothing.
+ *
+ * Then, if the data_available TPM GPIO is high(logical value 1)
+ * tpm_stm_i2c_recv will first receive the 10 bytes header of the TCG TPM
+ * response and then receive the others bytes by 40 bytes blocks.
+ *
+ * accept_command TPM GPIOs will goes high when the TPM Fofo is empty.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes received.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int ret = 0;
+	int i, size;
+	int pin = 0;
+	struct i2c_client *client;
+
+#ifdef DEBUG
+	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_recv\n");
+#endif
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (count < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	client = (struct i2c_client *)pin_infos->client;
+
+	/* Configure TPM I2C */
+	client->flags = I2C_M_RD;
+
+	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
+	init_waitqueue_head(&chip->vendor.read_queue);
+	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
+					       tpm_calc_ordinal_duration
+					       (chip, TPM_I2C_ORDINAL_LONG));
+
+	size = TPM_HEADER_SIZE;
+	for (i = 0; i < size && pin == DATA_ON;) {
+		ret =
+		    i2c_master_recv(client,
+				    pin_infos->tpm_i2c_buffer[1],
+				    (count >= TPM_HEADER_SIZE ? i ==
+				     0 ? TPM_HEADER_SIZE : (size - i) >
+				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
+				     size - i : count));
+		if (ret < 0) {
+			printk(KERN_INFO
+			       "tpm_st19_i2c:"
+			       " Failed to read gpio pin (DataAvalaible)\n");
+			goto end;
+		}
+
+		if (buf != NULL) {
+			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
+			       (count >= TPM_HEADER_SIZE ? i == 0 ?
+				TPM_HEADER_SIZE : (size - i) >
+				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
+				i : count));
+
+			if (i == 0) {
+				size = responseSize(buf, size);
+				if (size > count)
+					size = count;
+			}
+		} else {
+			printk(KERN_INFO "tpm_st19_i2c: read buffer is NULL\n");
+			goto end;
+		}
+
+		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+
+		if (i < size)
+			pin =
+			    wait_event_interruptible_on_gpio(chip->vendor.
+							     read_queue,
+							     msecs_to_jiffies
+							     (TPM_I2C_SHORT));
+	}
+
+	if (i == 0) {
+		printk(KERN_INFO
+		       "tpm_st19_i2c: "
+		       "Failed to read gpio pin (DataAvalaible)\n");
+		ret = -EIO;
+		goto end;
+	}
+	return size;
+end:
+	return ret;
+}
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+}				/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_i2c_status is not implemented because TIS registers are not
+ * implemented.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	return -ENOSYS;
+}				/* tpm_stm_i2c_status() */
+
+#ifdef _MODULE
+
+static void tpm_st19_i2c_dummy(struct device *dev)
+{
+
+}				/*tpm_st19_i2c_dummy() */
+
+/*
+ * tpm_st19_i2c_release do nothing
+ * @param: kobj, not used
+ */
+static void tpm_st19_i2c_release(struct kobject *kobj)
+{
+	struct tpm_chip *chip;
+	printk(KERN_INFO "tpm_st19_i2c_release\n");
+
+	if (_client != NULL) {
+		chip = (struct tpm_chip *)i2c_get_clientdata(_client);
+
+		if (chip != NULL) {
+			chip->release = tpm_st19_i2c_dummy;
+			chip->dev->release(chip->dev);
+		}
+	}
+}				/* tpm_st19_i2c_release() */
+#endif /*_MODULE */
+/*
+ * tpm_st19_i2c_ioctl provides 2 handles:
+ * - TPMIOC_CANCEL: allow to CANCEL a TPM commands execution.
+ *   See tpm_stm_i2c_cancel description above
+ * - TPMIOC_TRANSMIT: allow to transmit a TPM commands.
+ *
+ * @return: In case of success, return TPM response size.
+ * In other case return < 0 value describing the issue.
+ */
+static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
+				  unsigned int cmd, unsigned long arg)
+{
+	int in_size = 0, out_size = 0;
+	struct tpm_chip *chip = file->private_data;
+
+	switch (cmd) {
+	case TPMIOC_CANCEL:
+		tpm_stm_i2c_cancel(chip);
+		return -ENOSYS;
+	case TPMIOC_TRANSMIT:
+		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
+		    (const char *)arg, TPM_HEADER_SIZE))
+			return -EFAULT;
+		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
+				      TPM_HEADER_SIZE);
+		if (in_size > sizeof(pin_infos->tpm_i2c_buffer[0]))
+			in_size = sizeof(pin_infos->tpm_i2c_buffer[0]);
+		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
+				   (const char *)arg, in_size))
+			return -EFAULT;
+		tpm_stm_i2c_send(chip, pin_infos->tpm_i2c_buffer[0], in_size);
+
+		out_size = tpm_stm_i2c_recv(chip, pin_infos->tpm_i2c_buffer[1],
+					    TPM_BUFSIZE);
+		if (copy_to_user((char *)arg, pin_infos->tpm_i2c_buffer[1],
+				 out_size))
+			return -EFAULT;
+		return out_size;
+	default:
+		return -ENOTTY;
+	}
+	return -ENOTTY;
+}
+
+static const struct file_operations tpm_st19_i2c_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = tpm_read,
+	.ioctl = tpm_st19_i2c_ioctl,
+	.write = tpm_write,
+	.open = tpm_open,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *stm_tpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group stm_tpm_attr_grp = {
+	.attrs = stm_tpm_attrs
+};
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.attr_group = &stm_tpm_attr_grp,
+	.miscdev = {.fops = &tpm_st19_i2c_fops,},
+};
+
+/*
+ * tpm_st19_i2c_probe initialize the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: id, the i2c_device_id struct.
+ * @return: 0 in case of success.
+ *			-1 in other case.
+ */
+static int
+tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int err;
+	struct tpm_chip *chip;
+	struct st19np18_platform_data *platform_data;
+
+	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_probe\n");
+
+	err = 0;
+
+	/* Check I2C platform functionnalities */
+	if (client == NULL) {
+		printk(KERN_INFO "client is NULL. exiting.\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		printk(KERN_INFO "tpm_st19_i2c: client not i2c capable\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
+	if (!chip) {
+		err = -ENODEV;
+		goto end;
+	}
+
+	/*
+	 * ST19 TPM does not support interrupt. chip->vendor.irq is only
+	 * set to a value greater that 0 because status function have no
+	 * sense with this device (TIS register not available)
+	 */
+	chip->vendor.irq = 1;
+
+	platform_data = client->dev.platform_data;
+	pin_infos = platform_data;
+	platform_data->tpm_i2c_buffer[0] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[0] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_answer;
+	}
+	platform_data->tpm_i2c_buffer[1] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[1] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_response;
+	}
+
+	platform_data->client = client;
+
+	/* Register GPIO pin through generic Linux GPIO API */
+	err = gpio_request(platform_data->accept_pin, "accept command");
+	if (err)
+		goto _gpio_init;
+
+	err = gpio_request(platform_data->data_avail_pin, "data available");
+	if (err)
+		goto _gpio_init;
+
+	err = wait_until_good_shape();
+	if (err)
+		goto _gpio_set;
+
+	tpm_get_timeouts(chip);
+
+	/* attach chip datas to client */
+	i2c_set_clientdata(client, chip);
+	pin_infos->bChipF = false;
+
+	printk(KERN_INFO "tpm_st19_i2c: TPM I2C Initialized\n");
+	return 0;
+_gpio_set:
+_gpio_init:
+	if (platform_data) {
+		gpio_free(platform_data->accept_pin);
+		gpio_free(platform_data->data_avail_pin);
+	}
+_tpm_clean_response:
+	tpm_remove_hardware(chip->dev);
+	if (platform_data->tpm_i2c_buffer[1] != NULL) {
+		kfree(platform_data->tpm_i2c_buffer[1]);
+		platform_data->tpm_i2c_buffer[1] = NULL;
+	}
+_tpm_clean_answer:
+	if (platform_data->tpm_i2c_buffer[0] != NULL) {
+		kfree(platform_data->tpm_i2c_buffer[0]);
+		platform_data->tpm_i2c_buffer[0] = NULL;
+	}
+	pin_infos->bChipF = true;
+end:
+	printk(KERN_INFO "tpm_st19_i2c: TPM I2C initialisation fail\n");
+	return err;
+}
+
+/*
+ * tpm_st19_i2c_remove remove the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+		clear_bit(0, &chip->is_open);
+ * @return: 0 in case of success.
+ */
+static __devexit int tpm_st19_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
+	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_remove\n");
+
+	if (pin_infos != NULL) {
+		gpio_free(pin_infos->accept_pin);
+		gpio_free(pin_infos->data_avail_pin);
+
+		/* Check if chip has been previously clean */
+		if (pin_infos->bChipF != true)
+			tpm_remove_hardware(chip->dev);
+		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
+			kfree(pin_infos->tpm_i2c_buffer[1]);
+			pin_infos->tpm_i2c_buffer[1] = NULL;
+		}
+		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
+			kfree(pin_infos->tpm_i2c_buffer[0]);
+			pin_infos->tpm_i2c_buffer[0] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * tpm_st19_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: mesg, the power management message.
+ * @return: 0 in case of success.
+ */
+static int tpm_st19_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int ret = 0;
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_suspend(&client->dev, mesg);
+	return ret;
+}				/* tpm_st19_i2c_suspend() */
+
+/*
+ * tpm_st19_i2c_pm_resume resume the TPM device
+ * This part of the Linux driver should be move in an other part or
+ * environment (bootloader ?)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @return: 0 in case of success.
+ */
+static int tpm_st19_i2c_pm_resume(struct i2c_client *client)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int ret = 0;
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_resume(&client->dev);
+	return ret;
+}				/* tpm_st19_i2c_pm_resume() */
+
+static const struct i2c_device_id tpm_st19_i2c_id[] = {
+	{TPM_DRIVER_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_st19_i2c_id);
+
+static struct i2c_driver tpm_st19_i2c_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = TPM_DRIVER_NAME,
+		   },
+	.probe = tpm_st19_i2c_probe,
+	.remove = tpm_st19_i2c_remove,
+	.resume = tpm_st19_i2c_pm_resume,
+	.suspend = tpm_st19_i2c_pm_suspend,
+	.id_table = tpm_st19_i2c_id
+};
+
+/*
+ * tpm_st19_i2c_init initialize driver
+ * @return: 0 if successful, else non zero value.
+ */
+static int __init tpm_st19_i2c_init(void)
+{
+	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_init\n");
+	return i2c_add_driver(&tpm_st19_i2c_driver);
+}
+
+/*
+ * tpm_st19_i2c_exit The kernel calls this function during unloading the
+ * module or during shut down process
+ */
+static void __exit tpm_st19_i2c_exit(void)
+{
+	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_exit\n");
+	i2c_del_driver(&tpm_st19_i2c_driver);
+}
+
+module_init(tpm_st19_i2c_init);
+module_exit(tpm_st19_i2c_exit);
+
+MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
+MODULE_DESCRIPTION("STM TPM I2C ST19 Driver");
+MODULE_VERSION("1.2.0");
+MODULE_LICENSE("GPL");
diff -uNr linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.h linux-tpm/drivers/char/tpm/tpm_stm_st19_i2c.h
--- linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-tpm/drivers/char/tpm/tpm_stm_st19_i2c.h	2010-09-03 07:09:24.264393476 -0500
@@ -0,0 +1,63 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010  STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: stm_st19_tpm_i2c.h
+ *
+ * @Date: 02/12/2008
+ */
+#ifndef __STM_ST19_TPM_I2C_MAIN_H__
+#define __STM_ST19_TPM_I2C_MAIN_H__
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_DRIVER_NAME		"st19np18"
+
+#define	TPM_BUFSIZE		2048
+
+#define TPM_HEADER_SIZE		10
+#define TPM_I2C_BLOCK_SIZE	0x28
+
+#define TPM_I2C_ORDINAL_LONG	0x0D	/* TPM_ORD_TakeOwnership */
+
+#define TPM_I2C_SHORT	2000	/* 2s */
+#define TICK_GPIO_SPOOLING	2
+#define STARTUP_WAIT_INTERVAL	8 /* 8ms */
+
+/* ioctl commands */
+#define TPMIOC_CANCEL		_IO('T', 0x00)	/* Not supported */
+#define TPMIOC_TRANSMIT		_IO('T', 0x01)
+
+#define DATA_ON			  1	/* data available */
+#define COMMAND_ON		  2	/* accept command */
+
+#endif /* __STM_ST19_TPM_I2C_MAIN_H__ */
diff -uNr linux-2.6.35.4/include/linux/i2c/tpm_stm_st19_i2c.h linux-tpm/include/linux/i2c/tpm_stm_st19_i2c.h
--- linux-2.6.35.4/include/linux/i2c/tpm_stm_st19_i2c.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-tpm/include/linux/i2c/tpm_stm_st19_i2c.h	2010-08-31 12:50:31.774410881 -0500
@@ -0,0 +1,45 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010 STMicroelectronics
+ * Christophe RICARD tpmsupport@st.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @File: stm_st19_tpm_i2c.h
+ *
+ * @Date: 06/15/2008
+ */
+#ifndef __STM_ST19_TPM_I2C_H__
+#define __STM_ST19_TPM_I2C_H__
+
+#include <linux/i2c.h>
+
+#define TPM_DRIVER_NAME         "st19np18"
+#define TPM_I2C_ST19_ADDR_WR	(0x26 >> 1)
+
+struct st19np18_platform_data {
+	int accept_pin;	/* accept command pin */
+	int data_avail_pin;/* data available pin */
+	struct i2c_client *client;
+	bool bChipF;
+	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
+	wait_queue_head_t write_queue;
+};
+
+#endif /* __STM_ST19_TPM_I2C_H__ */

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 0/2] tpm_stm_st19+i2c: use pr_<level> and cleanups
  2010-09-03 19:54                 ` [tpmdd-devel] ST19NP18 I2C driver submission + possible bug found in the last TPM kernel core Christophe Henri RICARD
@ 2010-09-03 23:28                   ` Joe Perches
  2010-09-03 23:29                     ` [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER Joe Perches
  2010-09-03 23:29                     ` [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening Joe Perches
  0 siblings, 2 replies; 10+ messages in thread
From: Joe Perches @ 2010-09-03 23:28 UTC (permalink / raw)
  To: Christophe Henri RICARD
  Cc: Marcel Selhorst, Debora Velarde, Rajiv Andrade, James Morris,
	tpmdd-devel, LKML

There appears to be a missing break in wait_until_good_shape.
Other than that, just some neatening.

Joe Perches (2):
  drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER
  drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening

 drivers/char/tpm/tpm_stm_st19_i2c.c |  215 ++++++++++++++++++----------------
 1 files changed, 114 insertions(+), 101 deletions(-)

-- 
1.7.2.19.g9a302


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER
  2010-09-03 23:28                   ` [PATCH 0/2] tpm_stm_st19+i2c: use pr_<level> and cleanups Joe Perches
@ 2010-09-03 23:29                     ` Joe Perches
  2010-09-14 17:06                       ` Rajiv Andrade
  2010-09-03 23:29                     ` [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening Joe Perches
  1 sibling, 1 reply; 10+ messages in thread
From: Joe Perches @ 2010-09-03 23:29 UTC (permalink / raw)
  To: Christophe Henri RICARD
  Cc: Marcel Selhorst, Debora Velarde, Rajiv Andrade, James Morris,
	tpmdd-devel, LKML

Add FUNC_ENTER to emit pr_info("%s\n", __func_) with #DEBUG

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/char/tpm/tpm_stm_st19_i2c.c |   57 ++++++++++++++++++-----------------
 1 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
index 35307d2..cdf2eb3 100644
--- a/drivers/char/tpm/tpm_stm_st19_i2c.c
+++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
@@ -58,6 +58,8 @@
  * ----------------------------------------------------------------------
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -81,6 +83,12 @@
 
 #include "tpm_stm_st19_i2c.h"
 
+#ifdef DEBUG
+#define FUNC_ENTER()	pr_info("%s\n", __func__)
+#else
+#define FUNC_ENTER()	do {} while (0)
+#endif
+
 /*
  * @Comments: tpm_stm_st19_platform_specific.h deliver shows a platform specific
  * file example.
@@ -260,9 +268,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 	u32 ret = 0, i, size, ordinal, pin = 0;
 	struct i2c_client *client;
 
-#ifdef DEBUG
-	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_send\n");
-#endif
+	FUNC_ENTER();
 
 	if (chip == NULL)
 		return -EBUSY;
@@ -337,7 +343,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
 				    count - i : count);
 		if (ret < 0) {
-			printk(KERN_INFO "tpm_st19_i2c: Failed to send data\n");
+			pr_info("Failed to send data\n");
 			goto end;
 		}
 
@@ -351,16 +357,13 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 							     (TPM_I2C_SHORT));
 
 		if (pin != COMMAND_ON) {
-			printk(KERN_INFO
-			       "tpm_st19_i2c:"
-			       " Failed to read gpio pin (AcceptCmd)\n");
+			pr_info("Failed to read gpio pin (AcceptCmd)\n");
 			ret = -EIO;
 			goto end;
 		}
 	}
 	if (i == 0) {
-		printk(KERN_INFO
-		       "tpm_st19_i2c: Failed to read gpio pin (AcceptCmd)\n");
+		pr_info("Failed to read gpio pin (AcceptCmd)\n");
 		ret = -EIO;
 	}
 end:
@@ -395,9 +398,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
 	int pin = 0;
 	struct i2c_client *client;
 
-#ifdef DEBUG
-	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_recv\n");
-#endif
+	FUNC_ENTER();
 
 	if (chip == NULL)
 		return -EBUSY;
@@ -425,9 +426,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
 				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
 				     size - i : count));
 		if (ret < 0) {
-			printk(KERN_INFO
-			       "tpm_st19_i2c:"
-			       " Failed to read gpio pin (DataAvalaible)\n");
+			pr_info("Failed to read gpio pin (DataAvailable)\n");
 			goto end;
 		}
 
@@ -444,7 +443,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
 					size = count;
 			}
 		} else {
-			printk(KERN_INFO "tpm_st19_i2c: read buffer is NULL\n");
+			pr_info("read buffer is NULL\n");
 			goto end;
 		}
 
@@ -459,9 +458,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
 	}
 
 	if (i == 0) {
-		printk(KERN_INFO
-		       "tpm_st19_i2c: "
-		       "Failed to read gpio pin (DataAvalaible)\n");
+		pr_info("Failed to read gpio pin (DataAvailable)\n");
 		ret = -EIO;
 		goto end;
 	}
@@ -501,7 +498,8 @@ static void tpm_st19_i2c_dummy(struct device *dev)
 static void tpm_st19_i2c_release(struct kobject *kobj)
 {
 	struct tpm_chip *chip;
-	printk(KERN_INFO "tpm_st19_i2c_release\n");
+
+	FUNC_ENTER();
 
 	if (_client != NULL) {
 		chip = (struct tpm_chip *)i2c_get_clientdata(_client);
@@ -614,19 +612,19 @@ tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	struct tpm_chip *chip;
 	struct st19np18_platform_data *platform_data;
 
-	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_probe\n");
+	FUNC_ENTER();
 
 	err = 0;
 
 	/* Check I2C platform functionnalities */
 	if (client == NULL) {
-		printk(KERN_INFO "client is NULL. exiting.\n");
+		pr_info("client is NULL. exiting.\n");
 		err = -ENODEV;
 		goto end;
 	}
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		printk(KERN_INFO "tpm_st19_i2c: client not i2c capable\n");
+		pr_info("client not i2c capable\n");
 		err = -ENODEV;
 		goto end;
 	}
@@ -680,7 +678,7 @@ tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	i2c_set_clientdata(client, chip);
 	pin_infos->bChipF = false;
 
-	printk(KERN_INFO "tpm_st19_i2c: TPM I2C Initialized\n");
+	pr_info("TPM I2C Initialized\n");
 	return 0;
 _gpio_set:
 _gpio_init:
@@ -701,7 +699,7 @@ _tpm_clean_answer:
 	}
 	pin_infos->bChipF = true;
 end:
-	printk(KERN_INFO "tpm_st19_i2c: TPM I2C initialisation fail\n");
+	pr_info("TPM I2C initialisation fail\n");
 	return err;
 }
 
@@ -714,7 +712,8 @@ end:
 static __devexit int tpm_st19_i2c_remove(struct i2c_client *client)
 {
 	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
-	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_remove\n");
+
+	FUNC_ENTER();
 
 	if (pin_infos != NULL) {
 		gpio_free(pin_infos->accept_pin);
@@ -799,7 +798,8 @@ static struct i2c_driver tpm_st19_i2c_driver = {
  */
 static int __init tpm_st19_i2c_init(void)
 {
-	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_init\n");
+	FUNC_ENTER();
+
 	return i2c_add_driver(&tpm_st19_i2c_driver);
 }
 
@@ -809,7 +809,8 @@ static int __init tpm_st19_i2c_init(void)
  */
 static void __exit tpm_st19_i2c_exit(void)
 {
-	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_exit\n");
+	FUNC_ENTER();
+
 	i2c_del_driver(&tpm_st19_i2c_driver);
 }
 
-- 
1.7.2.19.g9a302


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-03 23:28                   ` [PATCH 0/2] tpm_stm_st19+i2c: use pr_<level> and cleanups Joe Perches
  2010-09-03 23:29                     ` [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER Joe Perches
@ 2010-09-03 23:29                     ` Joe Perches
  2010-09-14 17:11                       ` Rajiv Andrade
  1 sibling, 1 reply; 10+ messages in thread
From: Joe Perches @ 2010-09-03 23:29 UTC (permalink / raw)
  To: Christophe Henri RICARD
  Cc: Marcel Selhorst, Debora Velarde, Rajiv Andrade, James Morris,
	tpmdd-devel, LKML

Add missing break in wait_until_good_shape
Use init; while (test) loops not for(init;test;)
Calculate bytes to transfer using if and min_t not multiple ?:
Miscellaneous function whitespace aliging

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
 1 files changed, 85 insertions(+), 73 deletions(-)

diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
index cdf2eb3..4b1ed05 100644
--- a/drivers/char/tpm/tpm_stm_st19_i2c.c
+++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
@@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
 		else if (!signal_pending(current)) {
 			ret = schedule_timeout(time);
 			wait_time += time;
-		} else
+		} else {
 			ret = -ERESTARTSYS;
+			break;
+		}
 	} while (1);
 	finish_wait(&queue, &__wait);
 
@@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
 		else if (wait_time >= timeout)
 			break;
 		else if (!signal_pending(current)) {
-			ret =
-			    schedule_timeout(msecs_to_jiffies
-					     (TICK_GPIO_SPOOLING));
-			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
+			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
+
+			ret = schedule_timeout(time);
+			wait_time += time;
 		} else {
 			ret = -ERESTARTSYS;
 			break;
@@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 	/* sending data (data_avail_pin hight) */
 	/* If data are available, we read the data */
 	init_waitqueue_head(&pin_infos->write_queue);
-	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
-					       tpm_calc_ordinal_duration
-					       (chip, ordinal));
+	pin = wait_event_interruptible_on_gpio(
+			pin_infos->write_queue,
+			tpm_calc_ordinal_duration(chip, ordinal));
 	if (pin < 0) {
 		ret = pin;
 		goto end;
@@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 	client->flags = I2C_M_RD;
 
 	size = TPM_HEADER_SIZE;
-	for (i = 0; pin == DATA_ON && i < size;) {
-		ret = i2c_master_recv(client,
-				      pin_infos->tpm_i2c_buffer[1],
-				      (i == 0) ? TPM_HEADER_SIZE :
-				      count - i > TPM_I2C_BLOCK_SIZE ?
-				      TPM_I2C_BLOCK_SIZE : count - i);
+	i = 0;
+	while (i < size && pin == DATA_ON) {
+		int bytes;
+
+		if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
+
+		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
+				      bytes);
 		if (ret < 0)
 			goto end;
-		if (i == 0)
-			size =
-			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
-		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+		if (i == 0) {
+			size = responseSize(pin_infos->tpm_i2c_buffer[1],
+					    count);
+			i += TPM_HEADER_SIZE;
+		} else
+			i += TPM_I2C_BLOCK_SIZE;
 
 		if (i < size)
-			pin =
-			    wait_event_interruptible_on_gpio(pin_infos->
-							     write_queue,
-							     msecs_to_jiffies
-							     (TPM_I2C_SHORT));
+			pin = wait_event_interruptible_on_gpio(
+					pin_infos->write_queue,
+					msecs_to_jiffies(TPM_I2C_SHORT));
 	}
 
 	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
@@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 	client->flags = 0;
 
 	size = TPM_HEADER_SIZE;
-	for (i = 0; i < size && pin == COMMAND_ON;) {
-		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
-		       (i == 0) ? TPM_HEADER_SIZE : count - i >
-		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
+	i = 0;
+	while (i < size && pin == COMMAND_ON) {
+		int bytes;
+
+		if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
+
+		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
 
 		if (i == 0) {
 			size = responseSize(buf, count);
-			size = (size < count ? size : count);
+			size = size < count ? size : count;
 		}
-		ret =
-		    i2c_master_send(client,
-				    pin_infos->tpm_i2c_buffer[0],
-				    count >= TPM_HEADER_SIZE ? (i ==
-								0) ?
-				    TPM_HEADER_SIZE : count - i >
-				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
-				    count - i : count);
+
+		if (count < TPM_HEADER_SIZE)
+			bytes = count;
+
+		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
+				      bytes);
 		if (ret < 0) {
 			pr_info("Failed to send data\n");
 			goto end;
 		}
 
-		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+		if (i == 0)
+			i += TPM_HEADER_SIZE;
+		else
+			i += TPM_I2C_BLOCK_SIZE;
 		/* Wait for AcceptCmd signal hight */
 		if (i < size)
-			pin =
-			    wait_event_interruptible_on_gpio(pin_infos->
-							     write_queue,
-							     msecs_to_jiffies
-							     (TPM_I2C_SHORT));
+			pin = wait_event_interruptible_on_gpio(
+					pin_infos->write_queue,
+					msecs_to_jiffies(TPM_I2C_SHORT));
 
 		if (pin != COMMAND_ON) {
 			pr_info("Failed to read gpio pin (AcceptCmd)\n");
@@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
 			goto end;
 		}
 	}
+
 	if (i == 0) {
 		pr_info("Failed to read gpio pin (AcceptCmd)\n");
 		ret = -EIO;
@@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
 
 	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
 	init_waitqueue_head(&chip->vendor.read_queue);
-	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
-					       tpm_calc_ordinal_duration
-					       (chip, TPM_I2C_ORDINAL_LONG));
+	pin = wait_event_interruptible_on_gpio(
+			chip->vendor.read_queue,
+			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
 
 	size = TPM_HEADER_SIZE;
-	for (i = 0; i < size && pin == DATA_ON;) {
-		ret =
-		    i2c_master_recv(client,
-				    pin_infos->tpm_i2c_buffer[1],
-				    (count >= TPM_HEADER_SIZE ? i ==
-				     0 ? TPM_HEADER_SIZE : (size - i) >
-				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
-				     size - i : count));
+	i = 0;
+	while (i < size && pin == DATA_ON) {
+		int bytes;
+
+		if (count < TPM_HEADER_SIZE)
+			bytes = count;
+		else if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
+
+		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
+				      bytes);
 		if (ret < 0) {
 			pr_info("Failed to read gpio pin (DataAvailable)\n");
 			goto end;
 		}
 
-		if (buf != NULL) {
-			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
-			       (count >= TPM_HEADER_SIZE ? i == 0 ?
-				TPM_HEADER_SIZE : (size - i) >
-				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
-				i : count));
-
-			if (i == 0) {
-				size = responseSize(buf, size);
-				if (size > count)
-					size = count;
-			}
-		} else {
+		if (!buf) {
 			pr_info("read buffer is NULL\n");
 			goto end;
 		}
 
-		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
+		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
+
+		if (i == 0) {
+			size = responseSize(buf, size);
+			if (size > count)
+				size = count;
+			i += TPM_HEADER_SIZE;
+		} else
+			i += TPM_I2C_BLOCK_SIZE;
 
 		if (i < size)
-			pin =
-			    wait_event_interruptible_on_gpio(chip->vendor.
-							     read_queue,
-							     msecs_to_jiffies
-							     (TPM_I2C_SHORT));
+			pin = wait_event_interruptible_on_gpio(
+					chip->vendor.read_queue,
+					msecs_to_jiffies(TPM_I2C_SHORT));
 	}
 
 	if (i == 0) {
@@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
 		return -ENOSYS;
 	case TPMIOC_TRANSMIT:
 		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
-		    (const char *)arg, TPM_HEADER_SIZE))
+				   (const char *)arg, TPM_HEADER_SIZE))
 			return -EFAULT;
 		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
 				      TPM_HEADER_SIZE);
-- 
1.7.2.19.g9a302


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER
  2010-09-03 23:29                     ` [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER Joe Perches
@ 2010-09-14 17:06                       ` Rajiv Andrade
  0 siblings, 0 replies; 10+ messages in thread
From: Rajiv Andrade @ 2010-09-14 17:06 UTC (permalink / raw)
  To: Joe Perches
  Cc: Christophe Henri RICARD, Marcel Selhorst, Debora Velarde,
	James Morris, tpmdd-devel, LKML

Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>

On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
> Add FUNC_ENTER to emit pr_info("%s\n", __func_) with #DEBUG
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
>  drivers/char/tpm/tpm_stm_st19_i2c.c |   57 ++++++++++++++++++-----------------
>  1 files changed, 29 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
> index 35307d2..cdf2eb3 100644
> --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
> +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
> @@ -58,6 +58,8 @@
>   * ----------------------------------------------------------------------
>   */
> 
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
>  #include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/delay.h>
> @@ -81,6 +83,12 @@
> 
>  #include "tpm_stm_st19_i2c.h"
> 
> +#ifdef DEBUG
> +#define FUNC_ENTER()	pr_info("%s\n", __func__)
> +#else
> +#define FUNC_ENTER()	do {} while (0)
> +#endif
> +
>  /*
>   * @Comments: tpm_stm_st19_platform_specific.h deliver shows a platform specific
>   * file example.
> @@ -260,9 +268,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	u32 ret = 0, i, size, ordinal, pin = 0;
>  	struct i2c_client *client;
> 
> -#ifdef DEBUG
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_send\n");
> -#endif
> +	FUNC_ENTER();
> 
>  	if (chip == NULL)
>  		return -EBUSY;
> @@ -337,7 +343,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
>  				    count - i : count);
>  		if (ret < 0) {
> -			printk(KERN_INFO "tpm_st19_i2c: Failed to send data\n");
> +			pr_info("Failed to send data\n");
>  			goto end;
>  		}
> 
> @@ -351,16 +357,13 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  							     (TPM_I2C_SHORT));
> 
>  		if (pin != COMMAND_ON) {
> -			printk(KERN_INFO
> -			       "tpm_st19_i2c:"
> -			       " Failed to read gpio pin (AcceptCmd)\n");
> +			pr_info("Failed to read gpio pin (AcceptCmd)\n");
>  			ret = -EIO;
>  			goto end;
>  		}
>  	}
>  	if (i == 0) {
> -		printk(KERN_INFO
> -		       "tpm_st19_i2c: Failed to read gpio pin (AcceptCmd)\n");
> +		pr_info("Failed to read gpio pin (AcceptCmd)\n");
>  		ret = -EIO;
>  	}
>  end:
> @@ -395,9 +398,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
>  	int pin = 0;
>  	struct i2c_client *client;
> 
> -#ifdef DEBUG
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_stm_i2c_recv\n");
> -#endif
> +	FUNC_ENTER();
> 
>  	if (chip == NULL)
>  		return -EBUSY;
> @@ -425,9 +426,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
>  				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
>  				     size - i : count));
>  		if (ret < 0) {
> -			printk(KERN_INFO
> -			       "tpm_st19_i2c:"
> -			       " Failed to read gpio pin (DataAvalaible)\n");
> +			pr_info("Failed to read gpio pin (DataAvailable)\n");
>  			goto end;
>  		}
> 
> @@ -444,7 +443,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
>  					size = count;
>  			}
>  		} else {
> -			printk(KERN_INFO "tpm_st19_i2c: read buffer is NULL\n");
> +			pr_info("read buffer is NULL\n");
>  			goto end;
>  		}
> 
> @@ -459,9 +458,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
>  	}
> 
>  	if (i == 0) {
> -		printk(KERN_INFO
> -		       "tpm_st19_i2c: "
> -		       "Failed to read gpio pin (DataAvalaible)\n");
> +		pr_info("Failed to read gpio pin (DataAvailable)\n");
>  		ret = -EIO;
>  		goto end;
>  	}
> @@ -501,7 +498,8 @@ static void tpm_st19_i2c_dummy(struct device *dev)
>  static void tpm_st19_i2c_release(struct kobject *kobj)
>  {
>  	struct tpm_chip *chip;
> -	printk(KERN_INFO "tpm_st19_i2c_release\n");
> +
> +	FUNC_ENTER();
> 
>  	if (_client != NULL) {
>  		chip = (struct tpm_chip *)i2c_get_clientdata(_client);
> @@ -614,19 +612,19 @@ tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	struct tpm_chip *chip;
>  	struct st19np18_platform_data *platform_data;
> 
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_probe\n");
> +	FUNC_ENTER();
> 
>  	err = 0;
> 
>  	/* Check I2C platform functionnalities */
>  	if (client == NULL) {
> -		printk(KERN_INFO "client is NULL. exiting.\n");
> +		pr_info("client is NULL. exiting.\n");
>  		err = -ENODEV;
>  		goto end;
>  	}
> 
>  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> -		printk(KERN_INFO "tpm_st19_i2c: client not i2c capable\n");
> +		pr_info("client not i2c capable\n");
>  		err = -ENODEV;
>  		goto end;
>  	}
> @@ -680,7 +678,7 @@ tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	i2c_set_clientdata(client, chip);
>  	pin_infos->bChipF = false;
> 
> -	printk(KERN_INFO "tpm_st19_i2c: TPM I2C Initialized\n");
> +	pr_info("TPM I2C Initialized\n");
>  	return 0;
>  _gpio_set:
>  _gpio_init:
> @@ -701,7 +699,7 @@ _tpm_clean_answer:
>  	}
>  	pin_infos->bChipF = true;
>  end:
> -	printk(KERN_INFO "tpm_st19_i2c: TPM I2C initialisation fail\n");
> +	pr_info("TPM I2C initialisation fail\n");
>  	return err;
>  }
> 
> @@ -714,7 +712,8 @@ end:
>  static __devexit int tpm_st19_i2c_remove(struct i2c_client *client)
>  {
>  	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_remove\n");
> +
> +	FUNC_ENTER();
> 
>  	if (pin_infos != NULL) {
>  		gpio_free(pin_infos->accept_pin);
> @@ -799,7 +798,8 @@ static struct i2c_driver tpm_st19_i2c_driver = {
>   */
>  static int __init tpm_st19_i2c_init(void)
>  {
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_init\n");
> +	FUNC_ENTER();
> +
>  	return i2c_add_driver(&tpm_st19_i2c_driver);
>  }
> 
> @@ -809,7 +809,8 @@ static int __init tpm_st19_i2c_init(void)
>   */
>  static void __exit tpm_st19_i2c_exit(void)
>  {
> -	printk(KERN_INFO "tpm_st19_i2c: tpm_st19_i2c_exit\n");
> +	FUNC_ENTER();
> +
>  	i2c_del_driver(&tpm_st19_i2c_driver);
>  }
> 



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-03 23:29                     ` [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening Joe Perches
@ 2010-09-14 17:11                       ` Rajiv Andrade
  2010-09-17 15:53                         ` Christophe Henri RICARD
  0 siblings, 1 reply; 10+ messages in thread
From: Rajiv Andrade @ 2010-09-14 17:11 UTC (permalink / raw)
  To: Joe Perches
  Cc: Christophe Henri RICARD, Marcel Selhorst, Debora Velarde,
	James Morris, tpmdd-devel, LKML

Chris, did you have the chance to test it against this specific TPM?
Despite this, the patch looks pretty good, thanks Joe.

Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>

On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
> Add missing break in wait_until_good_shape
> Use init; while (test) loops not for(init;test;)
> Calculate bytes to transfer using if and min_t not multiple ?:
> Miscellaneous function whitespace aliging
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
>  drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
>  1 files changed, 85 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
> index cdf2eb3..4b1ed05 100644
> --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
> +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
> @@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
>  		else if (!signal_pending(current)) {
>  			ret = schedule_timeout(time);
>  			wait_time += time;
> -		} else
> +		} else {
>  			ret = -ERESTARTSYS;
> +			break;
> +		}
>  	} while (1);
>  	finish_wait(&queue, &__wait);
> 
> @@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
>  		else if (wait_time >= timeout)
>  			break;
>  		else if (!signal_pending(current)) {
> -			ret =
> -			    schedule_timeout(msecs_to_jiffies
> -					     (TICK_GPIO_SPOOLING));
> -			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
> +			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
> +
> +			ret = schedule_timeout(time);
> +			wait_time += time;
>  		} else {
>  			ret = -ERESTARTSYS;
>  			break;
> @@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	/* sending data (data_avail_pin hight) */
>  	/* If data are available, we read the data */
>  	init_waitqueue_head(&pin_infos->write_queue);
> -	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> -					       tpm_calc_ordinal_duration
> -					       (chip, ordinal));
> +	pin = wait_event_interruptible_on_gpio(
> +			pin_infos->write_queue,
> +			tpm_calc_ordinal_duration(chip, ordinal));
>  	if (pin < 0) {
>  		ret = pin;
>  		goto end;
> @@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	client->flags = I2C_M_RD;
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; pin == DATA_ON && i < size;) {
> -		ret = i2c_master_recv(client,
> -				      pin_infos->tpm_i2c_buffer[1],
> -				      (i == 0) ? TPM_HEADER_SIZE :
> -				      count - i > TPM_I2C_BLOCK_SIZE ?
> -				      TPM_I2C_BLOCK_SIZE : count - i);
> +	i = 0;
> +	while (i < size && pin == DATA_ON) {
> +		int bytes;
> +
> +		if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> +
> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> +				      bytes);
>  		if (ret < 0)
>  			goto end;
> -		if (i == 0)
> -			size =
> -			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		if (i == 0) {
> +			size = responseSize(pin_infos->tpm_i2c_buffer[1],
> +					    count);
> +			i += TPM_HEADER_SIZE;
> +		} else
> +			i += TPM_I2C_BLOCK_SIZE;
> 
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(pin_infos->
> -							     write_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					pin_infos->write_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
>  	}
> 
>  	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> @@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	client->flags = 0;
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; i < size && pin == COMMAND_ON;) {
> -		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
> -		       (i == 0) ? TPM_HEADER_SIZE : count - i >
> -		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
> +	i = 0;
> +	while (i < size && pin == COMMAND_ON) {
> +		int bytes;
> +
> +		if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> +
> +		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
> 
>  		if (i == 0) {
>  			size = responseSize(buf, count);
> -			size = (size < count ? size : count);
> +			size = size < count ? size : count;
>  		}
> -		ret =
> -		    i2c_master_send(client,
> -				    pin_infos->tpm_i2c_buffer[0],
> -				    count >= TPM_HEADER_SIZE ? (i ==
> -								0) ?
> -				    TPM_HEADER_SIZE : count - i >
> -				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> -				    count - i : count);
> +
> +		if (count < TPM_HEADER_SIZE)
> +			bytes = count;
> +
> +		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
> +				      bytes);
>  		if (ret < 0) {
>  			pr_info("Failed to send data\n");
>  			goto end;
>  		}
> 
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		if (i == 0)
> +			i += TPM_HEADER_SIZE;
> +		else
> +			i += TPM_I2C_BLOCK_SIZE;
>  		/* Wait for AcceptCmd signal hight */
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(pin_infos->
> -							     write_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					pin_infos->write_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
> 
>  		if (pin != COMMAND_ON) {
>  			pr_info("Failed to read gpio pin (AcceptCmd)\n");
> @@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  			goto end;
>  		}
>  	}
> +
>  	if (i == 0) {
>  		pr_info("Failed to read gpio pin (AcceptCmd)\n");
>  		ret = -EIO;
> @@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
> 
>  	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
>  	init_waitqueue_head(&chip->vendor.read_queue);
> -	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
> -					       tpm_calc_ordinal_duration
> -					       (chip, TPM_I2C_ORDINAL_LONG));
> +	pin = wait_event_interruptible_on_gpio(
> +			chip->vendor.read_queue,
> +			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; i < size && pin == DATA_ON;) {
> -		ret =
> -		    i2c_master_recv(client,
> -				    pin_infos->tpm_i2c_buffer[1],
> -				    (count >= TPM_HEADER_SIZE ? i ==
> -				     0 ? TPM_HEADER_SIZE : (size - i) >
> -				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> -				     size - i : count));
> +	i = 0;
> +	while (i < size && pin == DATA_ON) {
> +		int bytes;
> +
> +		if (count < TPM_HEADER_SIZE)
> +			bytes = count;
> +		else if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
> +
> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> +				      bytes);
>  		if (ret < 0) {
>  			pr_info("Failed to read gpio pin (DataAvailable)\n");
>  			goto end;
>  		}
> 
> -		if (buf != NULL) {
> -			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
> -			       (count >= TPM_HEADER_SIZE ? i == 0 ?
> -				TPM_HEADER_SIZE : (size - i) >
> -				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
> -				i : count));
> -
> -			if (i == 0) {
> -				size = responseSize(buf, size);
> -				if (size > count)
> -					size = count;
> -			}
> -		} else {
> +		if (!buf) {
>  			pr_info("read buffer is NULL\n");
>  			goto end;
>  		}
> 
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
> +
> +		if (i == 0) {
> +			size = responseSize(buf, size);
> +			if (size > count)
> +				size = count;
> +			i += TPM_HEADER_SIZE;
> +		} else
> +			i += TPM_I2C_BLOCK_SIZE;
> 
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(chip->vendor.
> -							     read_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					chip->vendor.read_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
>  	}
> 
>  	if (i == 0) {
> @@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
>  		return -ENOSYS;
>  	case TPMIOC_TRANSMIT:
>  		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
> -		    (const char *)arg, TPM_HEADER_SIZE))
> +				   (const char *)arg, TPM_HEADER_SIZE))
>  			return -EFAULT;
>  		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
>  				      TPM_HEADER_SIZE);



^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-14 17:11                       ` Rajiv Andrade
@ 2010-09-17 15:53                         ` Christophe Henri RICARD
  2010-09-23 23:38                           ` James Morris
  0 siblings, 1 reply; 10+ messages in thread
From: Christophe Henri RICARD @ 2010-09-17 15:53 UTC (permalink / raw)
  To: Rajiv Andrade, Joe Perches
  Cc: Marcel Selhorst, Debora Velarde, James Morris, tpmdd-devel, LKML

[-- Attachment #1: Type: text/plain, Size: 9274 bytes --]

Rajiv,
Please find in attached file a full patch (driver + Joe Perches observations/patches + comments update).
This patch has been tested.

Thanks
Christophe

-----Original Message-----
From: Rajiv Andrade [mailto:srajiv@linux.vnet.ibm.com] 
Sent: Tuesday, September 14, 2010 12:11 PM
To: Joe Perches
Cc: Christophe Henri RICARD; Marcel Selhorst; Debora Velarde; James Morris; tpmdd-devel@lists.sourceforge.net; LKML
Subject: Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening

Chris, did you have the chance to test it against this specific TPM?
Despite this, the patch looks pretty good, thanks Joe.

Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>

On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
> Add missing break in wait_until_good_shape
> Use init; while (test) loops not for(init;test;)
> Calculate bytes to transfer using if and min_t not multiple ?:
> Miscellaneous function whitespace aliging
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
>  drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
>  1 files changed, 85 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
> index cdf2eb3..4b1ed05 100644
> --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
> +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
> @@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
>  		else if (!signal_pending(current)) {
>  			ret = schedule_timeout(time);
>  			wait_time += time;
> -		} else
> +		} else {
>  			ret = -ERESTARTSYS;
> +			break;
> +		}
>  	} while (1);
>  	finish_wait(&queue, &__wait);
> 
> @@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
>  		else if (wait_time >= timeout)
>  			break;
>  		else if (!signal_pending(current)) {
> -			ret =
> -			    schedule_timeout(msecs_to_jiffies
> -					     (TICK_GPIO_SPOOLING));
> -			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
> +			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
> +
> +			ret = schedule_timeout(time);
> +			wait_time += time;
>  		} else {
>  			ret = -ERESTARTSYS;
>  			break;
> @@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	/* sending data (data_avail_pin hight) */
>  	/* If data are available, we read the data */
>  	init_waitqueue_head(&pin_infos->write_queue);
> -	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> -					       tpm_calc_ordinal_duration
> -					       (chip, ordinal));
> +	pin = wait_event_interruptible_on_gpio(
> +			pin_infos->write_queue,
> +			tpm_calc_ordinal_duration(chip, ordinal));
>  	if (pin < 0) {
>  		ret = pin;
>  		goto end;
> @@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	client->flags = I2C_M_RD;
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; pin == DATA_ON && i < size;) {
> -		ret = i2c_master_recv(client,
> -				      pin_infos->tpm_i2c_buffer[1],
> -				      (i == 0) ? TPM_HEADER_SIZE :
> -				      count - i > TPM_I2C_BLOCK_SIZE ?
> -				      TPM_I2C_BLOCK_SIZE : count - i);
> +	i = 0;
> +	while (i < size && pin == DATA_ON) {
> +		int bytes;
> +
> +		if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> +
> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> +				      bytes);
>  		if (ret < 0)
>  			goto end;
> -		if (i == 0)
> -			size =
> -			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		if (i == 0) {
> +			size = responseSize(pin_infos->tpm_i2c_buffer[1],
> +					    count);
> +			i += TPM_HEADER_SIZE;
> +		} else
> +			i += TPM_I2C_BLOCK_SIZE;
> 
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(pin_infos->
> -							     write_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					pin_infos->write_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
>  	}
> 
>  	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> @@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  	client->flags = 0;
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; i < size && pin == COMMAND_ON;) {
> -		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
> -		       (i == 0) ? TPM_HEADER_SIZE : count - i >
> -		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
> +	i = 0;
> +	while (i < size && pin == COMMAND_ON) {
> +		int bytes;
> +
> +		if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> +
> +		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
> 
>  		if (i == 0) {
>  			size = responseSize(buf, count);
> -			size = (size < count ? size : count);
> +			size = size < count ? size : count;
>  		}
> -		ret =
> -		    i2c_master_send(client,
> -				    pin_infos->tpm_i2c_buffer[0],
> -				    count >= TPM_HEADER_SIZE ? (i ==
> -								0) ?
> -				    TPM_HEADER_SIZE : count - i >
> -				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> -				    count - i : count);
> +
> +		if (count < TPM_HEADER_SIZE)
> +			bytes = count;
> +
> +		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
> +				      bytes);
>  		if (ret < 0) {
>  			pr_info("Failed to send data\n");
>  			goto end;
>  		}
> 
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		if (i == 0)
> +			i += TPM_HEADER_SIZE;
> +		else
> +			i += TPM_I2C_BLOCK_SIZE;
>  		/* Wait for AcceptCmd signal hight */
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(pin_infos->
> -							     write_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					pin_infos->write_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
> 
>  		if (pin != COMMAND_ON) {
>  			pr_info("Failed to read gpio pin (AcceptCmd)\n");
> @@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>  			goto end;
>  		}
>  	}
> +
>  	if (i == 0) {
>  		pr_info("Failed to read gpio pin (AcceptCmd)\n");
>  		ret = -EIO;
> @@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
> 
>  	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
>  	init_waitqueue_head(&chip->vendor.read_queue);
> -	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
> -					       tpm_calc_ordinal_duration
> -					       (chip, TPM_I2C_ORDINAL_LONG));
> +	pin = wait_event_interruptible_on_gpio(
> +			chip->vendor.read_queue,
> +			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
> 
>  	size = TPM_HEADER_SIZE;
> -	for (i = 0; i < size && pin == DATA_ON;) {
> -		ret =
> -		    i2c_master_recv(client,
> -				    pin_infos->tpm_i2c_buffer[1],
> -				    (count >= TPM_HEADER_SIZE ? i ==
> -				     0 ? TPM_HEADER_SIZE : (size - i) >
> -				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> -				     size - i : count));
> +	i = 0;
> +	while (i < size && pin == DATA_ON) {
> +		int bytes;
> +
> +		if (count < TPM_HEADER_SIZE)
> +			bytes = count;
> +		else if (i == 0)
> +			bytes = TPM_HEADER_SIZE;
> +		else
> +			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
> +
> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> +				      bytes);
>  		if (ret < 0) {
>  			pr_info("Failed to read gpio pin (DataAvailable)\n");
>  			goto end;
>  		}
> 
> -		if (buf != NULL) {
> -			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
> -			       (count >= TPM_HEADER_SIZE ? i == 0 ?
> -				TPM_HEADER_SIZE : (size - i) >
> -				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
> -				i : count));
> -
> -			if (i == 0) {
> -				size = responseSize(buf, size);
> -				if (size > count)
> -					size = count;
> -			}
> -		} else {
> +		if (!buf) {
>  			pr_info("read buffer is NULL\n");
>  			goto end;
>  		}
> 
> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> +		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
> +
> +		if (i == 0) {
> +			size = responseSize(buf, size);
> +			if (size > count)
> +				size = count;
> +			i += TPM_HEADER_SIZE;
> +		} else
> +			i += TPM_I2C_BLOCK_SIZE;
> 
>  		if (i < size)
> -			pin =
> -			    wait_event_interruptible_on_gpio(chip->vendor.
> -							     read_queue,
> -							     msecs_to_jiffies
> -							     (TPM_I2C_SHORT));
> +			pin = wait_event_interruptible_on_gpio(
> +					chip->vendor.read_queue,
> +					msecs_to_jiffies(TPM_I2C_SHORT));
>  	}
> 
>  	if (i == 0) {
> @@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
>  		return -ENOSYS;
>  	case TPMIOC_TRANSMIT:
>  		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
> -		    (const char *)arg, TPM_HEADER_SIZE))
> +				   (const char *)arg, TPM_HEADER_SIZE))
>  			return -EFAULT;
>  		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
>  				      TPM_HEADER_SIZE);



[-- Attachment #2: tpm_stm_st19_i2c_tested.patch --]
[-- Type: application/octet-stream, Size: 35573 bytes --]

diff -uNr linux-2.6.35.4/Documentation/tpm/tpm_stm_st19_i2c.txt linux-st19i2c/Documentation/tpm/tpm_stm_st19_i2c.txt
--- linux-2.6.35.4/Documentation/tpm/tpm_stm_st19_i2c.txt	1969-12-31 18:00:00.000000000 -0600
+++ linux-st19i2c/Documentation/tpm/tpm_stm_st19_i2c.txt	2010-09-17 09:42:46.296572075 -0500
@@ -0,0 +1,170 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010 STMicroelectronics
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ */
+
+PURPOSE OF THE DOCUMENT
+------------------------
+This document is intend to describe how to install the TPM driver for
+TPM ST19NP18 using I2C protocols.
+
+
+PLATFORM USED FOR TESTING
+--------------------------
+During the development, several embedded platforms running ARM CPU have been
+used.
+Validated platforms listing:
+- TI Beagleboard
+- STMicroelectronics Spear 300
+- STMicroelectronics Spear 600
+
+REQUIREMENTS
+-------------
+Software
+=========
+This TPM driver could be install under a kernel which implement at least the
+following features:
+- Linux GENERIC_GPIO programming interfaces.
+- I2C new style programming interface base (with probe & remove functions)
+- 1 I2C adapter (I2C Linux controller driver) or use of I2C_GPIO driver for I2C
+bitbanging.
+
+
+Hardware
+=========
+To run a TPM the platform needs  at least:
+- 2 Power supply (3.3V).
+- 1 I2C controller or 2 GPIOs used for SDA & SCL (I2C bit bang method).
+- 2 GPIOs for signals accept_command & data_available.
+
+TPM I2C speed is 100Khz (Maximum)
+
+All TPM signals work at 3.3V
+
+HOW TO INSTALL
+---------------
+Platform installation file
+===========================
+(N.B: platform file in arch/<processor_type>/mach-<platform-name>/
+
+
+1 - Software integration
+=========================
+<processor_type> could be: alpha, arm, avr32, blackfin, cris, frv, h8300, ia64,
+m32r, m68k, m68knommu, parisc, powerpc, s390, sh, sparc, sparc64, um, x86,
+xtensa...
+<platform-name> corresponds to your platform
+
+In the file where the machine_init() function exists, the developer must
+declare:
+- 1 struct st19np18_platform_data to provide which gpio the driver will use.
+	* The accept_pin and data_avail_pin gpio are configured as input only.
+	* This gpio management is under the platform developer responsability.
+
+Finally in the machine_init() function provided in the same file, the developer
+should use the well known function i2c_register_board_info() from the I2C Linux
+API Core.
+
+2- Hardware integration
+========================
+- ST recommends connecting VPS1 and VPS2 to board power supply and at least two
+GNDs (on each side of TSSOP28 package). (See datasheet for further informations)
+
+- As the ST19NP18 has no internal pull up, ST recommands to had:
+  * 2 external pull up on SDA & SCL signals (RpSDA/RpSCL) with value according
+to the abacus on page 40 or the "I2C Bus specification", version 2.1 January
+2000.
+
+
+Platform integration advises
+=============================
+
+For power management purposes, the kernel will send a TPM_SaveState command in the
+suspend tpm driver function.
+If the platform generate a TPM Init event on wakeup, the first TPM command that should
+be executed before the Linux kernel is back (resume function execution) is
+TPM_Startup(ST_STATE).
+
+Here is an example with beagleboard:
+====================================
+Depending on the platform, the developper should specify in
+the platform init file the following informations:
+- The platform gpio's used to managed the tpm's accept_pin/data_avail_pin
+(in a struct st19np18_platform_data declaration).
+- The TPM I2C 7 bits address (TPM_I2C_ST19_ADDR_WR) (in a struct i2c_board_info).
+
+Then the developper should add  the TPM slave device to the good i2c adapter with the
+i2c_register_board_info function (Assuming that the gpio and the i2c bus are well configured).
+
+Note: For the beagleboard configure your kernel with the following option: CONFIG_OMAP_MUX=y
+
+file arch\arm\mach-omap2\board-omap3beagle.c
+add the following:
+-----------------------------------------------------------------------
+
+static struct st19np18_platform_data tpm_data = {
+        .accept_pin = 135,
+        .data_avail_pin = 143,
+};
+
+static struct i2c_board_info __initdata tpm_st19_i2c_board_info[] = {
+        {
+         I2C_BOARD_INFO(TPM_DRIVER_NAME, TPM_I2C_ST19_ADDR_WR),
+         .platform_data = &tpm_data,
+         },
+};
+
+------------------------------------------------------------------------
+Then complete the beagleboard init to be like that:
+------------------------------------------------------------------------
+static void __init omap3_beagle_init(void)
+{
+        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+        omap3_beagle_i2c_init();
+        platform_add_devices(omap3_beagle_devices,
+                        ARRAY_SIZE(omap3_beagle_devices));
+        omap_serial_init();
+
+        omap_mux_init_gpio(170, OMAP_PIN_INPUT);
+        gpio_request(170, "DVI_nPD");
+        /* REVISIT leave DVI powered down until it's needed ... */
+        gpio_direction_output(170, true);
+
+        usb_musb_init(&musb_board_data);
+        usb_ehci_init(&ehci_pdata);
+        omap3beagle_flash_init();
+
+        beagle_display_init();
+
+        /* Ensure SDRC pins are mux'd for self-refresh */
+        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+        omap_mux_init_gpio(((struct st19np18_platform_data *)
+                           tpm_st19_i2c_board_info[0].platform_data)->data_avail_pin,
+                           OMAP_PIN_INPUT);
+	omap_mux_init_gpio(((struct st19np18_platform_data *)
+                           tpm_st19_i2c_board_info[0].platform_data)->accept_pin,
+                           OMAP_PIN_INPUT);
+
+	i2c_register_board_info(3, tpm_st19_i2c_board_info, ARRAY_SIZE(tpm_st19_i2c_board_info));
+}
diff -uNr linux-2.6.35.4/drivers/char/tpm/Kconfig linux-st19i2c/drivers/char/tpm/Kconfig
--- linux-2.6.35.4/drivers/char/tpm/Kconfig	2010-08-26 18:47:12.000000000 -0500
+++ linux-st19i2c/drivers/char/tpm/Kconfig	2010-09-16 14:15:16.685780128 -0500
@@ -60,4 +60,13 @@
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.prosec.rub.de/tpm
 
+config TCG_ST19_I2C
+        tristate "STMicroelectronics ST19 I2C TPM"
+        depends on I2C
+        depends on GPIOLIB
+        ---help---
+        If you have a TPM security chip from STMicroelectronics working with
+        an I2C bus say Yes and it will be accessible from within Linux.
+        To compile this driver as a module, choose M here; the module will be
+        called tpm_stm_st19_i2c.
 endif # TCG_TPM
diff -uNr linux-2.6.35.4/drivers/char/tpm/Makefile linux-st19i2c/drivers/char/tpm/Makefile
--- linux-2.6.35.4/drivers/char/tpm/Makefile	2010-08-26 18:47:12.000000000 -0500
+++ linux-st19i2c/drivers/char/tpm/Makefile	2010-09-17 10:17:24.076572385 -0500
@@ -9,3 +9,4 @@
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_ST19_I2C) += tpm_stm_st19_i2c.o
diff -uNr linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.c linux-st19i2c/drivers/char/tpm/tpm_stm_st19_i2c.c
--- linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-st19i2c/drivers/char/tpm/tpm_stm_st19_i2c.c	2010-09-17 09:49:44.739668841 -0500
@@ -0,0 +1,800 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010  STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: tpm_stm_st19_i2c.c
+ *
+ * @Synopsis:
+ * ----------------------------------------------------------------------
+ *	02/12/2008
+ *	- Stand alone implementation (without any TPM api)
+ * ----------------------------------------------------------------------
+ *	03/02/2010
+ *	- Power management (suspend and resume functions)
+ *	implementation
+ * ----------------------------------------------------------------------
+ *	03/19/2010
+ *	- Use of the linux kernel TPM api --> driver/char/tpm
+ * ----------------------------------------------------------------------
+ *	05/26/2010
+ *	- Update code for code submission and bug fixes:
+ *	- Comments spelling fixes
+ *	- Lindent script execution
+ *	- checkpatch.pl script execution
+ *	- fix syslog error when loaded as a module:
+ *	 "release() function missing and must be fixed"
+ *	- name files change from
+ *	  stm_st19_tpm_i2c to tpm_stm_st19_i2c
+ * ----------------------------------------------------------------------
+ *	06/15/2010
+ *	- Update for new tpm core device.
+ *	num_opens --> is_open
+ * ----------------------------------------------------------------------
+ *	07/08/2010
+ *	- Update probe, resume suspend functions
+ *	- Fix issue suspend buffer and work around related to the
+ *	chip->data_buffer not allocated.
+ * ----------------------------------------------------------------------
+ *	09/03/2010
+ *	- Review under LKLM
+ *	- Patches from Joe Perches after review which fix some break and
+ *	some neatings.
+ * ----------------------------------------------------------------------
+ *	09/16/2010
+ *	- Remove unaccurate comment.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/tpm_stm_st19_i2c.h>
+
+#include "tpm.h"
+
+#include "tpm_stm_st19_i2c.h"
+
+#ifdef DEBUG
+#define FUNC_ENTER() pr_info("%s\n", __func__)
+#else
+#define FUNC_ENTER() do {} while (0)
+#endif
+
+static struct st19np18_platform_data *pin_infos;
+
+/*
+ * gpio_readpin is a wrapper to read a gpio value.
+ * Use generic gpio APIs
+ * @param: pin_id, the pin identifier where the value will be read.
+ * @return: the gpio value (should be 0 or 1) or negative errno
+ */
+static int gpio_readpin(int pin_id)
+{
+	int ret;
+	ret = gpio_direction_input(pin_id);
+	if (ret == 0)
+		return gpio_get_value(pin_id);
+	return ret;
+}
+
+/*
+ * gpio_writepin is a wrapper to write a gpio value.
+ * Use generic gpio APIs.
+ * @param: pin_id, the pin identifier where the value will be wrote.
+ * @param: value, the value that will be written.
+ * @return: 0 in case of success
+ */
+#ifdef DEBUG
+static int gpio_writepin(int pin_id, int value)
+{
+	int ret;
+	ret = gpio_direction_output(pin_id, value);
+
+	if (ret == 0)
+		gpio_set_value(pin_id, value);
+	return ret;
+}
+#endif
+
+static int wait_until_good_shape(void)
+{
+	int state_data = 0;
+	int state_command = 0;
+	int timeout = msecs_to_jiffies(STARTUP_WAIT_INTERVAL);
+	int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
+	int ret = 0;
+	wait_queue_head_t queue;
+
+	int wait_time = 0;
+	DEFINE_WAIT(__wait);
+	init_waitqueue_head(&queue);
+
+	do {
+		prepare_to_wait(&queue, &__wait, TASK_INTERRUPTIBLE);
+		state_data = gpio_readpin(pin_infos->data_avail_pin);
+		state_command = gpio_readpin(pin_infos->accept_pin);
+
+		if (state_data == 0 && state_command > 0)
+			return 0;
+		else if (wait_time >= timeout)
+			return -EIO;
+		else if (!signal_pending(current)) {
+			ret = schedule_timeout(time);
+			wait_time += time;
+		} else {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	} while (1);
+	finish_wait(&queue, &__wait);
+
+	return ret;
+}
+
+/*
+ * wait_event_interruptible_on_gpio is a function that poll on
+ * GPIO dataavailable and GPIO acceptcommand
+ * @param: queue, the queue where the work will be stored
+ * @param: timeout, maximal pooling time.
+ * @return: DATA_ON in case of data_available pin goes high (logical value 1).
+ * COMMAND_ON in case of accept_command pin goes high (logical value 1).
+ * -EIO in case of data_available & accept_command pin goes high
+ *		(logical value 1).
+ * -EPERM in case of data_available & accept_command pin still low
+ *		(logical value 0).
+ */
+static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
+					    int timeout)
+{
+	int state_data = 0;
+	int state_command = 0;
+	int ret = msecs_to_jiffies(TICK_GPIO_SPOOLING);
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int long_timeout =
+	    tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG);
+	int wait_time = 0;
+	DEFINE_WAIT(__wait);
+
+	if (timeout > long_timeout)
+		timeout = long_timeout;
+
+	do {
+		prepare_to_wait(&queue, &__wait, TASK_INTERRUPTIBLE);
+		state_data = gpio_readpin(pin_infos->data_avail_pin);
+		state_command = gpio_readpin(pin_infos->accept_pin);
+
+		if (state_data > 0 || state_command > 0)
+			break;
+		else if (wait_time >= timeout)
+			break;
+		else if (!signal_pending(current)) {
+			ret =
+			    schedule_timeout(msecs_to_jiffies
+					     (TICK_GPIO_SPOOLING));
+			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
+		} else {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	} while (1);
+	finish_wait(&queue, &__wait);
+
+	return (state_data && state_command) ? -EIO : state_data ? DATA_ON :
+	    state_command ? COMMAND_ON : -EPERM;
+}
+
+/*
+ * responseSize return the command size
+ * @param: buffer, command buffer.
+ * @param: size, the buffer size.
+ * @return: the command size.
+ */
+static int responseSize(const char *buffer, size_t size)
+{
+	size_t val = 0;
+	if (size >= TPM_HEADER_SIZE) {
+		val = (size_t) (((unsigned)buffer[2]) << 24
+				| ((unsigned)buffer[3]) << 16
+				| ((unsigned)buffer[4]) << 8 | (unsigned)
+				buffer[5]);
+	}
+
+	if (val < TPM_BUFSIZE)
+		return val;
+	else
+		return TPM_BUFSIZE;
+}
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ * Before sending any TPM commands, tpm_stm_i2c_send poll data_available and
+ * accept_command TPM GPIOs.
+ *
+ * In case the data_available is high (logical value 1), tpm_stm_i2c_send will
+ * empty the TPM FIFO by reading all the datas stored inside the TPM.
+ *
+ * Then, if the accept_command TPM GPIO is high(logical value 1)
+ * tpm_stm_i2c_send will first send the 10 bytes header of the TCG commands and
+ * then send the others bytes by 40 bytes blocks.
+ *
+ * data_available and accept_command TPM GPIOs will goes low when the TPM
+ * compute the command.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to send.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes sent.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	u32 ret = 0, i, size, ordinal, pin = 0;
+	struct i2c_client *client;
+
+	FUNC_ENTER();
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (count < TPM_HEADER_SIZE)
+		return -EBUSY;
+	client = (struct i2c_client *)pin_infos->client;
+
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+	/* i2c_client initialization */
+	client->flags = 0;
+
+	/* Wait for AcceptCmd signal high */
+	/* Check if data are available before */
+	/* sending data (data_avail_pin hight) */
+	/* If data are available, we read the data */
+	init_waitqueue_head(&pin_infos->write_queue);
+	pin = wait_event_interruptible_on_gpio(
+		pin_infos->write_queue,
+		tpm_calc_ordinal_duration(chip, ordinal));
+	if (pin < 0) {
+		ret = pin;
+		goto end;
+	}
+
+	client->flags = I2C_M_RD;
+
+	size = TPM_HEADER_SIZE;
+	i = 0;
+	while (pin == DATA_ON && i < size) {
+		int bytes;
+		if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
+
+		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
+				      bytes);
+		if (ret < 0)
+			goto end;
+		if (i == 0) {
+			size = responseSize(pin_infos->tpm_i2c_buffer[1],
+				count);
+			i += TPM_HEADER_SIZE;
+		} else
+			i += TPM_I2C_BLOCK_SIZE;
+
+		if (i < size)
+			pin = wait_event_interruptible_on_gpio(
+			    pin_infos->write_queue,
+			    msecs_to_jiffies(TPM_I2C_SHORT));
+	}
+
+	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
+					       msecs_to_jiffies(TPM_I2C_SHORT));
+
+	/* i2c_client initialization */
+	client->flags = 0;
+
+	size = TPM_HEADER_SIZE;
+	i = 0;
+	while (i < size && pin == COMMAND_ON) {
+		int bytes;
+
+		if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
+
+		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
+
+		if (i == 0) {
+			size = responseSize(buf, count);
+			size = size < count ? size : count;
+		}
+		if (count < TPM_HEADER_SIZE)
+			bytes = count;
+		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
+			  bytes);
+		if (ret < 0) {
+			pr_info("Failed to send data\n");
+			goto end;
+		}
+
+		if (i == 0)
+			i += TPM_HEADER_SIZE;
+		else
+			i += TPM_I2C_BLOCK_SIZE;
+		/* Wait for AcceptCmd signal hight */
+		if (i < size)
+			pin = wait_event_interruptible_on_gpio(
+			    pin_infos->write_queue,
+			    msecs_to_jiffies(TPM_I2C_SHORT));
+
+		if (pin != COMMAND_ON) {
+			pr_info("Failed to read gpio pin (AcceptCmd)\n");
+			ret = -EIO;
+			goto end;
+		}
+	}
+
+	if (i == 0) {
+		pr_info("Failed to read gpio pin (AcceptCmd)\n");
+		ret = -EIO;
+	}
+end:
+	return ret ? ret : count;
+}
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * Before receiving any TPM response, tpm_stm_i2c_recv poll data_available and
+ * accept_command TPM GPIOs.
+ *
+ * In case the accept_command is high (logical value 1), tpm_stm_i2c_recv will
+ * do nothing.
+ *
+ * Then, if the data_available TPM GPIO is high(logical value 1)
+ * tpm_stm_i2c_recv will first receive the 10 bytes header of the TCG TPM
+ * response and then receive the others bytes by 40 bytes blocks.
+ *
+ * accept_command TPM GPIOs will goes high when the TPM Fofo is empty.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes received.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int ret = 0;
+	int i, size;
+	int pin = 0;
+	struct i2c_client *client;
+
+	FUNC_ENTER();
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (count < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	client = (struct i2c_client *)pin_infos->client;
+
+	/* Configure TPM I2C */
+	client->flags = I2C_M_RD;
+
+	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
+	init_waitqueue_head(&chip->vendor.read_queue);
+	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
+		       tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
+
+	size = TPM_HEADER_SIZE;
+	i = 0;
+	while (i < size && pin == DATA_ON) {
+		int bytes;
+
+		if (count < TPM_HEADER_SIZE)
+			bytes = count;
+		else if (i == 0)
+			bytes = TPM_HEADER_SIZE;
+		else
+			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
+
+		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
+			  bytes);
+		if (ret < 0) {
+			pr_info(" Failed to read gpio pin (DataAvailable)\n");
+			goto end;
+		}
+
+		if (!buf) {
+			pr_info("read buffer is NULL\n");
+			goto end;
+		}
+
+		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
+
+		if (i == 0) {
+			size = responseSize(buf, size);
+			if (size > count)
+				size = count;
+			i += TPM_HEADER_SIZE;
+		} else
+			i += TPM_I2C_BLOCK_SIZE;
+
+		if (i < size)
+			pin = wait_event_interruptible_on_gpio(
+				       chip->vendor.read_queue,
+				       msecs_to_jiffies(TPM_I2C_SHORT));
+	}
+
+	if (i == 0) {
+		pr_info("Failed to read gpio pin (DataAvailable)\n");
+		ret = -EIO;
+		goto end;
+	}
+	return size;
+end:
+	return ret;
+}
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+}				/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_i2c_status is not implemented because TIS registers are not
+ * implemented.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	return -ENOSYS;
+}				/* tpm_stm_i2c_status() */
+
+/*
+ * tpm_st19_i2c_ioctl provides 2 handles:
+ * - TPMIOC_CANCEL: allow to CANCEL a TPM commands execution.
+ *   See tpm_stm_i2c_cancel description above
+ * - TPMIOC_TRANSMIT: allow to transmit a TPM commands.
+ *
+ * @return: In case of success, return TPM response size.
+ * In other case return < 0 value describing the issue.
+ */
+static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
+				  unsigned int cmd, unsigned long arg)
+{
+	int in_size = 0, out_size = 0;
+	struct tpm_chip *chip = file->private_data;
+
+	switch (cmd) {
+	case TPMIOC_CANCEL:
+		tpm_stm_i2c_cancel(chip);
+		return -ENOSYS;
+	case TPMIOC_TRANSMIT:
+		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
+		       (const char *)arg, TPM_HEADER_SIZE))
+			return -EFAULT;
+		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
+				      TPM_HEADER_SIZE);
+		if (in_size > sizeof(pin_infos->tpm_i2c_buffer[0]))
+			in_size = sizeof(pin_infos->tpm_i2c_buffer[0]);
+		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
+				   (const char *)arg, in_size))
+			return -EFAULT;
+		tpm_stm_i2c_send(chip, pin_infos->tpm_i2c_buffer[0], in_size);
+
+		out_size = tpm_stm_i2c_recv(chip, pin_infos->tpm_i2c_buffer[1],
+					    TPM_BUFSIZE);
+		if (copy_to_user((char *)arg, pin_infos->tpm_i2c_buffer[1],
+				 out_size))
+			return -EFAULT;
+		return out_size;
+	default:
+		return -ENOTTY;
+	}
+	return -ENOTTY;
+}
+
+static const struct file_operations tpm_st19_i2c_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = tpm_read,
+	.ioctl = tpm_st19_i2c_ioctl,
+	.write = tpm_write,
+	.open = tpm_open,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *stm_tpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group stm_tpm_attr_grp = {
+	.attrs = stm_tpm_attrs
+};
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.attr_group = &stm_tpm_attr_grp,
+	.miscdev = {.fops = &tpm_st19_i2c_fops,},
+};
+
+/*
+ * tpm_st19_i2c_probe initialize the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: id, the i2c_device_id struct.
+ * @return: 0 in case of success.
+ *			-1 in other case.
+ */
+static int
+tpm_st19_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int err;
+	struct tpm_chip *chip;
+	struct st19np18_platform_data *platform_data;
+
+	FUNC_ENTER();
+
+	err = 0;
+
+	/* Check I2C platform functionnalities */
+	if (client == NULL) {
+		pr_info("client is NULL. exiting.\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_info("client not i2c capable\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
+	if (!chip) {
+		err = -ENODEV;
+		goto end;
+	}
+
+	/*
+	 * ST19 TPM does not support interrupt. chip->vendor.irq is only
+	 * set to a value greater that 0 because status function have no
+	 * sense with this device (TIS register not available)
+	 */
+	chip->vendor.irq = 1;
+
+	platform_data = client->dev.platform_data;
+	pin_infos = platform_data;
+	platform_data->tpm_i2c_buffer[0] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[0] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_answer;
+	}
+	platform_data->tpm_i2c_buffer[1] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[1] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_response;
+	}
+
+	platform_data->client = client;
+
+	/* Register GPIO pin through generic Linux GPIO API */
+	err = gpio_request(platform_data->accept_pin, "accept command");
+	if (err)
+		goto _gpio_init;
+
+	err = gpio_request(platform_data->data_avail_pin, "data available");
+	if (err)
+		goto _gpio_init;
+
+	err = wait_until_good_shape();
+	if (err)
+		goto _gpio_set;
+
+	tpm_get_timeouts(chip);
+
+	/* attach chip datas to client */
+	i2c_set_clientdata(client, chip);
+	pin_infos->bChipF = false;
+
+	pr_info("TPM I2C Initialized\n");
+	return 0;
+_gpio_set:
+_gpio_init:
+	if (platform_data) {
+		gpio_free(platform_data->accept_pin);
+		gpio_free(platform_data->data_avail_pin);
+	}
+_tpm_clean_response:
+	tpm_remove_hardware(chip->dev);
+	if (platform_data->tpm_i2c_buffer[1] != NULL) {
+		kfree(platform_data->tpm_i2c_buffer[1]);
+		platform_data->tpm_i2c_buffer[1] = NULL;
+	}
+_tpm_clean_answer:
+	if (platform_data->tpm_i2c_buffer[0] != NULL) {
+		kfree(platform_data->tpm_i2c_buffer[0]);
+		platform_data->tpm_i2c_buffer[0] = NULL;
+	}
+	pin_infos->bChipF = true;
+end:
+	pr_info("TPM I2C initialisation fail\n");
+	return err;
+}
+
+/*
+ * tpm_st19_i2c_remove remove the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+		clear_bit(0, &chip->is_open);
+ * @return: 0 in case of success.
+ */
+static __devexit int tpm_st19_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
+	FUNC_ENTER();
+
+	if (pin_infos != NULL) {
+		gpio_free(pin_infos->accept_pin);
+		gpio_free(pin_infos->data_avail_pin);
+
+		/* Check if chip has been previously clean */
+		if (pin_infos->bChipF != true)
+			tpm_remove_hardware(chip->dev);
+		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
+			kfree(pin_infos->tpm_i2c_buffer[1]);
+			pin_infos->tpm_i2c_buffer[1] = NULL;
+		}
+		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
+			kfree(pin_infos->tpm_i2c_buffer[0]);
+			pin_infos->tpm_i2c_buffer[0] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * tpm_st19_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: mesg, the power management message.
+ * @return: 0 in case of success.
+ */
+static int tpm_st19_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int ret = 0;
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_suspend(&client->dev, mesg);
+	return ret;
+}				/* tpm_st19_i2c_suspend() */
+
+/*
+ * tpm_st19_i2c_pm_resume resume the TPM device
+ * This part of the Linux driver should be move in an other part or
+ * environment (bootloader ?)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @return: 0 in case of success.
+ */
+static int tpm_st19_i2c_pm_resume(struct i2c_client *client)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(pin_infos->client);
+	int ret = 0;
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_resume(&client->dev);
+	return ret;
+}				/* tpm_st19_i2c_pm_resume() */
+
+static const struct i2c_device_id tpm_st19_i2c_id[] = {
+	{TPM_DRIVER_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_st19_i2c_id);
+
+static struct i2c_driver tpm_st19_i2c_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = TPM_DRIVER_NAME,
+		   },
+	.probe = tpm_st19_i2c_probe,
+	.remove = tpm_st19_i2c_remove,
+	.resume = tpm_st19_i2c_pm_resume,
+	.suspend = tpm_st19_i2c_pm_suspend,
+	.id_table = tpm_st19_i2c_id
+};
+
+/*
+ * tpm_st19_i2c_init initialize driver
+ * @return: 0 if successful, else non zero value.
+ */
+static int __init tpm_st19_i2c_init(void)
+{
+	FUNC_ENTER();
+	return i2c_add_driver(&tpm_st19_i2c_driver);
+}
+
+/*
+ * tpm_st19_i2c_exit The kernel calls this function during unloading the
+ * module or during shut down process
+ */
+static void __exit tpm_st19_i2c_exit(void)
+{
+	FUNC_ENTER();
+	i2c_del_driver(&tpm_st19_i2c_driver);
+}
+
+module_init(tpm_st19_i2c_init);
+module_exit(tpm_st19_i2c_exit);
+
+MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
+MODULE_DESCRIPTION("STM TPM I2C ST19 Driver");
+MODULE_VERSION("1.2.0");
+MODULE_LICENSE("GPL");
Binary files linux-2.6.35.4/drivers/char/tpm/.tpm_stm_st19_i2c.c.swp and linux-st19i2c/drivers/char/tpm/.tpm_stm_st19_i2c.c.swp differ
diff -uNr linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.h linux-st19i2c/drivers/char/tpm/tpm_stm_st19_i2c.h
--- linux-2.6.35.4/drivers/char/tpm/tpm_stm_st19_i2c.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-st19i2c/drivers/char/tpm/tpm_stm_st19_i2c.h	2010-09-16 14:15:16.685780128 -0500
@@ -0,0 +1,63 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010  STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: stm_st19_tpm_i2c.h
+ *
+ * @Date: 02/12/2008
+ */
+#ifndef __STM_ST19_TPM_I2C_MAIN_H__
+#define __STM_ST19_TPM_I2C_MAIN_H__
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_DRIVER_NAME		"st19np18"
+
+#define	TPM_BUFSIZE		2048
+
+#define TPM_HEADER_SIZE		10
+#define TPM_I2C_BLOCK_SIZE	0x28
+
+#define TPM_I2C_ORDINAL_LONG	0x0D	/* TPM_ORD_TakeOwnership */
+
+#define TPM_I2C_SHORT	2000	/* 2s */
+#define TICK_GPIO_SPOOLING	2
+#define STARTUP_WAIT_INTERVAL	8 /* 8ms */
+
+/* ioctl commands */
+#define TPMIOC_CANCEL		_IO('T', 0x00)	/* Not supported */
+#define TPMIOC_TRANSMIT		_IO('T', 0x01)
+
+#define DATA_ON			  1	/* data available */
+#define COMMAND_ON		  2	/* accept command */
+
+#endif /* __STM_ST19_TPM_I2C_MAIN_H__ */
diff -uNr linux-2.6.35.4/include/linux/i2c/tpm_stm_st19_i2c.h linux-st19i2c/include/linux/i2c/tpm_stm_st19_i2c.h
--- linux-2.6.35.4/include/linux/i2c/tpm_stm_st19_i2c.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-st19i2c/include/linux/i2c/tpm_stm_st19_i2c.h	2010-09-16 14:15:16.685780128 -0500
@@ -0,0 +1,45 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST19NP18
+ * Copyright (C) 2009, 2010 STMicroelectronics
+ * Christophe RICARD tpmsupport@st.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @File: stm_st19_tpm_i2c.h
+ *
+ * @Date: 06/15/2008
+ */
+#ifndef __STM_ST19_TPM_I2C_H__
+#define __STM_ST19_TPM_I2C_H__
+
+#include <linux/i2c.h>
+
+#define TPM_DRIVER_NAME         "st19np18"
+#define TPM_I2C_ST19_ADDR_WR	(0x26 >> 1)
+
+struct st19np18_platform_data {
+	int accept_pin;	/* accept command pin */
+	int data_avail_pin;/* data available pin */
+	struct i2c_client *client;
+	bool bChipF;
+	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
+	wait_queue_head_t write_queue;
+};
+
+#endif /* __STM_ST19_TPM_I2C_H__ */

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-17 15:53                         ` Christophe Henri RICARD
@ 2010-09-23 23:38                           ` James Morris
  2010-09-29 17:08                             ` Christophe Henri RICARD
  0 siblings, 1 reply; 10+ messages in thread
From: James Morris @ 2010-09-23 23:38 UTC (permalink / raw)
  To: Christophe Henri RICARD
  Cc: Rajiv Andrade, Joe Perches, Marcel Selhorst, Debora Velarde,
	tpmdd-devel, LKML

Which patches need to be applied to the tree?

Rajiv: can you please send them to me as plain text inline, against my 
-next tree, with your signoffs?


On Fri, 17 Sep 2010, Christophe Henri RICARD wrote:

> Rajiv,
> Please find in attached file a full patch (driver + Joe Perches observations/patches + comments update).
> This patch has been tested.
> 
> Thanks
> Christophe
> 
> -----Original Message-----
> From: Rajiv Andrade [mailto:srajiv@linux.vnet.ibm.com] 
> Sent: Tuesday, September 14, 2010 12:11 PM
> To: Joe Perches
> Cc: Christophe Henri RICARD; Marcel Selhorst; Debora Velarde; James Morris; tpmdd-devel@lists.sourceforge.net; LKML
> Subject: Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
> 
> Chris, did you have the chance to test it against this specific TPM?
> Despite this, the patch looks pretty good, thanks Joe.
> 
> Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
> 
> On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
> > Add missing break in wait_until_good_shape
> > Use init; while (test) loops not for(init;test;)
> > Calculate bytes to transfer using if and min_t not multiple ?:
> > Miscellaneous function whitespace aliging
> > 
> > Signed-off-by: Joe Perches <joe@perches.com>
> > ---
> >  drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
> >  1 files changed, 85 insertions(+), 73 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
> > index cdf2eb3..4b1ed05 100644
> > --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
> > +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
> > @@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
> >  		else if (!signal_pending(current)) {
> >  			ret = schedule_timeout(time);
> >  			wait_time += time;
> > -		} else
> > +		} else {
> >  			ret = -ERESTARTSYS;
> > +			break;
> > +		}
> >  	} while (1);
> >  	finish_wait(&queue, &__wait);
> > 
> > @@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
> >  		else if (wait_time >= timeout)
> >  			break;
> >  		else if (!signal_pending(current)) {
> > -			ret =
> > -			    schedule_timeout(msecs_to_jiffies
> > -					     (TICK_GPIO_SPOOLING));
> > -			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
> > +			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
> > +
> > +			ret = schedule_timeout(time);
> > +			wait_time += time;
> >  		} else {
> >  			ret = -ERESTARTSYS;
> >  			break;
> > @@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	/* sending data (data_avail_pin hight) */
> >  	/* If data are available, we read the data */
> >  	init_waitqueue_head(&pin_infos->write_queue);
> > -	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> > -					       tpm_calc_ordinal_duration
> > -					       (chip, ordinal));
> > +	pin = wait_event_interruptible_on_gpio(
> > +			pin_infos->write_queue,
> > +			tpm_calc_ordinal_duration(chip, ordinal));
> >  	if (pin < 0) {
> >  		ret = pin;
> >  		goto end;
> > @@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	client->flags = I2C_M_RD;
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; pin == DATA_ON && i < size;) {
> > -		ret = i2c_master_recv(client,
> > -				      pin_infos->tpm_i2c_buffer[1],
> > -				      (i == 0) ? TPM_HEADER_SIZE :
> > -				      count - i > TPM_I2C_BLOCK_SIZE ?
> > -				      TPM_I2C_BLOCK_SIZE : count - i);
> > +	i = 0;
> > +	while (i < size && pin == DATA_ON) {
> > +		int bytes;
> > +
> > +		if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> > +				      bytes);
> >  		if (ret < 0)
> >  			goto end;
> > -		if (i == 0)
> > -			size =
> > -			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		if (i == 0) {
> > +			size = responseSize(pin_infos->tpm_i2c_buffer[1],
> > +					    count);
> > +			i += TPM_HEADER_SIZE;
> > +		} else
> > +			i += TPM_I2C_BLOCK_SIZE;
> > 
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(pin_infos->
> > -							     write_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					pin_infos->write_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> >  	}
> > 
> >  	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> > @@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	client->flags = 0;
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; i < size && pin == COMMAND_ON;) {
> > -		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
> > -		       (i == 0) ? TPM_HEADER_SIZE : count - i >
> > -		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
> > +	i = 0;
> > +	while (i < size && pin == COMMAND_ON) {
> > +		int bytes;
> > +
> > +		if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
> > 
> >  		if (i == 0) {
> >  			size = responseSize(buf, count);
> > -			size = (size < count ? size : count);
> > +			size = size < count ? size : count;
> >  		}
> > -		ret =
> > -		    i2c_master_send(client,
> > -				    pin_infos->tpm_i2c_buffer[0],
> > -				    count >= TPM_HEADER_SIZE ? (i ==
> > -								0) ?
> > -				    TPM_HEADER_SIZE : count - i >
> > -				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> > -				    count - i : count);
> > +
> > +		if (count < TPM_HEADER_SIZE)
> > +			bytes = count;
> > +
> > +		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
> > +				      bytes);
> >  		if (ret < 0) {
> >  			pr_info("Failed to send data\n");
> >  			goto end;
> >  		}
> > 
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		if (i == 0)
> > +			i += TPM_HEADER_SIZE;
> > +		else
> > +			i += TPM_I2C_BLOCK_SIZE;
> >  		/* Wait for AcceptCmd signal hight */
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(pin_infos->
> > -							     write_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					pin_infos->write_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> > 
> >  		if (pin != COMMAND_ON) {
> >  			pr_info("Failed to read gpio pin (AcceptCmd)\n");
> > @@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  			goto end;
> >  		}
> >  	}
> > +
> >  	if (i == 0) {
> >  		pr_info("Failed to read gpio pin (AcceptCmd)\n");
> >  		ret = -EIO;
> > @@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
> > 
> >  	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
> >  	init_waitqueue_head(&chip->vendor.read_queue);
> > -	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
> > -					       tpm_calc_ordinal_duration
> > -					       (chip, TPM_I2C_ORDINAL_LONG));
> > +	pin = wait_event_interruptible_on_gpio(
> > +			chip->vendor.read_queue,
> > +			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; i < size && pin == DATA_ON;) {
> > -		ret =
> > -		    i2c_master_recv(client,
> > -				    pin_infos->tpm_i2c_buffer[1],
> > -				    (count >= TPM_HEADER_SIZE ? i ==
> > -				     0 ? TPM_HEADER_SIZE : (size - i) >
> > -				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> > -				     size - i : count));
> > +	i = 0;
> > +	while (i < size && pin == DATA_ON) {
> > +		int bytes;
> > +
> > +		if (count < TPM_HEADER_SIZE)
> > +			bytes = count;
> > +		else if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> > +				      bytes);
> >  		if (ret < 0) {
> >  			pr_info("Failed to read gpio pin (DataAvailable)\n");
> >  			goto end;
> >  		}
> > 
> > -		if (buf != NULL) {
> > -			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
> > -			       (count >= TPM_HEADER_SIZE ? i == 0 ?
> > -				TPM_HEADER_SIZE : (size - i) >
> > -				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
> > -				i : count));
> > -
> > -			if (i == 0) {
> > -				size = responseSize(buf, size);
> > -				if (size > count)
> > -					size = count;
> > -			}
> > -		} else {
> > +		if (!buf) {
> >  			pr_info("read buffer is NULL\n");
> >  			goto end;
> >  		}
> > 
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
> > +
> > +		if (i == 0) {
> > +			size = responseSize(buf, size);
> > +			if (size > count)
> > +				size = count;
> > +			i += TPM_HEADER_SIZE;
> > +		} else
> > +			i += TPM_I2C_BLOCK_SIZE;
> > 
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(chip->vendor.
> > -							     read_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					chip->vendor.read_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> >  	}
> > 
> >  	if (i == 0) {
> > @@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
> >  		return -ENOSYS;
> >  	case TPMIOC_TRANSMIT:
> >  		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
> > -		    (const char *)arg, TPM_HEADER_SIZE))
> > +				   (const char *)arg, TPM_HEADER_SIZE))
> >  			return -EFAULT;
> >  		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
> >  				      TPM_HEADER_SIZE);
> 
> 
> 

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-23 23:38                           ` James Morris
@ 2010-09-29 17:08                             ` Christophe Henri RICARD
  2010-09-29 17:37                               ` Rajiv Andrade
  0 siblings, 1 reply; 10+ messages in thread
From: Christophe Henri RICARD @ 2010-09-29 17:08 UTC (permalink / raw)
  To: James Morris
  Cc: Rajiv Andrade, Joe Perches, Marcel Selhorst, Debora Velarde,
	tpmdd-devel, LKML

Hi James, Rajiv,

The last one includes all the patches and some comments cleaning.
Let me know if you need some information's or have some improvements I have to do.

Thanks
Christophe

-----Original Message-----
From: James Morris [mailto:jmorris@namei.org] 
Sent: Thursday, September 23, 2010 6:39 PM
To: Christophe Henri RICARD
Cc: Rajiv Andrade; Joe Perches; Marcel Selhorst; Debora Velarde; tpmdd-devel@lists.sourceforge.net; LKML
Subject: RE: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening

Which patches need to be applied to the tree?

Rajiv: can you please send them to me as plain text inline, against my 
-next tree, with your signoffs?


On Fri, 17 Sep 2010, Christophe Henri RICARD wrote:

> Rajiv,
> Please find in attached file a full patch (driver + Joe Perches observations/patches + comments update).
> This patch has been tested.
> 
> Thanks
> Christophe
> 
> -----Original Message-----
> From: Rajiv Andrade [mailto:srajiv@linux.vnet.ibm.com] 
> Sent: Tuesday, September 14, 2010 12:11 PM
> To: Joe Perches
> Cc: Christophe Henri RICARD; Marcel Selhorst; Debora Velarde; James Morris; tpmdd-devel@lists.sourceforge.net; LKML
> Subject: Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
> 
> Chris, did you have the chance to test it against this specific TPM?
> Despite this, the patch looks pretty good, thanks Joe.
> 
> Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
> 
> On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
> > Add missing break in wait_until_good_shape
> > Use init; while (test) loops not for(init;test;)
> > Calculate bytes to transfer using if and min_t not multiple ?:
> > Miscellaneous function whitespace aliging
> > 
> > Signed-off-by: Joe Perches <joe@perches.com>
> > ---
> >  drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
> >  1 files changed, 85 insertions(+), 73 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
> > index cdf2eb3..4b1ed05 100644
> > --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
> > +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
> > @@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
> >  		else if (!signal_pending(current)) {
> >  			ret = schedule_timeout(time);
> >  			wait_time += time;
> > -		} else
> > +		} else {
> >  			ret = -ERESTARTSYS;
> > +			break;
> > +		}
> >  	} while (1);
> >  	finish_wait(&queue, &__wait);
> > 
> > @@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
> >  		else if (wait_time >= timeout)
> >  			break;
> >  		else if (!signal_pending(current)) {
> > -			ret =
> > -			    schedule_timeout(msecs_to_jiffies
> > -					     (TICK_GPIO_SPOOLING));
> > -			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
> > +			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
> > +
> > +			ret = schedule_timeout(time);
> > +			wait_time += time;
> >  		} else {
> >  			ret = -ERESTARTSYS;
> >  			break;
> > @@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	/* sending data (data_avail_pin hight) */
> >  	/* If data are available, we read the data */
> >  	init_waitqueue_head(&pin_infos->write_queue);
> > -	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> > -					       tpm_calc_ordinal_duration
> > -					       (chip, ordinal));
> > +	pin = wait_event_interruptible_on_gpio(
> > +			pin_infos->write_queue,
> > +			tpm_calc_ordinal_duration(chip, ordinal));
> >  	if (pin < 0) {
> >  		ret = pin;
> >  		goto end;
> > @@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	client->flags = I2C_M_RD;
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; pin == DATA_ON && i < size;) {
> > -		ret = i2c_master_recv(client,
> > -				      pin_infos->tpm_i2c_buffer[1],
> > -				      (i == 0) ? TPM_HEADER_SIZE :
> > -				      count - i > TPM_I2C_BLOCK_SIZE ?
> > -				      TPM_I2C_BLOCK_SIZE : count - i);
> > +	i = 0;
> > +	while (i < size && pin == DATA_ON) {
> > +		int bytes;
> > +
> > +		if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> > +				      bytes);
> >  		if (ret < 0)
> >  			goto end;
> > -		if (i == 0)
> > -			size =
> > -			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		if (i == 0) {
> > +			size = responseSize(pin_infos->tpm_i2c_buffer[1],
> > +					    count);
> > +			i += TPM_HEADER_SIZE;
> > +		} else
> > +			i += TPM_I2C_BLOCK_SIZE;
> > 
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(pin_infos->
> > -							     write_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					pin_infos->write_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> >  	}
> > 
> >  	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
> > @@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  	client->flags = 0;
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; i < size && pin == COMMAND_ON;) {
> > -		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
> > -		       (i == 0) ? TPM_HEADER_SIZE : count - i >
> > -		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
> > +	i = 0;
> > +	while (i < size && pin == COMMAND_ON) {
> > +		int bytes;
> > +
> > +		if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
> > 
> >  		if (i == 0) {
> >  			size = responseSize(buf, count);
> > -			size = (size < count ? size : count);
> > +			size = size < count ? size : count;
> >  		}
> > -		ret =
> > -		    i2c_master_send(client,
> > -				    pin_infos->tpm_i2c_buffer[0],
> > -				    count >= TPM_HEADER_SIZE ? (i ==
> > -								0) ?
> > -				    TPM_HEADER_SIZE : count - i >
> > -				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> > -				    count - i : count);
> > +
> > +		if (count < TPM_HEADER_SIZE)
> > +			bytes = count;
> > +
> > +		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
> > +				      bytes);
> >  		if (ret < 0) {
> >  			pr_info("Failed to send data\n");
> >  			goto end;
> >  		}
> > 
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		if (i == 0)
> > +			i += TPM_HEADER_SIZE;
> > +		else
> > +			i += TPM_I2C_BLOCK_SIZE;
> >  		/* Wait for AcceptCmd signal hight */
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(pin_infos->
> > -							     write_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					pin_infos->write_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> > 
> >  		if (pin != COMMAND_ON) {
> >  			pr_info("Failed to read gpio pin (AcceptCmd)\n");
> > @@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> >  			goto end;
> >  		}
> >  	}
> > +
> >  	if (i == 0) {
> >  		pr_info("Failed to read gpio pin (AcceptCmd)\n");
> >  		ret = -EIO;
> > @@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
> > 
> >  	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
> >  	init_waitqueue_head(&chip->vendor.read_queue);
> > -	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
> > -					       tpm_calc_ordinal_duration
> > -					       (chip, TPM_I2C_ORDINAL_LONG));
> > +	pin = wait_event_interruptible_on_gpio(
> > +			chip->vendor.read_queue,
> > +			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
> > 
> >  	size = TPM_HEADER_SIZE;
> > -	for (i = 0; i < size && pin == DATA_ON;) {
> > -		ret =
> > -		    i2c_master_recv(client,
> > -				    pin_infos->tpm_i2c_buffer[1],
> > -				    (count >= TPM_HEADER_SIZE ? i ==
> > -				     0 ? TPM_HEADER_SIZE : (size - i) >
> > -				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
> > -				     size - i : count));
> > +	i = 0;
> > +	while (i < size && pin == DATA_ON) {
> > +		int bytes;
> > +
> > +		if (count < TPM_HEADER_SIZE)
> > +			bytes = count;
> > +		else if (i == 0)
> > +			bytes = TPM_HEADER_SIZE;
> > +		else
> > +			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
> > +
> > +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
> > +				      bytes);
> >  		if (ret < 0) {
> >  			pr_info("Failed to read gpio pin (DataAvailable)\n");
> >  			goto end;
> >  		}
> > 
> > -		if (buf != NULL) {
> > -			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
> > -			       (count >= TPM_HEADER_SIZE ? i == 0 ?
> > -				TPM_HEADER_SIZE : (size - i) >
> > -				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
> > -				i : count));
> > -
> > -			if (i == 0) {
> > -				size = responseSize(buf, size);
> > -				if (size > count)
> > -					size = count;
> > -			}
> > -		} else {
> > +		if (!buf) {
> >  			pr_info("read buffer is NULL\n");
> >  			goto end;
> >  		}
> > 
> > -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
> > +		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
> > +
> > +		if (i == 0) {
> > +			size = responseSize(buf, size);
> > +			if (size > count)
> > +				size = count;
> > +			i += TPM_HEADER_SIZE;
> > +		} else
> > +			i += TPM_I2C_BLOCK_SIZE;
> > 
> >  		if (i < size)
> > -			pin =
> > -			    wait_event_interruptible_on_gpio(chip->vendor.
> > -							     read_queue,
> > -							     msecs_to_jiffies
> > -							     (TPM_I2C_SHORT));
> > +			pin = wait_event_interruptible_on_gpio(
> > +					chip->vendor.read_queue,
> > +					msecs_to_jiffies(TPM_I2C_SHORT));
> >  	}
> > 
> >  	if (i == 0) {
> > @@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
> >  		return -ENOSYS;
> >  	case TPMIOC_TRANSMIT:
> >  		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
> > -		    (const char *)arg, TPM_HEADER_SIZE))
> > +				   (const char *)arg, TPM_HEADER_SIZE))
> >  			return -EFAULT;
> >  		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
> >  				      TPM_HEADER_SIZE);
> 
> 
> 

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
  2010-09-29 17:08                             ` Christophe Henri RICARD
@ 2010-09-29 17:37                               ` Rajiv Andrade
  0 siblings, 0 replies; 10+ messages in thread
From: Rajiv Andrade @ 2010-09-29 17:37 UTC (permalink / raw)
  To: Christophe Henri RICARD
  Cc: James Morris, Joe Perches, Marcel Selhorst, Debora Velarde,
	tpmdd-devel, LKML

Hi James,

I'll send you the complete patchset against your -next tree today.

Thanks,
Rajiv

On 29/09/2010, at 14:08, Christophe Henri RICARD wrote:

> Hi James, Rajiv,
> 
> The last one includes all the patches and some comments cleaning.
> Let me know if you need some information's or have some improvements I have to do.
> 
> Thanks
> Christophe
> 
> -----Original Message-----
> From: James Morris [mailto:jmorris@namei.org] 
> Sent: Thursday, September 23, 2010 6:39 PM
> To: Christophe Henri RICARD
> Cc: Rajiv Andrade; Joe Perches; Marcel Selhorst; Debora Velarde; tpmdd-devel@lists.sourceforge.net; LKML
> Subject: RE: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
> 
> Which patches need to be applied to the tree?
> 
> Rajiv: can you please send them to me as plain text inline, against my 
> -next tree, with your signoffs?
> 
> 
> On Fri, 17 Sep 2010, Christophe Henri RICARD wrote:
> 
>> Rajiv,
>> Please find in attached file a full patch (driver + Joe Perches observations/patches + comments update).
>> This patch has been tested.
>> 
>> Thanks
>> Christophe
>> 
>> -----Original Message-----
>> From: Rajiv Andrade [mailto:srajiv@linux.vnet.ibm.com] 
>> Sent: Tuesday, September 14, 2010 12:11 PM
>> To: Joe Perches
>> Cc: Christophe Henri RICARD; Marcel Selhorst; Debora Velarde; James Morris; tpmdd-devel@lists.sourceforge.net; LKML
>> Subject: Re: [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening
>> 
>> Chris, did you have the chance to test it against this specific TPM?
>> Despite this, the patch looks pretty good, thanks Joe.
>> 
>> Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
>> 
>> On Fri, 2010-09-03 at 16:29 -0700, Joe Perches wrote:
>>> Add missing break in wait_until_good_shape
>>> Use init; while (test) loops not for(init;test;)
>>> Calculate bytes to transfer using if and min_t not multiple ?:
>>> Miscellaneous function whitespace aliging
>>> 
>>> Signed-off-by: Joe Perches <joe@perches.com>
>>> ---
>>> drivers/char/tpm/tpm_stm_st19_i2c.c |  158 +++++++++++++++++++----------------
>>> 1 files changed, 85 insertions(+), 73 deletions(-)
>>> 
>>> diff --git a/drivers/char/tpm/tpm_stm_st19_i2c.c b/drivers/char/tpm/tpm_stm_st19_i2c.c
>>> index cdf2eb3..4b1ed05 100644
>>> --- a/drivers/char/tpm/tpm_stm_st19_i2c.c
>>> +++ b/drivers/char/tpm/tpm_stm_st19_i2c.c
>>> @@ -158,8 +158,10 @@ static int wait_until_good_shape(void)
>>> 		else if (!signal_pending(current)) {
>>> 			ret = schedule_timeout(time);
>>> 			wait_time += time;
>>> -		} else
>>> +		} else {
>>> 			ret = -ERESTARTSYS;
>>> +			break;
>>> +		}
>>> 	} while (1);
>>> 	finish_wait(&queue, &__wait);
>>> 
>>> @@ -204,10 +206,10 @@ static int wait_event_interruptible_on_gpio(wait_queue_head_t queue,
>>> 		else if (wait_time >= timeout)
>>> 			break;
>>> 		else if (!signal_pending(current)) {
>>> -			ret =
>>> -			    schedule_timeout(msecs_to_jiffies
>>> -					     (TICK_GPIO_SPOOLING));
>>> -			wait_time += msecs_to_jiffies(TICK_GPIO_SPOOLING);
>>> +			int time = msecs_to_jiffies(TICK_GPIO_SPOOLING);
>>> +
>>> +			ret = schedule_timeout(time);
>>> +			wait_time += time;
>>> 		} else {
>>> 			ret = -ERESTARTSYS;
>>> 			break;
>>> @@ -286,9 +288,9 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>>> 	/* sending data (data_avail_pin hight) */
>>> 	/* If data are available, we read the data */
>>> 	init_waitqueue_head(&pin_infos->write_queue);
>>> -	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
>>> -					       tpm_calc_ordinal_duration
>>> -					       (chip, ordinal));
>>> +	pin = wait_event_interruptible_on_gpio(
>>> +			pin_infos->write_queue,
>>> +			tpm_calc_ordinal_duration(chip, ordinal));
>>> 	if (pin < 0) {
>>> 		ret = pin;
>>> 		goto end;
>>> @@ -297,25 +299,30 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>>> 	client->flags = I2C_M_RD;
>>> 
>>> 	size = TPM_HEADER_SIZE;
>>> -	for (i = 0; pin == DATA_ON && i < size;) {
>>> -		ret = i2c_master_recv(client,
>>> -				      pin_infos->tpm_i2c_buffer[1],
>>> -				      (i == 0) ? TPM_HEADER_SIZE :
>>> -				      count - i > TPM_I2C_BLOCK_SIZE ?
>>> -				      TPM_I2C_BLOCK_SIZE : count - i);
>>> +	i = 0;
>>> +	while (i < size && pin == DATA_ON) {
>>> +		int bytes;
>>> +
>>> +		if (i == 0)
>>> +			bytes = TPM_HEADER_SIZE;
>>> +		else
>>> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
>>> +
>>> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
>>> +				      bytes);
>>> 		if (ret < 0)
>>> 			goto end;
>>> -		if (i == 0)
>>> -			size =
>>> -			    responseSize(pin_infos->tpm_i2c_buffer[1], count);
>>> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
>>> +		if (i == 0) {
>>> +			size = responseSize(pin_infos->tpm_i2c_buffer[1],
>>> +					    count);
>>> +			i += TPM_HEADER_SIZE;
>>> +		} else
>>> +			i += TPM_I2C_BLOCK_SIZE;
>>> 
>>> 		if (i < size)
>>> -			pin =
>>> -			    wait_event_interruptible_on_gpio(pin_infos->
>>> -							     write_queue,
>>> -							     msecs_to_jiffies
>>> -							     (TPM_I2C_SHORT));
>>> +			pin = wait_event_interruptible_on_gpio(
>>> +					pin_infos->write_queue,
>>> +					msecs_to_jiffies(TPM_I2C_SHORT));
>>> 	}
>>> 
>>> 	pin = wait_event_interruptible_on_gpio(pin_infos->write_queue,
>>> @@ -325,36 +332,41 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>>> 	client->flags = 0;
>>> 
>>> 	size = TPM_HEADER_SIZE;
>>> -	for (i = 0; i < size && pin == COMMAND_ON;) {
>>> -		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i,
>>> -		       (i == 0) ? TPM_HEADER_SIZE : count - i >
>>> -		       TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : count - i);
>>> +	i = 0;
>>> +	while (i < size && pin == COMMAND_ON) {
>>> +		int bytes;
>>> +
>>> +		if (i == 0)
>>> +			bytes = TPM_HEADER_SIZE;
>>> +		else
>>> +			bytes = min_t(int, count - i, TPM_I2C_BLOCK_SIZE);
>>> +
>>> +		memcpy(pin_infos->tpm_i2c_buffer[0], buf + i, bytes);
>>> 
>>> 		if (i == 0) {
>>> 			size = responseSize(buf, count);
>>> -			size = (size < count ? size : count);
>>> +			size = size < count ? size : count;
>>> 		}
>>> -		ret =
>>> -		    i2c_master_send(client,
>>> -				    pin_infos->tpm_i2c_buffer[0],
>>> -				    count >= TPM_HEADER_SIZE ? (i ==
>>> -								0) ?
>>> -				    TPM_HEADER_SIZE : count - i >
>>> -				    TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
>>> -				    count - i : count);
>>> +
>>> +		if (count < TPM_HEADER_SIZE)
>>> +			bytes = count;
>>> +
>>> +		ret = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
>>> +				      bytes);
>>> 		if (ret < 0) {
>>> 			pr_info("Failed to send data\n");
>>> 			goto end;
>>> 		}
>>> 
>>> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
>>> +		if (i == 0)
>>> +			i += TPM_HEADER_SIZE;
>>> +		else
>>> +			i += TPM_I2C_BLOCK_SIZE;
>>> 		/* Wait for AcceptCmd signal hight */
>>> 		if (i < size)
>>> -			pin =
>>> -			    wait_event_interruptible_on_gpio(pin_infos->
>>> -							     write_queue,
>>> -							     msecs_to_jiffies
>>> -							     (TPM_I2C_SHORT));
>>> +			pin = wait_event_interruptible_on_gpio(
>>> +					pin_infos->write_queue,
>>> +					msecs_to_jiffies(TPM_I2C_SHORT));
>>> 
>>> 		if (pin != COMMAND_ON) {
>>> 			pr_info("Failed to read gpio pin (AcceptCmd)\n");
>>> @@ -362,6 +374,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
>>> 			goto end;
>>> 		}
>>> 	}
>>> +
>>> 	if (i == 0) {
>>> 		pr_info("Failed to read gpio pin (AcceptCmd)\n");
>>> 		ret = -EIO;
>>> @@ -412,49 +425,48 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
>>> 
>>> 	/* Spool on the good gpio as long as pin GPIO 3 not HIGHT */
>>> 	init_waitqueue_head(&chip->vendor.read_queue);
>>> -	pin = wait_event_interruptible_on_gpio(chip->vendor.read_queue,
>>> -					       tpm_calc_ordinal_duration
>>> -					       (chip, TPM_I2C_ORDINAL_LONG));
>>> +	pin = wait_event_interruptible_on_gpio(
>>> +			chip->vendor.read_queue,
>>> +			tpm_calc_ordinal_duration(chip, TPM_I2C_ORDINAL_LONG));
>>> 
>>> 	size = TPM_HEADER_SIZE;
>>> -	for (i = 0; i < size && pin == DATA_ON;) {
>>> -		ret =
>>> -		    i2c_master_recv(client,
>>> -				    pin_infos->tpm_i2c_buffer[1],
>>> -				    (count >= TPM_HEADER_SIZE ? i ==
>>> -				     0 ? TPM_HEADER_SIZE : (size - i) >
>>> -				     TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE :
>>> -				     size - i : count));
>>> +	i = 0;
>>> +	while (i < size && pin == DATA_ON) {
>>> +		int bytes;
>>> +
>>> +		if (count < TPM_HEADER_SIZE)
>>> +			bytes = count;
>>> +		else if (i == 0)
>>> +			bytes = TPM_HEADER_SIZE;
>>> +		else
>>> +			bytes = min_t(int, size - i, TPM_I2C_BLOCK_SIZE);
>>> +
>>> +		ret = i2c_master_recv(client, pin_infos->tpm_i2c_buffer[1],
>>> +				      bytes);
>>> 		if (ret < 0) {
>>> 			pr_info("Failed to read gpio pin (DataAvailable)\n");
>>> 			goto end;
>>> 		}
>>> 
>>> -		if (buf != NULL) {
>>> -			memcpy(buf + i, pin_infos->tpm_i2c_buffer[1],
>>> -			       (count >= TPM_HEADER_SIZE ? i == 0 ?
>>> -				TPM_HEADER_SIZE : (size - i) >
>>> -				TPM_I2C_BLOCK_SIZE ? TPM_I2C_BLOCK_SIZE : size -
>>> -				i : count));
>>> -
>>> -			if (i == 0) {
>>> -				size = responseSize(buf, size);
>>> -				if (size > count)
>>> -					size = count;
>>> -			}
>>> -		} else {
>>> +		if (!buf) {
>>> 			pr_info("read buffer is NULL\n");
>>> 			goto end;
>>> 		}
>>> 
>>> -		(i == 0) ? (i += TPM_HEADER_SIZE) : (i += TPM_I2C_BLOCK_SIZE);
>>> +		memcpy(buf + i, pin_infos->tpm_i2c_buffer[1], size);
>>> +
>>> +		if (i == 0) {
>>> +			size = responseSize(buf, size);
>>> +			if (size > count)
>>> +				size = count;
>>> +			i += TPM_HEADER_SIZE;
>>> +		} else
>>> +			i += TPM_I2C_BLOCK_SIZE;
>>> 
>>> 		if (i < size)
>>> -			pin =
>>> -			    wait_event_interruptible_on_gpio(chip->vendor.
>>> -							     read_queue,
>>> -							     msecs_to_jiffies
>>> -							     (TPM_I2C_SHORT));
>>> +			pin = wait_event_interruptible_on_gpio(
>>> +					chip->vendor.read_queue,
>>> +					msecs_to_jiffies(TPM_I2C_SHORT));
>>> 	}
>>> 
>>> 	if (i == 0) {
>>> @@ -532,7 +544,7 @@ static ssize_t tpm_st19_i2c_ioctl(struct inode *inode, struct file *file,
>>> 		return -ENOSYS;
>>> 	case TPMIOC_TRANSMIT:
>>> 		if (copy_from_user(pin_infos->tpm_i2c_buffer[0],
>>> -		    (const char *)arg, TPM_HEADER_SIZE))
>>> +				   (const char *)arg, TPM_HEADER_SIZE))
>>> 			return -EFAULT;
>>> 		in_size = responseSize(pin_infos->tpm_i2c_buffer[0],
>>> 				      TPM_HEADER_SIZE);
>> 
>> 
>> 
> 
> -- 
> James Morris
> <jmorris@namei.org>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-09-29 17:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <002501cacb5d$9c883650$d598a2f0$@ricard@st.com>
     [not found] ` <5C722288-63DA-494B-AD37-1B4CA5A35EA0@linux.vnet.ibm.com>
     [not found]   ` <002801cacc24$385cdf60$a9169e20$@ricard@st.com>
     [not found]     ` <1269551792.3027.5.camel@blackbox.ibm.com>
     [not found]       ` <51078F5F-518D-4B08-8BB0-CEB672AD10FF@linux.vnet.ibm.com>
     [not found]         ` <000601cae64a$a532aad0$ef980070$@ricard@st.com>
     [not found]           ` <4BD98EEA.4060805@sirrix.com>
     [not found]             ` <!&!AAAAAAAAAAAYAAAAAAAAAP0vDh1zjO1PkFCA0mWh9hHCgAAAEAAAANBlGrYv425GtuqHVwaJ6hkBAAAAAA==@st.com>
     [not found]               ` <35E2570B-DD77-4CDB-9B13-7211E18E7000@linux.vnet.ibm.com>
2010-09-03 19:54                 ` [tpmdd-devel] ST19NP18 I2C driver submission + possible bug found in the last TPM kernel core Christophe Henri RICARD
2010-09-03 23:28                   ` [PATCH 0/2] tpm_stm_st19+i2c: use pr_<level> and cleanups Joe Perches
2010-09-03 23:29                     ` [PATCH 1/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Use pr_fmt, pr_<level> and FUNC_ENTER Joe Perches
2010-09-14 17:06                       ` Rajiv Andrade
2010-09-03 23:29                     ` [PATCH 2/2] drivers/char/tpm/tpm_stm_st19_i2c.c: Add missing break and neatening Joe Perches
2010-09-14 17:11                       ` Rajiv Andrade
2010-09-17 15:53                         ` Christophe Henri RICARD
2010-09-23 23:38                           ` James Morris
2010-09-29 17:08                             ` Christophe Henri RICARD
2010-09-29 17:37                               ` Rajiv Andrade

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.