[PATCH 30/30] W1: ds2490.c optimize ds_set_pullup

!MAILaRCHIVE_VOTE_RePLACE
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <linux-kernel@...>
Cc: Andrew Morton <akpm@...>, David Fries <david@...>, Evgeniy Polyakov <johnpol@...>
Date: Friday, July 11, 2008 - 9:51 am

Optimize the ds_set_pullup function.  For a strong pullup to be sent
the ds2490 has to have both the strong pullup mode enabled, and the
specific write operation has to have the SPU bit enabled.  Previously
the write always had the SPU bit enabled and both the duration and
model was set when a strong pullup was requested.  Now the strong
pullup mode is enabled at initialization time, the delay is updated
only when the value changes, and the write SPU bit is set only when a
strong pullup is required.  This removes two or three bus transactions
per strong pullup request.

Signed-off-by: David Fries <david@fries.net>
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

---
 drivers/w1/masters/ds2490.c |   64 ++++++++++++++++++++++++++++++-------------
 1 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 466048f..d38ac01 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -141,6 +141,10 @@ struct ds_device
 	 * 0: pullup not active, else duration in milliseconds
 	 */
 	int			spu_sleep;
+	/* spu_bit contains COMM_SPU or 0 depending on if the strong pullup
+	 * should be active or not for writes.
+	 */
+	u16			spu_bit;
 
 	struct w1_bus_master	master;
 };
@@ -311,6 +315,25 @@ static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count)
 	}
 }
 
+static void ds_reset_device(struct ds_device *dev)
+{
+	ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+	/* Always allow strong pullup which allow individual writes to use
+	 * the strong pullup.
+	 */
+	if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE))
+		printk(KERN_ERR "ds_reset_device: "
+			"Error allowing strong pullup\n");
+	/* Chip strong pullup time was cleared. */
+	if (dev->spu_sleep) {
+		/* lower 4 bits are 0, see ds_set_pullup */
+		u8 del = dev->spu_sleep>>4;
+		if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del))
+			printk(KERN_ERR "ds_reset_device: "
+				"Error setting duration\n");
+	}
+}
+
 static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 {
 	int count, err;
@@ -444,7 +467,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 
 	if (err >= 16 && st->status & ST_EPOF) {
 		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
-		ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+		ds_reset_device(dev);
 		/* Always dump the device status. */
 		count = 101;
 	}
@@ -509,24 +532,26 @@ static int ds_set_speed(struct ds_device *dev, int speed)
 
 static int ds_set_pullup(struct ds_device *dev, int delay)
 {
-	int err;
+	int err = 0;
 	u8 del = 1 + (u8)(delay >> 4);
+	/* Just storing delay would not get the trunication and roundup. */
+	int ms = del<<4;
+
+	/* Enable spu_bit if a delay is set. */
+	dev->spu_bit = delay?COMM_SPU:0;
+	/* If delay is zero, it has already been disabled, if the time is
+	 * the same as the hardware was last programmed to, there is also
+	 * nothing more to do.  Compare with the recalculated value ms
+	 * rather than del or delay which can have a different value.
+	 */
+	if (delay == 0 || ms == dev->spu_sleep)
+		return err;
 
-	dev->spu_sleep = 0;
-	err = ds_send_control_mode(dev, MOD_PULSE_EN, delay?PULSE_SPUE:0);
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
 	if (err)
 		return err;
 
-	if (delay) {
-		err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
-		if (err)
-			return err;
-
-		/* Just storing delay would not get the trunication and
-		 * roundup.
-		 */
-		dev->spu_sleep = del<<4;
-	}
+	dev->spu_sleep = ms;
 
 	return err;
 }
@@ -577,11 +602,11 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
 	struct ds_status st;
 	u8 rbyte;
 
-	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
 	if (err)
 		return err;
 
-	if (dev->spu_sleep)
+	if (dev->spu_bit)
 		msleep(dev->spu_sleep);
 
 	err = ds_wait_status(dev, &st);
@@ -648,11 +673,11 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
 	if (err < 0)
 		return err;
 
-	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len);
 	if (err)
 		return err;
 
-	if (dev->spu_sleep)
+	if (dev->spu_bit)
 		msleep(dev->spu_sleep);
 
 	ds_wait_status(dev, &st);
@@ -849,7 +874,7 @@ static int ds_w1_init(struct ds_device *dev)
 	 * the input buffer.  This will cause the next read to fail
 	 * see the note in ds_recv_data.
 	 */
-	ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+	ds_reset_device(dev);
 
 	dev->master.data	= dev;
 	dev->master.touch_bit	= &ds9490r_touch_bit;
@@ -892,6 +917,7 @@ static int ds_probe(struct usb_interface *intf,
 		return -ENOMEM;
 	}
 	dev->spu_sleep = 0;
+	dev->spu_bit = 0;
 	dev->udev = usb_get_dev(udev);
 	if (!dev->udev) {
 		err = -ENOMEM;
-- 
1.4.4.4

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
w1 updates., Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 17/30] W1: w1_io.c reset comments and msleep, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 29/30] W1: Documentation/w1/masters/ds2490 update, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 8/30] W1: recode w1_slave_found logic, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 15/30] W1: w1_int.c use first available master number, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 16/30] W1: w1.c s/printk/dev_dbg/, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 23/30] W1: ds2490.c simplify and fix ds_touch_bit, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 27/30] W1: ds2490.c magic number work, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 1/30] W1: fix deadlocks and remove w1_control_thread, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 7/30] W1: be able to manually add and remove slaves, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 26/30] W1: ds2490.c reset ds2490 in init, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 22/30] W1: ds2490.c disable bit read and write, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 18/30] W1: ds1wm.c msleep for reset, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 3/30] W1: don't delay search start, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 2/30] W1: abort search early on on exit, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 19/30] W1: ds2490.c correct print message, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 9/30] W1: new module parameter search_count, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 13/30] W1: w1_family, remove unused variable need_exit, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 20/30] W1: ds2490.c add support for strong pullup, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 12/30] W1: w1_therm fix user buffer overflow and cat, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 30/30] W1: ds2490.c optimize ds_set_pullup, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 5/30] W1: feature, enable hardware strong pullup, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 24/30] W1: ds2490.c ds_dump_status rework, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 4/30] W1: w1_process, block or sleep, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)
[PATCH 25/30] W1: ds2490.c ds_reset remove ds_wait_status, Evgeniy Polyakov, (Fri Jul 11, 9:51 am)