diff options
author | Baruch Siach <baruch@tkos.co.il> | 2008-12-18 22:39:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-19 01:27:39 -0500 |
commit | 5664dd5561850df580414783cf3c8e0aa834c62e (patch) | |
tree | aac02f7e39a2adbac4920c131c1a49f6ddb571e2 /drivers/net/enc28j60.c | |
parent | b88a2a22c6670c31586d1a716255eae4c320b363 (diff) |
enc28j60: reduce the number of spi transfers in enc28j60_set_bank()
A major source of overhead in the enc28j60 driver is the SPI transfers. Each
SPI transfer entails two kernel thread context switches. One major source of
SPI transfers is the enc28j60_set_bank() functions which runs before every
register access. This patch reduces the number of SPI transfers that
enc28j60_set_bank() performs in two ways:
1. removes unnecessary bank switch for the registers that are present in all
banks
2. when switching from banks 0 or 3 to banks 1 or 2 (i.e. only one bit
changes) enc28j60_set_bank() does only one SPI transfer instead of two
According to my tests these changes reduce the number of SPI transfers in
about 25%.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/enc28j60.c')
-rw-r--r-- | drivers/net/enc28j60.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 535e14094971..b0ef46c51a9d 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c | |||
@@ -196,16 +196,32 @@ static void enc28j60_soft_reset(struct enc28j60_net *priv) | |||
196 | */ | 196 | */ |
197 | static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr) | 197 | static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr) |
198 | { | 198 | { |
199 | if ((addr & BANK_MASK) != priv->bank) { | 199 | u8 b = (addr & BANK_MASK) >> 5; |
200 | u8 b = (addr & BANK_MASK) >> 5; | ||
201 | 200 | ||
202 | if (b != (ECON1_BSEL1 | ECON1_BSEL0)) | 201 | /* These registers (EIE, EIR, ESTAT, ECON2, ECON1) |
202 | * are present in all banks, no need to switch bank | ||
203 | */ | ||
204 | if (addr >= EIE && addr <= ECON1) | ||
205 | return; | ||
206 | |||
207 | /* Clear or set each bank selection bit as needed */ | ||
208 | if ((b & ECON1_BSEL0) != (priv->bank & ECON1_BSEL0)) { | ||
209 | if (b & ECON1_BSEL0) | ||
210 | spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1, | ||
211 | ECON1_BSEL0); | ||
212 | else | ||
213 | spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1, | ||
214 | ECON1_BSEL0); | ||
215 | } | ||
216 | if ((b & ECON1_BSEL1) != (priv->bank & ECON1_BSEL1)) { | ||
217 | if (b & ECON1_BSEL1) | ||
218 | spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1, | ||
219 | ECON1_BSEL1); | ||
220 | else | ||
203 | spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1, | 221 | spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1, |
204 | ECON1_BSEL1 | ECON1_BSEL0); | 222 | ECON1_BSEL1); |
205 | if (b != 0) | ||
206 | spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1, b); | ||
207 | priv->bank = (addr & BANK_MASK); | ||
208 | } | 223 | } |
224 | priv->bank = b; | ||
209 | } | 225 | } |
210 | 226 | ||
211 | /* | 227 | /* |