diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2005-10-28 18:14:52 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 19:06:44 -0400 |
commit | 2c36ed22c6f64de94c6c3b7258dd7285bb093401 (patch) | |
tree | bf8ab970180df5abe28d0c75d993a86a063bd8d5 /drivers/net/wireless/hermes.c | |
parent | 63f57fb69b017230c77c40f1713e40885ae6d159 (diff) |
[PATCH] Better fixup for the orinoco driver
The latest kernel added a pretty ugly fix for the orinoco etherleak bug
which contains bogus skb->len checks already done by the caller and causes
copies of all odd sized frames (which are quite common)
While the skb->len check should be ripped out the other fix is harder to do
properly so I'm proposing for this the -mm tree only until next 2.6.x so
that it gets tested.
Instead of copying buffers around blindly this code implements a padding
aware version of the hermes buffer writing function which does padding as
the buffer is loaded and thus more cleanly and without bogus 1.5K copies.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/wireless/hermes.c')
-rw-r--r-- | drivers/net/wireless/hermes.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index eba0d9d2b7c5..579480dad374 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c | |||
@@ -444,6 +444,43 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len, | |||
444 | return err; | 444 | return err; |
445 | } | 445 | } |
446 | 446 | ||
447 | /* Write a block of data to the chip's buffer with padding if | ||
448 | * neccessary, via the BAP. Synchronization/serialization is the | ||
449 | * caller's problem. len must be even. | ||
450 | * | ||
451 | * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware | ||
452 | */ | ||
453 | int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len, | ||
454 | u16 id, u16 offset) | ||
455 | { | ||
456 | int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; | ||
457 | int err = 0; | ||
458 | |||
459 | if (len < 0 || len % 2 || data_len > len) | ||
460 | return -EINVAL; | ||
461 | |||
462 | err = hermes_bap_seek(hw, bap, id, offset); | ||
463 | if (err) | ||
464 | goto out; | ||
465 | |||
466 | /* Transfer all the complete words of data */ | ||
467 | hermes_write_words(hw, dreg, buf, data_len/2); | ||
468 | /* If there is an odd byte left over pad and transfer it */ | ||
469 | if (data_len & 1) { | ||
470 | u8 end[2]; | ||
471 | end[1] = 0; | ||
472 | end[0] = ((unsigned char *)buf)[data_len - 1]; | ||
473 | hermes_write_words(hw, dreg, end, 1); | ||
474 | data_len ++; | ||
475 | } | ||
476 | /* Now send zeros for the padding */ | ||
477 | if (data_len < len) | ||
478 | hermes_clear_words(hw, dreg, (len - data_len) / 2); | ||
479 | /* Complete */ | ||
480 | out: | ||
481 | return err; | ||
482 | } | ||
483 | |||
447 | /* Read a Length-Type-Value record from the card. | 484 | /* Read a Length-Type-Value record from the card. |
448 | * | 485 | * |
449 | * If length is NULL, we ignore the length read from the card, and | 486 | * If length is NULL, we ignore the length read from the card, and |
@@ -531,6 +568,7 @@ EXPORT_SYMBOL(hermes_allocate); | |||
531 | 568 | ||
532 | EXPORT_SYMBOL(hermes_bap_pread); | 569 | EXPORT_SYMBOL(hermes_bap_pread); |
533 | EXPORT_SYMBOL(hermes_bap_pwrite); | 570 | EXPORT_SYMBOL(hermes_bap_pwrite); |
571 | EXPORT_SYMBOL(hermes_bap_pwrite_pad); | ||
534 | EXPORT_SYMBOL(hermes_read_ltv); | 572 | EXPORT_SYMBOL(hermes_read_ltv); |
535 | EXPORT_SYMBOL(hermes_write_ltv); | 573 | EXPORT_SYMBOL(hermes_write_ltv); |
536 | 574 | ||