diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2007-02-06 16:29:21 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-08 15:38:57 -0500 |
commit | 6b31a515e3401685cdab2eeb6692f1a0f53f72ca (patch) | |
tree | ad8bcb3bb7b9974fdd18c5c8f976fc23680be620 /drivers/net/tg3.c | |
parent | 0f08461ebf89e10f7db9042fb028359b810c3c81 (diff) |
[TG3]: Avoid an expensive divide.
During an oprofile session of linux-2.6.20 on a dual opteron system, I noticed
an expensive divide was done in tg3_poll().
I am using gcc-4.1.1, so the following comment from drivers/net/tg3.c seems
over-optimistic :
/* Do not place this n-ring entries value into the tp struct itself,
* we really want to expose these constants to GCC so that modulo et
* al. operations are done with shifts and masks instead of with
* hw multiply/modulo instructions. Another solution would be to
* replace things like '% foo' with '& (foo - 1)'.
*/
#define TG3_RX_RCB_RING_SIZE(tp) \
((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024)
Assembly code before patch :
(oprofile results included)
6434 0.0088 :ffffffff803684b9: mov 0x6f0(%r15),%eax
587 8.0e-04 :ffffffff803684c0: and $0x40000,%eax
2170 0.0030 :ffffffff803684c5: cmp $0x1,%eax
:ffffffff803684c8: lea 0x1(%r13),%eax
:ffffffff803684cc: sbb %ecx,%ecx
2051 0.0028 :ffffffff803684ce: xor %edx,%edx
:ffffffff803684d0: and $0x200,%ecx
20 2.7e-05 :ffffffff803684d6: add $0x200,%ecx
1986 0.0027 :ffffffff803684dc: div %ecx
103427 0.1410 :ffffffff803684de: cmp %edx,0xffffffffffffff7c(%rbp)
Assembly code after the suggested patch :
ffffffff803684b9: mov 0x6f0(%r15),%eax
ffffffff803684c0: and $0x40000,%eax
ffffffff803684c5: cmp $0x1,%eax
ffffffff803684c8: sbb %eax,%eax
ffffffff803684ca: inc %r13d
ffffffff803684cd: and $0x200,%eax
ffffffff803684d2: add $0x1ff,%eax
ffffffff803684d7: and %eax,%r13d
ffffffff803684da: cmp %r13d,0xffffffffffffff7c(%rbp)
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Acked-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 135c0987deae..e136bae61970 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3380,7 +3380,7 @@ next_pkt: | |||
3380 | } | 3380 | } |
3381 | next_pkt_nopost: | 3381 | next_pkt_nopost: |
3382 | sw_idx++; | 3382 | sw_idx++; |
3383 | sw_idx %= TG3_RX_RCB_RING_SIZE(tp); | 3383 | sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1); |
3384 | 3384 | ||
3385 | /* Refresh hw_idx to see if there is new work */ | 3385 | /* Refresh hw_idx to see if there is new work */ |
3386 | if (sw_idx == hw_idx) { | 3386 | if (sw_idx == hw_idx) { |