* [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus @ 2012-01-20 11:46 Olivier Sobrie [not found] ` <1327060014-7604-1-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Olivier Sobrie @ 2012-01-20 11:46 UTC (permalink / raw) To: linux-i2c-u79uwXL29TY76Z2rM5mHXA Cc: Jean Delvare, Ben Dooks, Wolfram Sang, Olivier Sobrie Generally it is not needed to wait for 1 msec, the SMBus get often ready in less than 200 usecs. msleep(1) can wait up to 20 msecs... It has a significant impact when there is a burst of transactions on the bus. Signed-off-by: Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> --- drivers/i2c/busses/i2c-isch.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 6561d27..f90a605 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -47,7 +47,7 @@ #define SMBBLKDAT (0x20 + sch_smba) /* Other settings */ -#define MAX_TIMEOUT 500 +#define MAX_RETRIES 5000 /* I2C constants */ #define SCH_QUICK 0x00 @@ -68,7 +68,7 @@ static int sch_transaction(void) { int temp; int result = 0; - int timeout = 0; + int retries = 0; dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), @@ -100,12 +100,12 @@ static int sch_transaction(void) outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); do { - msleep(1); + usleep_range(100, 200); temp = inb(SMBHSTSTS) & 0x0f; - } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); + } while ((temp & 0x08) && (retries++ < MAX_RETRIES)); /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { + if (retries > MAX_RETRIES) { dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
[parent not found: <1327060014-7604-1-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>]
* Re: [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus [not found] ` <1327060014-7604-1-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> @ 2012-01-23 15:26 ` Jean Delvare [not found] ` <20120123162620.031ade7f-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Jean Delvare @ 2012-01-23 15:26 UTC (permalink / raw) To: Olivier Sobrie; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Ben Dooks, Wolfram Sang Salut Olivier, On Fri, 20 Jan 2012 12:46:54 +0100, Olivier Sobrie wrote: > Generally it is not needed to wait for 1 msec, the SMBus get often ready > in less than 200 usecs. The code change looks OK but the patch description not really. The loop you're changing is waiting for command completion, it isn't checking for bus business, regardless of what the comment in the code says. What about: i2c-isch: Decrease delay in command completion check loop If this is OK with you I'll apply your patch with this description. > msleep(1) can wait up to 20 msecs... It has a significant impact when > there is a burst of transactions on the bus. To be honest I didn't know about usleep_range(). Probably the same change could apply to a number of polled SMBus controller drivers, starting with i2c-i801. I'll give it a try... Of course it's nowhere as good as switching the drivers to be interrupt-driven. Did you check if you patch had any impact in terms of CPU load? I'm also curious what happens on systems without high resolution timer support, as apparently usleep_range() is implemented in terms of these. I admit I am surprised that usleep_range() is unconditionally available given that. > Signed-off-by: Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> > --- > drivers/i2c/busses/i2c-isch.c | 10 +++++----- > 1 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c > index 6561d27..f90a605 100644 > --- a/drivers/i2c/busses/i2c-isch.c > +++ b/drivers/i2c/busses/i2c-isch.c > @@ -47,7 +47,7 @@ > #define SMBBLKDAT (0x20 + sch_smba) > > /* Other settings */ > -#define MAX_TIMEOUT 500 > +#define MAX_RETRIES 5000 > > /* I2C constants */ > #define SCH_QUICK 0x00 > @@ -68,7 +68,7 @@ static int sch_transaction(void) > { > int temp; > int result = 0; > - int timeout = 0; > + int retries = 0; > > dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " > "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), > @@ -100,12 +100,12 @@ static int sch_transaction(void) > outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); > > do { > - msleep(1); > + usleep_range(100, 200); > temp = inb(SMBHSTSTS) & 0x0f; > - } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); > + } while ((temp & 0x08) && (retries++ < MAX_RETRIES)); > > /* If the SMBus is still busy, we give up */ > - if (timeout > MAX_TIMEOUT) { > + if (retries > MAX_RETRIES) { > dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); > result = -ETIMEDOUT; > } -- Jean Delvare ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <20120123162620.031ade7f-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>]
* Re: [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus [not found] ` <20120123162620.031ade7f-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> @ 2012-01-24 8:46 ` Olivier Sobrie 2012-01-24 9:58 ` Jean Delvare 0 siblings, 1 reply; 6+ messages in thread From: Olivier Sobrie @ 2012-01-24 8:46 UTC (permalink / raw) To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Ben Dooks, Wolfram Sang Salut Jean, On Mon, Jan 23, 2012 at 04:26:20PM +0100, Jean Delvare wrote: > On Fri, 20 Jan 2012 12:46:54 +0100, Olivier Sobrie wrote: > > Generally it is not needed to wait for 1 msec, the SMBus get often ready > > in less than 200 usecs. > > The code change looks OK but the patch description not really. The loop > you're changing is waiting for command completion, it isn't checking > for bus business, regardless of what the comment in the code says. What > about: > > i2c-isch: Decrease delay in command completion check loop > > If this is OK with you I'll apply your patch with this description. It's OK for me. Sorry for the wrong description. Indeed yours looks better ! > > msleep(1) can wait up to 20 msecs... It has a significant impact when > > there is a burst of transactions on the bus. > > To be honest I didn't know about usleep_range(). Probably the same > change could apply to a number of polled SMBus controller drivers, > starting with i2c-i801. I'll give it a try... Indeed I saw there are a lot of msleep(1) in the i2c drivers. As I only have an intel SMBus I cannot test it for others i2c busses. I choose to use usleep_range() as the documentation located in Documentation/timers/timers-howto.txt of the kernel tree says to use this function in the case of a sleep between 10us and 20ms... > Of course it's nowhere as good as switching the drivers to be > interrupt-driven. Did you check if you patch had any impact in terms of > CPU load? I'm also curious what happens on systems without high > resolution timer support, as apparently usleep_range() is implemented > in terms of these. I admit I am surprised that usleep_range() is > unconditionally available given that. I didn't check the CPU load. But I assume there will be no difference in my case as the timer is generally fired only one time. For info, I tested this change with a touchscreen device for which I've to perform a lot of i2c_smbus_read_byte() to read touch data. I'll have a look at the CPU load. By the way if you've a good idea how to have relevant measures I'm interested in. Concerning the system without hrtimers support, I just did a test and the performances decrease! It introduces again a long delay... which is not the case if I do a udelay(100)... Thanks for your comments and have a nice day! -- Olivier Sobrie ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus 2012-01-24 8:46 ` Olivier Sobrie @ 2012-01-24 9:58 ` Jean Delvare [not found] ` <20120124105838.08c2a652-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Jean Delvare @ 2012-01-24 9:58 UTC (permalink / raw) To: Olivier Sobrie; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Ben Dooks, Wolfram Sang On Tue, 24 Jan 2012 09:46:41 +0100, Olivier Sobrie wrote: > On Mon, Jan 23, 2012 at 04:26:20PM +0100, Jean Delvare wrote: > > The code change looks OK but the patch description not really. The loop > > you're changing is waiting for command completion, it isn't checking > > for bus business, regardless of what the comment in the code says. What > > about: > > > > i2c-isch: Decrease delay in command completion check loop > > > > If this is OK with you I'll apply your patch with this description. > > It's OK for me. Sorry for the wrong description. > Indeed yours looks better ! OK, changed. I have queued your patch for kernel 3.4, it will be in linux-next until then. If adjustments are needed, feel free to send an update. http://khali.linux-fr.org/devel/linux-3/jdelvare-i2c/i2c-isch-decrease-delay-in-command-completion-check-loop.patch > > To be honest I didn't know about usleep_range(). Probably the same > > change could apply to a number of polled SMBus controller drivers, > > starting with i2c-i801. I'll give it a try... > > Indeed I saw there are a lot of msleep(1) in the i2c drivers. > As I only have an intel SMBus I cannot test it for others i2c busses. > I choose to use usleep_range() as the documentation located in > Documentation/timers/timers-howto.txt of the kernel tree says to use > this function in the case of a sleep between 10us and 20ms... And quite rightly so. Note that usleep_range() did not exist when most of these drivers were originally written, so the use of msleep(1) is by default and not a design decision. Using usleep_range() is certainly the right thing to do in most of them these days (or convert them to use interrupts, of course.) > (...) > I didn't check the CPU load. But I assume there will be no difference > in my case as the timer is generally fired only one time. In my own tests, the CPU load seems to increase slightly, most probably because I use i2c_smbus_read_byte_data() which is a longer transaction than yours so the timer is fired several times (2 or 3) per transaction. If I change the range from (100, 200) to (250, 500) then I'm almost back to the original CPU load figures, modulo measurement noise, with almost the same speed benefit. As the optimal range depends on the SMBus frequency and the transaction, it seems a little difficult to optimize. We can settle on a per-driver range, and anyone not happy with it will have to work on interrupt support ;) > For info, I tested this change with a touchscreen device for which I've > to perform a lot of i2c_smbus_read_byte() to read touch data. > I'll have a look at the CPU load. By the way if you've a good idea how > to have relevant measures I'm interested in. I am using the i2c-dev driver + i2cdump (from the i2c-tools package) on an arbitrary SMBus slave on my SMBus. I'm measuring the time it takes to dump all the register space: # modprobe i2c-dev # time for i in `seq 1 10` ; do i2cdump -y 8 0x2f b > /dev/null ; done real 0m5.139s user 0m0.016s sys 0m0.118s This was with the original i2c-i801 driver. "real" tells me how fast register reads actually are (2560 reads in 5.139 s -> 2 ms/read on average), and "sys" how much they cost in terms of CPU. "user" can be ignored. With usleep_range(100, 200) I get: real 0m1.448s user 0m0.006s sys 0m0.150s So you can see it's much faster (0.57 ms/read) but costs more CPU. With usleep_range(250, 500) I get: real 0m1.587s user 0m0.003s sys 0m0.124s That's 0.62 ms/read. And finally with usleep_range(400, 700) I get: real 0m2.043s user 0m0.007s sys 0m0.118s The speed/CPU tradeoff is visible, and I think I'll go with usleep_range(250, 500). Of course if you want more accurate measurements you want to do more iterations and probably use better statistical analysis than the sum I did. > Concerning the system without hrtimers support, I just did a test and > the performances decrease! It introduces again a long delay... which is > not the case if I do a udelay(100)... But udelay() is busy-waiting so it would have an unacceptable CPU cost especially on large transactions. Question is, is usleep_range(100, 200) without hrtimers support slower than msleep(1)? If not then we're fine. If it is slower then that would be a bug in the implementation of usleep_range(), as it really shouldn't be each driver's job to check for this individually. -- Jean Delvare ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <20120124105838.08c2a652-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>]
* Re: [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus [not found] ` <20120124105838.08c2a652-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> @ 2012-01-24 14:07 ` Olivier Sobrie 2012-01-24 16:04 ` Jean Delvare 0 siblings, 1 reply; 6+ messages in thread From: Olivier Sobrie @ 2012-01-24 14:07 UTC (permalink / raw) To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Ben Dooks, Wolfram Sang On Tue, Jan 24, 2012 at 10:58:38AM +0100, Jean Delvare wrote: > OK, changed. I have queued your patch for kernel 3.4, it will be in > linux-next until then. If adjustments are needed, feel free to send an > update. > > http://khali.linux-fr.org/devel/linux-3/jdelvare-i2c/i2c-isch-decrease-delay-in-command-completion-check-loop.patch Ok thanks! > > (...) > > I didn't check the CPU load. But I assume there will be no difference > > in my case as the timer is generally fired only one time. > > In my own tests, the CPU load seems to increase slightly, most probably > because I use i2c_smbus_read_byte_data() which is a longer transaction > than yours so the timer is fired several times (2 or 3) per > transaction. If I change the range from (100, 200) to (250, 500) then > I'm almost back to the original CPU load figures, modulo measurement > noise, with almost the same speed benefit. > > As the optimal range depends on the SMBus frequency and the transaction, > it seems a little difficult to optimize. We can settle on a per-driver > range, and anyone not happy with it will have to work on interrupt > support ;) > > > For info, I tested this change with a touchscreen device for which I've > > to perform a lot of i2c_smbus_read_byte() to read touch data. > > I'll have a look at the CPU load. By the way if you've a good idea how > > to have relevant measures I'm interested in. > > I am using the i2c-dev driver + i2cdump (from the i2c-tools package) on > an arbitrary SMBus slave on my SMBus. I'm measuring the time it takes > to dump all the register space: > > # modprobe i2c-dev > # time for i in `seq 1 10` ; do i2cdump -y 8 0x2f b > /dev/null ; done > > real 0m5.139s > user 0m0.016s > sys 0m0.118s > > This was with the original i2c-i801 driver. "real" tells me how fast > register reads actually are (2560 reads in 5.139 s -> 2 ms/read on > average), and "sys" how much they cost in terms of CPU. "user" can be > ignored. With usleep_range(100, 200) I get: > > real 0m1.448s > user 0m0.006s > sys 0m0.150s > > So you can see it's much faster (0.57 ms/read) but costs more CPU. With > usleep_range(250, 500) I get: > > real 0m1.587s > user 0m0.003s > sys 0m0.124s > > That's 0.62 ms/read. And finally with usleep_range(400, 700) I get: > > real 0m2.043s > user 0m0.007s > sys 0m0.118s > > The speed/CPU tradeoff is visible, and I think I'll go with > usleep_range(250, 500). > > Of course if you want more accurate measurements you want to do more > iterations and probably use better statistical analysis than the sum I > did. I performed the same test you did on my system and I observed this: * msleep(1) real 0m 51.20s user 0m 0.29s sys 0m 0.00s * usleep_range(100, 200) real 0m 1.46s user 0m 0.10s sys 0m 0.10s * usleep_range(250, 500) real 0m 2.01s user 0m 0.05s sys 0m 0.25s * usleep_range(50, 150) real 0m 1.43s user 0m 0.07s sys 0m 0.23s I think usleep_range(100, 200) is the best compromise. > > Concerning the system without hrtimers support, I just did a test and > > the performances decrease! It introduces again a long delay... which is > > not the case if I do a udelay(100)... > > But udelay() is busy-waiting so it would have an unacceptable CPU cost > especially on large transactions. Question is, is usleep_range(100, > 200) without hrtimers support slower than msleep(1)? If not then we're > fine. If it is slower then that would be a bug in the implementation of > usleep_range(), as it really shouldn't be each driver's job to check > for this individually. I agree udelay() is not a good solution! I did the test without hrtimers using usleep_range(100, 200) and got: real 0m 25.60s user 0m 0.30s sys 0m 0.00s So that's not slower than msleep(1) in the case of no hrtimers. -- Olivier Sobrie ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus 2012-01-24 14:07 ` Olivier Sobrie @ 2012-01-24 16:04 ` Jean Delvare 0 siblings, 0 replies; 6+ messages in thread From: Jean Delvare @ 2012-01-24 16:04 UTC (permalink / raw) To: Olivier Sobrie; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Ben Dooks, Wolfram Sang On Tue, 24 Jan 2012 15:07:50 +0100, Olivier Sobrie wrote: > I performed the same test you did on my system and I observed this: > > * msleep(1) > real 0m 51.20s > user 0m 0.29s > sys 0m 0.00s I assume your kernel has HZ=100, that means 20 ms per transaction i.e. 2 jiffies, as expected from the msleep() implementation. > > * usleep_range(100, 200) > real 0m 1.46s > user 0m 0.10s > sys 0m 0.10s > > * usleep_range(250, 500) > real 0m 2.01s > user 0m 0.05s > sys 0m 0.25s It's really curious that this can take more CPU time than usleep_range(100, 200). I can't explain it. > > * usleep_range(50, 150) > real 0m 1.43s > user 0m 0.07s > sys 0m 0.23s > > I think usleep_range(100, 200) is the best compromise. I agree. > (...) > I agree udelay() is not a good solution! > I did the test without hrtimers using usleep_range(100, 200) and got: > real 0m 25.60s > user 0m 0.30s > sys 0m 0.00s > So that's not slower than msleep(1) in the case of no hrtimers. In fact that's exactly twice as fast as msleep(2), i.e. 1 jiffy per transaction instead of 2. That's pretty good that there is a benefit even without hrtimers support. Thanks for testing and reporting, that's one less thing on my to-do list :) I'll send a patch similar to yours for the i2c-i801 driver in a minute. Thanks for showing us the way! -- Jean Delvare ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-01-24 16:04 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-01-20 11:46 [PATCH] i2c-isch: Decrease delay in the loop checking the BUSY state of the bus Olivier Sobrie [not found] ` <1327060014-7604-1-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> 2012-01-23 15:26 ` Jean Delvare [not found] ` <20120123162620.031ade7f-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> 2012-01-24 8:46 ` Olivier Sobrie 2012-01-24 9:58 ` Jean Delvare [not found] ` <20120124105838.08c2a652-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org> 2012-01-24 14:07 ` Olivier Sobrie 2012-01-24 16:04 ` Jean Delvare
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).