From: David Fries <david@fries.net>
To: linux-kernel@vger.kernel.org
Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Subject: [PATCH 35/35] W1: ds2490.c optimize ds_set_pullup
Date: Fri, 28 Mar 2008 07:28:04 -0500 [thread overview]
Message-ID: <20080328122804.GJ3613@spacedout.fries.net> (raw)
In-Reply-To: <200803272343.m2RNhDac017650@SpacedOut.fries.net>
[-- Attachment #1: Type: text/plain, Size: 6507 bytes --]
ds2490.c 1.20
Optimize the ds_set_pullup function.
Previously when ds_set_pullup was called with a time, the strong pullup
mode was enabled, and the delay was set, when the write command was
called the strong pullup bit was always set, then the strong pullup
mode would be disabled by ds_set_pullup after the write.
ds_send_control_mode(dev, MOD_PULSE_EN, delay?PULSE_SPUE:0);
ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
ds_send_control_mode(dev, MOD_PULSE_EN, delay?PULSE_SPUE:0);
This change enables the strong pullup mode at initialization.
ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
If ds_set_pullup was called with a time, the delay was updated only if
it had changed, and an internal variable set to enable the SPU bit on
the following write command. The ds_set_pullup to disable the strong pullup
only updates the variable.
ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); // if required
ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
In the best case, after the first pullup, the requested duration doesn't
change, making three less control transfers, 2 before and one after the
strong pullup enabled transaction.
In the worst case, after the hardware is initialized, it is 2 less
control transfers, as the delay has to be changed between each strong
pullup transfer.
Here is the total time for seven temperature conversions, three with 900ms
and four with 750ms. The conversion that includes the extra set delay
control takes a little longer. The additional time is a little closer to
the noise level than this data set might imply. USBMon puts it between
2ms and 3ms for a control transfer. This patch would save two to three
times that.
750ms request
real 0m1.002s 900ms request, update duration
real 0m0.994s 900ms request,
real 0m0.994s 900ms request,
real 0m0.842s 750ms request, update duration
real 0m0.834s 750ms request,
real 0m0.834s 750ms request,
real 0m0.834s 750ms request,
Signed-off-by: David Fries <david@fries.net>
---
drivers/w1/masters/ds2490.c | 62 +++++++++++++++++++++++++++++-------------
1 files changed, 43 insertions(+), 19 deletions(-)
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index cde99b7..9b44205 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;
};
@@ -310,6 +314,23 @@ 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("ds_reset_device: Error allowing string 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("ds_reset_device: Error setting duration\n");
+ }
+}
+
static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{
int count, err;
@@ -443,7 +464,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;
}
@@ -504,24 +525,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;
}
@@ -572,11 +595,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);
@@ -643,11 +666,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);
@@ -844,7 +867,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;
@@ -887,6 +910,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
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
prev parent reply other threads:[~2008-03-28 12:57 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200803272343.m2RNhDac017650@SpacedOut.fries.net>
2008-03-28 12:23 ` [PATCH 1/35] W1: fix deadlocks and remove w1_control_thread David Fries
2008-03-28 12:24 ` [PATCH 2/35] W1: abort search early on on exit David Fries
2008-03-28 12:24 ` [PATCH 3/35] W1: don't delay search start David Fries
2008-03-28 12:24 ` [PATCH 4/35] W1: w1_process, allow wakeup in sleep David Fries
2008-03-28 12:24 ` [PATCH 5/35] W1: w1_process, remove W1_MASTER_NEED_EXIT, it is redundant David Fries
2008-03-28 12:24 ` [PATCH 6/35] W1: w1_process, block when there's nothing to do David Fries
2008-03-30 11:28 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 7/35] W1: feature, enable hardware strong pullup David Fries
2008-03-30 11:31 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 8/35] W1: feature, w1_therm.c use " David Fries
2008-03-30 11:30 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 9/35] W1: create documentation for the w1_therm slave device David Fries
2008-03-30 11:32 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 10/35] W1: be able to manually add and remove slaves David Fries
2008-03-30 11:33 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 11/35] W1: recode w1_slave_found logic David Fries
2008-03-28 12:25 ` [PATCH 12/35] W1: new module parameter search_count David Fries
2008-03-28 12:25 ` [PATCH 13/35] W1: Document add, remove, and search_count David Fries
2008-03-30 11:33 ` Evgeniy Polyakov
2008-03-28 12:25 ` [PATCH 14/35] W1: w1_slave_read_id multiple short read bug David Fries
2008-03-28 12:26 ` [PATCH 15/35] W1: w1_slave_read_id from bin_attribute to device_attribute David Fries
2008-03-28 12:26 ` [PATCH 16/35] W1: w1_therm fix user buffer overflow and cat David Fries
2008-03-30 11:34 ` Evgeniy Polyakov
2008-03-28 12:26 ` [PATCH 17/35] W1: w1_family, remove unused variable need_exit David Fries
2008-03-28 12:26 ` [PATCH 18/35] W1: w1_therm consistent mutex access code cleanup David Fries
2008-03-28 12:26 ` [PATCH 19/35] W1: w1_int.c use first available master number David Fries
2008-03-28 12:26 ` [PATCH 20/35] W1: w1.c s/printk/dev_dbg/ David Fries
2008-03-30 11:35 ` Evgeniy Polyakov
2008-03-28 12:26 ` [PATCH 21/35] W1: w1_io.c reset comments and msleep David Fries
2008-03-30 11:36 ` Evgeniy Polyakov
2008-03-28 12:27 ` [PATCH 22/35] W1: ds1wm.c msleep for reset David Fries
2008-03-30 11:38 ` Evgeniy Polyakov
2008-03-30 13:43 ` David Fries
2008-03-28 12:27 ` [PATCH 23/35] W1: ds2490.c correct print message David Fries
2008-03-28 12:27 ` [PATCH 24/35] W1: ds2490.c add support for strong pullup David Fries
2008-03-28 12:27 ` [PATCH 25/35] W1: ds2490.c fix grouping error in ds_write_bit David Fries
2008-03-28 12:27 ` [PATCH 26/35] W1: ds2490.c ds_write_bit disable readback David Fries
2008-03-28 12:27 ` [PATCH 27/35] W1: ds2490.c disable bit read and write David Fries
2008-03-28 12:27 ` [PATCH 28/35] W1: ds2490.c simplify and fix ds_touch_bit David Fries
2008-03-28 12:27 ` [PATCH 29/35] W1: ds2490.c ds_dump_status rework David Fries
2008-03-28 12:27 ` [PATCH 30/35] W1: ds2490.c ds_reset remove ds_wait_status David Fries
2008-03-28 12:27 ` [PATCH 31/35] W1: ds2490.c reset ds2490 in init David Fries
2008-03-28 12:27 ` [PATCH 32/35] W1: ds2490.c magic number work David Fries
2008-03-28 12:27 ` [PATCH 33/35] W1: ds2490.c ds_write_block remove extra ds_wait_status David Fries
2008-03-28 12:27 ` [PATCH 34/35] W1: Documentation/w1/masters/ds2490 update David Fries
2008-03-30 11:43 ` Evgeniy Polyakov
2008-04-13 23:09 ` David Fries
2008-03-28 12:28 ` David Fries [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080328122804.GJ3613@spacedout.fries.net \
--to=david@fries.net \
--cc=johnpol@2ka.mipt.ru \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox