Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67974231 authored by Ion Badulescu's avatar Ion Badulescu Committed by Jeff Garzik
Browse files

[netdrvr starfire] fix highmem and broken firmware issues



Unfortunately, [your patch] might address the crash but doesn't address
the real problem. It turns out that the problem is one of padding
(the firmware cksum engine works only on 32-bit chunks, yuck), so
the special casing for length == 1 wasn't sufficient anyway.

This patch addresses the issue, as well the other issue of i386 +
CONFIG_HIGHMEM being broken. It is pretty much the same workaround
that Adaptec themselves used in their Windows driver. I have yet to
check if it fixes the problem when the skb is non-linear, but this
patch _will_ solve the problem for 99% of the users out there (those
not using sendfile).

Signed-off-by: default avatarIon Badulescu <ionut@badula.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 32fa2bfc
Loading
Loading
Loading
Loading
+24 −22
Original line number Original line Diff line number Diff line
@@ -133,14 +133,18 @@
	- finally added firmware (GPL'ed by Adaptec)
	- finally added firmware (GPL'ed by Adaptec)
	- removed compatibility code for 2.2.x
	- removed compatibility code for 2.2.x


	LK1.4.2.1 (Ion Badulescu)
	- fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM
	- added 32-bit padding to outgoing skb's, removed previous workaround

TODO:	- fix forced speed/duplexing code (broken a long time ago, when
TODO:	- fix forced speed/duplexing code (broken a long time ago, when
	somebody converted the driver to use the generic MII code)
	somebody converted the driver to use the generic MII code)
	- fix VLAN support
	- fix VLAN support
*/
*/


#define DRV_NAME	"starfire"
#define DRV_NAME	"starfire"
#define DRV_VERSION	"1.03+LK1.4.2"
#define DRV_VERSION	"1.03+LK1.4.2.1"
#define DRV_RELDATE	"January 19, 2005"
#define DRV_RELDATE	"October 3, 2005"


#include <linux/config.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/version.h>
@@ -165,6 +169,14 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when
 * of length 1. If and when this is fixed, the #define below can be removed.
 * of length 1. If and when this is fixed, the #define below can be removed.
 */
 */
#define HAS_BROKEN_FIRMWARE
#define HAS_BROKEN_FIRMWARE

/*
 * If using the broken firmware, data must be padded to the next 32-bit boundary.
 */
#ifdef HAS_BROKEN_FIRMWARE
#define PADDING_MASK 3
#endif

/*
/*
 * Define this if using the driver with the zero-copy patch
 * Define this if using the driver with the zero-copy patch
 */
 */
@@ -257,9 +269,10 @@ static int full_duplex[MAX_UNITS] = {0, };
 * This SUCKS.
 * This SUCKS.
 * We need a much better method to determine if dma_addr_t is 64-bit.
 * We need a much better method to determine if dma_addr_t is 64-bit.
 */
 */
#if (defined(__i386__) && defined(CONFIG_HIGHMEM) && (LINUX_VERSION_CODE > 0x20500 || defined(CONFIG_HIGHMEM64G))) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
/* 64-bit dma_addr_t */
/* 64-bit dma_addr_t */
#define ADDR_64BITS	/* This chip uses 64 bit addresses. */
#define ADDR_64BITS	/* This chip uses 64 bit addresses. */
#define netdrv_addr_t u64
#define cpu_to_dma(x) cpu_to_le64(x)
#define cpu_to_dma(x) cpu_to_le64(x)
#define dma_to_cpu(x) le64_to_cpu(x)
#define dma_to_cpu(x) le64_to_cpu(x)
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
@@ -268,6 +281,7 @@ static int full_duplex[MAX_UNITS] = {0, };
#define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
#define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
#define RX_DESC_ADDR_SIZE RxDescAddr64bit
#define RX_DESC_ADDR_SIZE RxDescAddr64bit
#else  /* 32-bit dma_addr_t */
#else  /* 32-bit dma_addr_t */
#define netdrv_addr_t u32
#define cpu_to_dma(x) cpu_to_le32(x)
#define cpu_to_dma(x) cpu_to_le32(x)
#define dma_to_cpu(x) le32_to_cpu(x)
#define dma_to_cpu(x) le32_to_cpu(x)
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
@@ -1333,21 +1347,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
	}
	}


#if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
#if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
	{
	if (skb->ip_summed == CHECKSUM_HW) {
		int has_bad_length = 0;
		skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK);

		if (skb == NULL)
		if (skb_first_frag_len(skb) == 1)
			return NETDEV_TX_OK;
			has_bad_length = 1;
		else {
			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
				if (skb_shinfo(skb)->frags[i].size == 1) {
					has_bad_length = 1;
					break;
				}
		}

		if (has_bad_length)
			skb_checksum_help(skb, 0);
	}
	}
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */


@@ -2127,13 +2130,12 @@ static int __init starfire_init (void)
#endif
#endif
#endif
#endif


#ifndef ADDR_64BITS
	/* we can do this test only at run-time... sigh */
	/* we can do this test only at run-time... sigh */
	if (sizeof(dma_addr_t) == sizeof(u64)) {
	if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
		printk("This driver has not been ported to this 64-bit architecture yet\n");
		printk("This driver has dma_addr_t issues, please send email to maintainer\n");
		return -ENODEV;
		return -ENODEV;
	}
	}
#endif /* not ADDR_64BITS */

	return pci_module_init (&starfire_driver);
	return pci_module_init (&starfire_driver);
}
}