* [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer()
@ 2009-02-15 19:30 Sergei Shtylyov
2009-02-15 19:48 ` Jeff Garzik
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Sergei Shtylyov @ 2009-02-15 19:30 UTC (permalink / raw)
To: jgarzik; +Cc: linux-ide, linux-kernel, alan
Handling of the trailing byte in ata_sff_data_xfer() is suboptimal bacause:
- it always initializes the padding buffer to 0 which is not really needed in
both the read and write cases;
- it has to use memcpy() to transfer a single byte from/to the padding buffer;
- it uses io{read|write}16() accessors which swap bytes on the big endian CPUs
and so have to additionally convert the data from/to the little endian format
instead of using io{read|write}16_rep() accessors which are not supposed to
change the byte ordering.
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
---
Oops, the subject got truncated -- resending...
The patch is against the recent Linus' tree but should apply to applicable
branch in the libata tree where it should probably wait for the next merge
window...
drivers/ata/libata-sff.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
Index: linux-2.6/drivers/ata/libata-sff.c
===================================================================
--- linux-2.6.orig/drivers/ata/libata-sff.c
+++ linux-2.6/drivers/ata/libata-sff.c
@@ -723,17 +723,23 @@ unsigned int ata_sff_data_xfer(struct at
else
iowrite16_rep(data_addr, buf, words);
- /* Transfer trailing 1 byte, if any. */
+ /* Transfer trailing byte, if any. */
if (unlikely(buflen & 0x01)) {
- __le16 align_buf[1] = { 0 };
- unsigned char *trailing_buf = buf + buflen - 1;
+ unsigned char pad[2];
+ /* Point buf to the tail of buffer */
+ buf += buflen - 1;
+
+ /*
+ * Use io*16_rep() accessors here as well to avoid pointlessly
+ * swapping bytes to and fro on the big endian machines...
+ */
if (rw == READ) {
- align_buf[0] = cpu_to_le16(ioread16(data_addr));
- memcpy(trailing_buf, align_buf, 1);
+ ioread16_rep(data_addr, pad, 1);
+ *buf = pad[0];
} else {
- memcpy(align_buf, trailing_buf, 1);
- iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ pad[0] = *buf;
+ iowrite16_rep(data_addr, pad, 1);
}
words++;
}
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-02-15 19:30 [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() Sergei Shtylyov @ 2009-02-15 19:48 ` Jeff Garzik 2009-02-15 20:09 ` Sergei Shtylyov 2009-04-07 9:15 ` Sergei Shtylyov 2009-04-08 6:33 ` Jeff Garzik 2 siblings, 1 reply; 9+ messages in thread From: Jeff Garzik @ 2009-02-15 19:48 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: linux-ide, linux-kernel, alan Sergei Shtylyov wrote: > Handling of the trailing byte in ata_sff_data_xfer() is suboptimal bacause: > > - it always initializes the padding buffer to 0 which is not really needed in > both the read and write cases; > > - it has to use memcpy() to transfer a single byte from/to the padding buffer; Have you looked at the assembly, before deciding it is suboptiomal? gcc optimizes tiny arrays and structures quite well, and is well capable of seeing one path where the initialization is clobbered without a single read, and another code path where it is used. As for memcpy, for small and/or constant values that is quite often a compiler builtin. It is rarely useful, these days, to convert a memcpy() to a hand-rolled version of same. Jeff ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-02-15 19:48 ` Jeff Garzik @ 2009-02-15 20:09 ` Sergei Shtylyov 2009-02-17 18:07 ` Sergei Shtylyov 0 siblings, 1 reply; 9+ messages in thread From: Sergei Shtylyov @ 2009-02-15 20:09 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-ide, linux-kernel, alan Jeff Garzik wrote: >> Handling of the trailing byte in ata_sff_data_xfer() is suboptimal >> bacause: >> - it always initializes the padding buffer to 0 which is not really >> needed in >> both the read and write cases; >> - it has to use memcpy() to transfer a single byte from/to the padding >> buffer; > Have you looked at the assembly, before deciding it is suboptiomal? I'm estimating the code itself, not what the compiler can do to fix it. :-) > gcc optimizes tiny arrays and structures quite well, and is well capable > of seeing one path where the initialization is clobbered without a > single read, and another code path where it is used. The initialier just shouldn't have been there in the first place, clobbered or not. And let's looks at what gcc gave me: .L504: .loc 1 727 0 testb $1, %bl #, buflen jne .L511 #, [...] .L511: .LBB635: .loc 1 731 0 movl 8(%ebp), %eax # rw, .loc 1 729 0 leal (%esi,%ebx), %ebx #, tmp72 .LVL440: .loc 1 728 0 .LBB635: .loc 1 731 0 movl 8(%ebp), %eax # rw, .loc 1 729 0 leal (%esi,%ebx), %ebx #, tmp72 .LVL440: .loc 1 728 0 movw $0, -14(%ebp) #, align_buf .loc 1 731 0 testl %eax, %eax # jne .L507 #, .loc 1 732 0 movl -20(%ebp), %eax # data_addr, data_addr call ioread16 # movw %ax, -14(%ebp) # D.29224, align_buf .LBB629: .LBB630: .loc 4 60 0 movzbl -14(%ebp), %eax #, tmp73 movb %al, -1(%ebx) # tmp73, .L509: .LBE630: .LBE629: .loc 1 738 0 addl $1, %edi #, words jmp .L505 # .L507: .LBB631: .LBB632: .loc 4 60 0 movzbl -1(%ebx), %eax #, tmp74 .LBE632: .LBE631: .loc 1 736 0 movzwl -14(%ebp), %eax # align_buf, align_buf call iowrite16 # jmp .L509 # As you can see, it happily assigned 0 to align_buf[0] at .LVL440, regardless of the value of 'rw'. > As for memcpy, for small and/or constant values that is quite often a > compiler builtin. It is rarely useful, these days, to convert a memcpy() to a hand-rolled version of same. Here memcpy() just shouldn't have appeared in the first place. But indeed, gcc did optimize it away. > Jeff MBR, Sergei ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-02-15 20:09 ` Sergei Shtylyov @ 2009-02-17 18:07 ` Sergei Shtylyov 0 siblings, 0 replies; 9+ messages in thread From: Sergei Shtylyov @ 2009-02-17 18:07 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-ide, linux-kernel, alan Hello, I wrote: >>> Handling of the trailing byte in ata_sff_data_xfer() is suboptimal >>> bacause: >>> - it always initializes the padding buffer to 0 which is not really >>> needed in >>> both the read and write cases; >>> - it has to use memcpy() to transfer a single byte from/to the >>> padding buffer; >> Have you looked at the assembly, before deciding it is suboptiomal? > I'm estimating the code itself, not what the compiler can do to fix > it. :-) >> gcc optimizes tiny arrays and structures quite well, and is well >> capable of seeing one path where the initialization is clobbered >> without a single read, and another code path where it is used. > The initialier just shouldn't have been there in the first place, > clobbered or not. And let's looks at what gcc gave me: [...] >> As for memcpy, for small and/or constant values that is quite often a >> compiler builtin. It is rarely useful, these days, to convert a >> memcpy() to a hand-rolled > version of same. > Here memcpy() just shouldn't have appeared in the first place. But > indeed, gcc did optimize it away. In fact, we could do without both memcpy and io*15_rep() I think: if (unlikely(buflen & 0x01)) { u16 pad; /* Point buf to the tail of buffer */ buf += buflen - 1; /* * Copy from/to pad's LSB only (host order), * dropping its MSB or zero-extending it... */ if (rw == READ) { pad = ioread16(data_addr); *buf = (unsigned char)pad; } else { pad = *buf; iowrite16(pad, data_addr); } } It should work -- that easy... although io{read|write}16() will still byte-swap. >> Jeff MBR, Sergei ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-02-15 19:30 [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() Sergei Shtylyov 2009-02-15 19:48 ` Jeff Garzik @ 2009-04-07 9:15 ` Sergei Shtylyov 2009-06-01 19:31 ` Sergei Shtylyov 2009-04-08 6:33 ` Jeff Garzik 2 siblings, 1 reply; 9+ messages in thread From: Sergei Shtylyov @ 2009-04-07 9:15 UTC (permalink / raw) To: jgarzik; +Cc: linux-ide, linux-kernel, alan Hello, I wrote: > Handling of the trailing byte in ata_sff_data_xfer() is suboptimal bacause: > > - it always initializes the padding buffer to 0 which is not really needed in > both the read and write cases; > > - it has to use memcpy() to transfer a single byte from/to the padding buffer; > > - it uses io{read|write}16() accessors which swap bytes on the big endian CPUs > and so have to additionally convert the data from/to the little endian format > instead of using io{read|write}16_rep() accessors which are not supposed to > change the byte ordering. > > Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Jeff, have you forgotten about this one? MBR, Sergei ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-04-07 9:15 ` Sergei Shtylyov @ 2009-06-01 19:31 ` Sergei Shtylyov 2009-06-11 18:19 ` Jeff Garzik 0 siblings, 1 reply; 9+ messages in thread From: Sergei Shtylyov @ 2009-06-01 19:31 UTC (permalink / raw) To: jgarzik; +Cc: linux-ide, linux-kernel, alan Hello, I wrote: >> Handling of the trailing byte in ata_sff_data_xfer() is suboptimal >> bacause: >> - it always initializes the padding buffer to 0 which is not really >> needed in >> both the read and write cases; >> - it has to use memcpy() to transfer a single byte from/to the padding >> buffer; >> - it uses io{read|write}16() accessors which swap bytes on the big >> endian CPUs >> and so have to additionally convert the data from/to the little >> endian format >> instead of using io{read|write}16_rep() accessors which are not >> supposed to >> change the byte ordering. >> >> Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> > Jeff, have you forgotten about this one? PING. MBR, Sergei ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-06-01 19:31 ` Sergei Shtylyov @ 2009-06-11 18:19 ` Jeff Garzik 2009-06-11 18:28 ` Sergei Shtylyov 0 siblings, 1 reply; 9+ messages in thread From: Jeff Garzik @ 2009-06-11 18:19 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: linux-ide, linux-kernel, alan Sergei Shtylyov wrote: > Hello, I wrote: > >>> Handling of the trailing byte in ata_sff_data_xfer() is suboptimal >>> bacause: > >>> - it always initializes the padding buffer to 0 which is not really >>> needed in >>> both the read and write cases; > >>> - it has to use memcpy() to transfer a single byte from/to the >>> padding buffer; > >>> - it uses io{read|write}16() accessors which swap bytes on the big >>> endian CPUs >>> and so have to additionally convert the data from/to the little >>> endian format >>> instead of using io{read|write}16_rep() accessors which are not >>> supposed to >>> change the byte ordering. >>> >>> Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> > >> Jeff, have you forgotten about this one? > > PING. This has been queued to libata-dev.git#upstream, i.e. linux-next queue, for a long time. Apologies if I forgot the 'applied' reply. Just sent this upstream, as linux-ide should show. Jeff ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-06-11 18:19 ` Jeff Garzik @ 2009-06-11 18:28 ` Sergei Shtylyov 0 siblings, 0 replies; 9+ messages in thread From: Sergei Shtylyov @ 2009-06-11 18:28 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-ide, linux-kernel, alan Hello. Jeff Garzik wrote: >> Hello, I wrote: >>>> Handling of the trailing byte in ata_sff_data_xfer() is suboptimal >>>> bacause: >>>> - it always initializes the padding buffer to 0 which is not really >>>> needed in >>>> both the read and write cases; >>>> - it has to use memcpy() to transfer a single byte from/to the >>>> padding buffer; >>>> - it uses io{read|write}16() accessors which swap bytes on the big >>>> endian CPUs >>>> and so have to additionally convert the data from/to the little >>>> endian format >>>> instead of using io{read|write}16_rep() accessors which are not >>>> supposed to >>>> change the byte ordering. >>>> >>>> Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> >>> Jeff, have you forgotten about this one? >> PING. > This has been queued to libata-dev.git#upstream, i.e. linux-next queue, Ah, haven't looked there, so it appeared as forgotten since I know you usually reply with 'applied'. > for a long time. Apologies if I forgot the 'applied' reply. > Just sent this upstream, as linux-ide should show. Thanks. I began to think of reworking it to avoid even io*_rep() as per my followup mail and resending... well, it's good enogh as is. :-) > Jeff MBR, Sergei ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() 2009-02-15 19:30 [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() Sergei Shtylyov 2009-02-15 19:48 ` Jeff Garzik 2009-04-07 9:15 ` Sergei Shtylyov @ 2009-04-08 6:33 ` Jeff Garzik 2 siblings, 0 replies; 9+ messages in thread From: Jeff Garzik @ 2009-04-08 6:33 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: linux-ide, linux-kernel, alan Sergei Shtylyov wrote: > Handling of the trailing byte in ata_sff_data_xfer() is suboptimal bacause: > > - it always initializes the padding buffer to 0 which is not really needed in > both the read and write cases; > > - it has to use memcpy() to transfer a single byte from/to the padding buffer; > > - it uses io{read|write}16() accessors which swap bytes on the big endian CPUs > and so have to additionally convert the data from/to the little endian format > instead of using io{read|write}16_rep() accessors which are not supposed to > change the byte ordering. > > Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> applied ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-06-11 18:26 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-02-15 19:30 [PATCH 2/2 resend] libata-sff: avoid byte swapping in ata_sff_data_xfer() Sergei Shtylyov 2009-02-15 19:48 ` Jeff Garzik 2009-02-15 20:09 ` Sergei Shtylyov 2009-02-17 18:07 ` Sergei Shtylyov 2009-04-07 9:15 ` Sergei Shtylyov 2009-06-01 19:31 ` Sergei Shtylyov 2009-06-11 18:19 ` Jeff Garzik 2009-06-11 18:28 ` Sergei Shtylyov 2009-04-08 6:33 ` Jeff Garzik
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).