summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2004-07-02 13:20:46 +0100
committerAnton Altaparmakov <aia21@cantab.net>2004-07-02 13:20:46 +0100
commit62054d49783cfe93c9cee9d90a0779f1f9054968 (patch)
tree63234ac22723c76b84e629390fb230d499f41151
parent639b1a19248ed0aeb364f64fecbd24042a559bac (diff)
parenta2d708b887c8d932734f3c4ec600269f1252a3d1 (diff)
Merge cantab.net:/home/src/ntfs-2.6-devel
into cantab.net:/home/src/ntfs-2.6
-rw-r--r--arch/i386/kernel/smpboot.c9
-rw-r--r--arch/i386/mm/init.c27
-rw-r--r--arch/i386/mm/pageattr.c2
-rw-r--r--crypto/Kconfig14
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/tcrypt.c21
-rw-r--r--crypto/tcrypt.h190
-rw-r--r--crypto/tea.c248
-rw-r--r--drivers/cdrom/cdrom.c1
-rw-r--r--drivers/md/dm-raid1.c6
-rw-r--r--drivers/md/dm.c112
-rw-r--r--drivers/md/kcopyd.c16
-rw-r--r--drivers/net/3c59x.c6
-rw-r--r--drivers/net/Kconfig25
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/acenic.c12
-rw-r--r--drivers/net/arm/Kconfig18
-rw-r--r--drivers/net/arm/Makefile1
-rw-r--r--drivers/net/eepro100.c6
-rw-r--r--drivers/net/epic100.c6
-rw-r--r--drivers/net/fec_8xx/Kconfig14
-rw-r--r--drivers/net/fec_8xx/Makefile12
-rw-r--r--drivers/net/fec_8xx/fec_8xx-netta.c153
-rw-r--r--drivers/net/fec_8xx/fec_8xx.h218
-rw-r--r--drivers/net/fec_8xx/fec_main.c1275
-rw-r--r--drivers/net/fec_8xx/fec_mii.c380
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/pcmcia/3c574_cs.c11
-rw-r--r--drivers/net/pcmcia/3c589_cs.c9
-rw-r--r--drivers/net/pcmcia/axnet_cs.c9
-rw-r--r--drivers/net/pcmcia/com20020_cs.c32
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c9
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c1
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c9
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c9
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c9
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c9
-rw-r--r--drivers/net/pcnet32.c61
-rw-r--r--drivers/net/sb1250-mac.c6
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h6
-rw-r--r--drivers/net/skfp/fplustm.c28
-rw-r--r--drivers/net/skfp/h/cmtdef.h4
-rw-r--r--drivers/net/skfp/h/targetos.h2
-rw-r--r--drivers/net/skfp/skfddi.c5
-rw-r--r--drivers/net/skfp/smt.c86
-rw-r--r--drivers/net/smc91x.c (renamed from drivers/net/arm/smc91x.c)2
-rw-r--r--drivers/net/smc91x.h (renamed from drivers/net/arm/smc91x.h)37
-rw-r--r--drivers/net/sundance.c9
-rw-r--r--drivers/net/tulip/winbond-840.c9
-rw-r--r--drivers/net/typhoon.c6
-rw-r--r--drivers/net/via-rhine.c6
-rw-r--r--drivers/net/wan/sbni.h2
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c4
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c7
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c8
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c124
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.h3
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c4
-rw-r--r--drivers/net/yellowfin.c8
-rw-r--r--include/asm-i386/pgtable.h22
-rw-r--r--include/asm-x86_64/bootsetup.h3
-rw-r--r--kernel/exit.c34
-rw-r--r--net/ipv4/ipconfig.c11
-rw-r--r--net/ipv4/netfilter/ip_tables.c2
-rw-r--r--net/ipv4/tcp_input.c8
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv4/tcp_timer.c2
-rw-r--r--sound/isa/gus/interwave.c2
70 files changed, 3050 insertions, 355 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 27bda2a137d5..1a9b08190492 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -82,6 +82,7 @@ int smp_threads_ready;
extern unsigned char trampoline_data [];
extern unsigned char trampoline_end [];
static unsigned char *trampoline_base;
+static int trampoline_exec;
/*
* Currently trivial. Write the real->protected mode
@@ -108,6 +109,10 @@ void __init smp_alloc_memory(void)
*/
if (__pa(trampoline_base) >= 0x9F000)
BUG();
+ /*
+ * Make the SMP trampoline executable:
+ */
+ trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1);
}
/*
@@ -1375,6 +1380,10 @@ void __init smp_cpus_done(unsigned int max_cpus)
setup_ioapic_dest();
#endif
zap_low_mappings();
+ /*
+ * Disable executability of the SMP trampoline:
+ */
+ set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
}
void __init smp_intr_init(void)
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index f8661fd97303..d492599dac6a 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -455,6 +455,33 @@ static void __init set_nx(void)
}
}
+/*
+ * Enables/disables executability of a given kernel page and
+ * returns the previous setting.
+ */
+int __init set_kernel_exec(unsigned long vaddr, int enable)
+{
+ pte_t *pte;
+ int ret = 1;
+
+ if (!nx_enabled)
+ goto out;
+
+ pte = lookup_address(vaddr);
+ BUG_ON(!pte);
+
+ if (pte_val(*pte) & _PAGE_NX)
+ ret = 0;
+
+ if (enable)
+ pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
+ else
+ pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);
+ __flush_tlb_all();
+out:
+ return ret;
+}
+
#endif
/*
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index af7c60285237..8eb95be7d771 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -17,7 +17,7 @@ static spinlock_t cpa_lock = SPIN_LOCK_UNLOCKED;
static struct list_head df_list = LIST_HEAD_INIT(df_list);
-static inline pte_t *lookup_address(unsigned long address)
+pte_t *lookup_address(unsigned long address)
{
pgd_t *pgd = pgd_offset_k(address);
pmd_t *pmd;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index d0ed3ce3e091..de13d3ffb7fe 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -152,6 +152,20 @@ config CRYPTO_CAST6
The CAST6 encryption algorithm (synonymous with CAST-256) is
described in RFC2612.
+config CRYPTO_TEA
+ tristate "TEA and XTEA cipher algorithms"
+ depends on CRYPTO
+ help
+ TEA cipher algorithm.
+
+ Tiny Encryption Algorithm is a simple cipher that uses
+ many rounds for security. It is very fast and uses
+ little memory.
+
+ Xtendend Tiny Encryption Algorithm is a modifcation to
+ the TEA algorithm to address a potential key weakness
+ in the TEA algorithm.
+
config CRYPTO_ARC4
tristate "ARC4 cipher algorithm"
depends on CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index 105429fd288e..f9310ae44741 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_CRYPTO_AES) += aes.o
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
+obj-$(CONFIG_CRYPTO_TEA) += tea.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 152ad41ce235..2124e23382d0 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -61,7 +61,7 @@ static char *tvmem;
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", "crc32c", NULL
+ "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL
};
static void
@@ -665,6 +665,15 @@ do_test(void)
test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+ //TEA
+ test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+ test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+
+
+ //XTEA
+ test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+ test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+
test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
test_deflate();
@@ -763,6 +772,16 @@ do_test(void)
test_crc32c();
break;
+ case 19:
+ test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+ test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+ break;
+
+ case 20:
+ test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+ test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 43563450c9c4..4f514295355e 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -1630,6 +1630,195 @@ struct cipher_testvec arc4_dec_tv_template[] =
},
};
+/*
+ * TEA test vectors
+ */
+#define TEA_ENC_TEST_VECTORS 4
+#define TEA_DEC_TEST_VECTORS 4
+
+struct cipher_testvec tea_enc_tv_template[] =
+{
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { [0 ... 8] = 0x00 },
+ .ilen = 8,
+ .result = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .ilen = 8,
+ .result = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .ilen = 16,
+ .result = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+ 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .ilen = 32,
+ .result = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+ 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+ 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+ 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+ .rlen = 32,
+ }
+};
+
+struct cipher_testvec tea_dec_tv_template[] =
+{
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+ .ilen = 8,
+ .result = { [0 ... 8] = 0x00 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+ .ilen = 8,
+ .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+ 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+ .ilen = 16,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+ 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+ 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+ 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+ .ilen = 32,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .rlen = 32,
+ }
+};
+
+/*
+ * XTEA test vectors
+ */
+#define XTEA_ENC_TEST_VECTORS 4
+#define XTEA_DEC_TEST_VECTORS 4
+
+struct cipher_testvec xtea_enc_tv_template[] =
+{
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { [0 ... 8] = 0x00 },
+ .ilen = 8,
+ .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .ilen = 8,
+ .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .ilen = 16,
+ .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .ilen = 32,
+ .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .rlen = 32,
+ }
+};
+
+struct cipher_testvec xtea_dec_tv_template[] =
+{
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .ilen = 8,
+ .result = { [0 ... 8] = 0x00 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .ilen = 8,
+ .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+ .ilen = 16,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .ilen = 32,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .rlen = 32,
+ }
+};
+
+
/*
* Compression stuff.
@@ -1771,4 +1960,5 @@ struct hash_testvec michael_mic_tv_template[] =
.digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
}
};
+
#endif /* _CRYPTO_TCRYPT_H */
diff --git a/crypto/tea.c b/crypto/tea.c
new file mode 100644
index 000000000000..bf943294d495
--- /dev/null
+++ b/crypto/tea.c
@@ -0,0 +1,248 @@
+/*
+ * Cryptographic API.
+ *
+ * TEA and Xtended TEA Algorithms
+ *
+ * The TEA and Xtended TEA algorithms were developed by David Wheeler
+ * and Roger Needham at the Computer Laboratory of Cambridge University.
+ *
+ * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define TEA_KEY_SIZE 16
+#define TEA_BLOCK_SIZE 8
+#define TEA_ROUNDS 32
+#define TEA_DELTA 0x9e3779b9
+
+#define XTEA_KEY_SIZE 16
+#define XTEA_BLOCK_SIZE 8
+#define XTEA_ROUNDS 32
+#define XTEA_DELTA 0x9e3779b9
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+struct tea_ctx {
+ u32 KEY[4];
+};
+
+struct xtea_ctx {
+ u32 KEY[4];
+};
+
+static int tea_setkey(void *ctx_arg, const u8 *in_key,
+ unsigned int key_len, u32 *flags)
+{
+
+ struct tea_ctx *ctx = ctx_arg;
+
+ if (key_len != 16)
+ {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ ctx->KEY[0] = u32_in (in_key);
+ ctx->KEY[1] = u32_in (in_key + 4);
+ ctx->KEY[2] = u32_in (in_key + 8);
+ ctx->KEY[3] = u32_in (in_key + 12);
+
+ return 0;
+
+}
+
+static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+ u32 y, z, n, sum = 0;
+ u32 k0, k1, k2, k3;
+
+ struct tea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ k0 = ctx->KEY[0];
+ k1 = ctx->KEY[1];
+ k2 = ctx->KEY[2];
+ k3 = ctx->KEY[3];
+
+ n = TEA_ROUNDS;
+
+ while (n-- > 0) {
+ sum += TEA_DELTA;
+ y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+ z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+}
+
+static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+ u32 y, z, n, sum;
+ u32 k0, k1, k2, k3;
+
+ struct tea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ k0 = ctx->KEY[0];
+ k1 = ctx->KEY[1];
+ k2 = ctx->KEY[2];
+ k3 = ctx->KEY[3];
+
+ sum = TEA_DELTA << 5;
+
+ n = TEA_ROUNDS;
+
+ while (n-- > 0) {
+ z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+ y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+ sum -= TEA_DELTA;
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+
+}
+
+static int xtea_setkey(void *ctx_arg, const u8 *in_key,
+ unsigned int key_len, u32 *flags)
+{
+
+ struct xtea_ctx *ctx = ctx_arg;
+
+ if (key_len != 16)
+ {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ ctx->KEY[0] = u32_in (in_key);
+ ctx->KEY[1] = u32_in (in_key + 4);
+ ctx->KEY[2] = u32_in (in_key + 8);
+ ctx->KEY[3] = u32_in (in_key + 12);
+
+ return 0;
+
+}
+
+static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+
+ u32 y, z, sum = 0;
+ u32 limit = XTEA_DELTA * XTEA_ROUNDS;
+
+ struct xtea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ while (sum != limit) {
+ y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
+ sum += TEA_DELTA;
+ z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+
+}
+
+static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+
+ u32 y, z, sum;
+ struct tea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ sum = XTEA_DELTA * XTEA_ROUNDS;
+
+ while (sum) {
+ z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
+ sum -= XTEA_DELTA;
+ y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+
+}
+
+static struct crypto_alg tea_alg = {
+ .cra_name = "tea",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = TEA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof (struct tea_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(tea_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = TEA_KEY_SIZE,
+ .cia_max_keysize = TEA_KEY_SIZE,
+ .cia_setkey = tea_setkey,
+ .cia_encrypt = tea_encrypt,
+ .cia_decrypt = tea_decrypt } }
+};
+
+static struct crypto_alg xtea_alg = {
+ .cra_name = "xtea",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = XTEA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof (struct xtea_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = XTEA_KEY_SIZE,
+ .cia_max_keysize = XTEA_KEY_SIZE,
+ .cia_setkey = xtea_setkey,
+ .cia_encrypt = xtea_encrypt,
+ .cia_decrypt = xtea_decrypt } }
+};
+
+static int __init init(void)
+{
+ int ret = 0;
+
+ ret = crypto_register_alg(&tea_alg);
+ if (ret < 0)
+ goto out;
+
+ ret = crypto_register_alg(&xtea_alg);
+ if (ret < 0) {
+ crypto_unregister_alg(&tea_alg);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&tea_alg);
+ crypto_unregister_alg(&xtea_alg);
+}
+
+MODULE_ALIAS("xtea");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index eb0f062c3ce2..cd67fcddf394 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -901,6 +901,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
goto err;
if (cdrom_open_write(cdi))
goto err;
+ ret = 0;
}
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 843e9b83d6d2..92792bb7d1cb 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -602,7 +602,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
{
int r;
unsigned int i;
- struct io_region from, to[ms->nr_mirrors - 1], *dest;
+ struct io_region from, to[KCOPYD_MAX_REGIONS], *dest;
struct mirror *m;
unsigned long flags = 0;
@@ -757,7 +757,7 @@ static void write_callback(unsigned long error, void *context)
static void do_write(struct mirror_set *ms, struct bio *bio)
{
unsigned int i;
- struct io_region io[ms->nr_mirrors];
+ struct io_region io[KCOPYD_MAX_REGIONS+1];
struct mirror *m;
for (i = 0; i < ms->nr_mirrors; i++) {
@@ -1028,7 +1028,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argc -= args_used;
if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
- nr_mirrors < 2) {
+ nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) {
ti->error = "dm-mirror: Invalid number of mirrors";
dm_destroy_dirty_log(dl);
return -EINVAL;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 80a1901c4e31..01794ed391a2 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -17,11 +17,13 @@
#include <linux/slab.h>
static const char *_name = DM_NAME;
-#define MAX_DEVICES 1024
static unsigned int major = 0;
static unsigned int _major = 0;
+static int realloc_minor_bits(unsigned long requested_minor);
+static void free_minor_bits(void);
+
/*
* One of these is allocated per bio.
*/
@@ -111,11 +113,19 @@ static int __init local_init(void)
return -ENOMEM;
}
+ r = realloc_minor_bits(1024);
+ if (r < 0) {
+ kmem_cache_destroy(_tio_cache);
+ kmem_cache_destroy(_io_cache);
+ return r;
+ }
+
_major = major;
r = register_blkdev(_major, _name);
if (r < 0) {
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
+ free_minor_bits();
return r;
}
@@ -129,6 +139,7 @@ static void local_exit(void)
{
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
+ free_minor_bits();
if (unregister_blkdev(_major, _name) < 0)
DMERR("devfs_unregister_blkdev failed");
@@ -615,14 +626,58 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
/*-----------------------------------------------------------------
* A bitset is used to keep track of allocated minor numbers.
*---------------------------------------------------------------*/
-static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long _minor_bits[MAX_DEVICES / BITS_PER_LONG];
+static DECLARE_MUTEX(_minor_lock);
+static unsigned long *_minor_bits = NULL;
+static unsigned long _max_minors = 0;
+
+#define MINORS_SIZE(minors) ((minors / BITS_PER_LONG) * sizeof(unsigned long))
+
+static int realloc_minor_bits(unsigned long requested_minor)
+{
+ unsigned long max_minors;
+ unsigned long *minor_bits, *tmp;
+
+ if (requested_minor < _max_minors)
+ return -EINVAL;
+
+ /* Round up the requested minor to the next power-of-2. */
+ max_minors = 1 << fls(requested_minor - 1);
+ if (max_minors > (1 << MINORBITS))
+ return -EINVAL;
+
+ minor_bits = kmalloc(MINORS_SIZE(max_minors), GFP_KERNEL);
+ if (!minor_bits)
+ return -ENOMEM;
+ memset(minor_bits, 0, MINORS_SIZE(max_minors));
+
+ /* Copy the existing bit-set to the new one. */
+ if (_minor_bits)
+ memcpy(minor_bits, _minor_bits, MINORS_SIZE(_max_minors));
+
+ tmp = _minor_bits;
+ _minor_bits = minor_bits;
+ _max_minors = max_minors;
+ if (tmp)
+ kfree(tmp);
+
+ return 0;
+}
+
+static void free_minor_bits(void)
+{
+ down(&_minor_lock);
+ kfree(_minor_bits);
+ _minor_bits = NULL;
+ _max_minors = 0;
+ up(&_minor_lock);
+}
static void free_minor(unsigned int minor)
{
- spin_lock(&_minor_lock);
- clear_bit(minor, _minor_bits);
- spin_unlock(&_minor_lock);
+ down(&_minor_lock);
+ if (minor < _max_minors)
+ clear_bit(minor, _minor_bits);
+ up(&_minor_lock);
}
/*
@@ -630,37 +685,48 @@ static void free_minor(unsigned int minor)
*/
static int specific_minor(unsigned int minor)
{
- int r = -EBUSY;
+ int r = 0;
- if (minor >= MAX_DEVICES) {
- DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)",
- MAX_DEVICES);
+ if (minor > (1 << MINORBITS))
return -EINVAL;
+
+ down(&_minor_lock);
+ if (minor >= _max_minors) {
+ r = realloc_minor_bits(minor);
+ if (r) {
+ up(&_minor_lock);
+ return r;
+ }
}
- spin_lock(&_minor_lock);
- if (!test_and_set_bit(minor, _minor_bits))
- r = 0;
- spin_unlock(&_minor_lock);
+ if (test_and_set_bit(minor, _minor_bits))
+ r = -EBUSY;
+ up(&_minor_lock);
return r;
}
static int next_free_minor(unsigned int *minor)
{
- int r = -EBUSY;
+ int r;
unsigned int m;
- spin_lock(&_minor_lock);
- m = find_first_zero_bit(_minor_bits, MAX_DEVICES);
- if (m != MAX_DEVICES) {
- set_bit(m, _minor_bits);
- *minor = m;
- r = 0;
+ down(&_minor_lock);
+ m = find_first_zero_bit(_minor_bits, _max_minors);
+ if (m >= _max_minors) {
+ r = realloc_minor_bits(_max_minors * 2);
+ if (r) {
+ up(&_minor_lock);
+ return r;
+ }
+ m = find_first_zero_bit(_minor_bits, _max_minors);
}
- spin_unlock(&_minor_lock);
- return r;
+ set_bit(m, _minor_bits);
+ *minor = m;
+ up(&_minor_lock);
+
+ return 0;
}
static struct block_device_operations dm_blk_dops;
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index 40e46944ecb0..8bdf11700ce1 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -24,9 +24,6 @@
#include "kcopyd.h"
-/* FIXME: this is only needed for the DMERR macros */
-#include "dm.h"
-
static struct workqueue_struct *_kcopyd_wq;
static struct work_struct _kcopyd_work;
@@ -576,12 +573,11 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
static DECLARE_MUTEX(_client_lock);
static LIST_HEAD(_clients);
-static int client_add(struct kcopyd_client *kc)
+static void client_add(struct kcopyd_client *kc)
{
down(&_client_lock);
list_add(&kc->list, &_clients);
up(&_client_lock);
- return 0;
}
static void client_del(struct kcopyd_client *kc)
@@ -671,15 +667,7 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
return r;
}
- r = client_add(kc);
- if (r) {
- dm_io_put(nr_pages);
- client_free_pages(kc);
- kfree(kc);
- kcopyd_exit();
- return r;
- }
-
+ client_add(kc);
*result = kc;
return 0;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 37ec9ce1c952..6ca911cb9279 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -238,12 +238,6 @@ static int vortex_debug = VORTEX_DEBUG;
static int vortex_debug = 1;
#endif
-#ifndef __OPTIMIZE__
-#error You must compile this file with the correct options!
-#error See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8749b06c6b99..6f53a942039e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -813,6 +813,24 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32.
+config SMC91X
+ tristate "SMC 91C9x/91C1xxx support"
+ select CRC32
+ select MII
+ depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6)
+ help
+ This is a driver for SMC's 91x series of Ethernet chipsets,
+ including the SMC91C94 and the SMC91C111. Say Y if you want it
+ compiled into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.linuxdoc.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc91x. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
config SMC9194
tristate "SMC 9194 support"
depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
@@ -883,7 +901,7 @@ source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)"
- depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL
+ depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -1122,7 +1140,7 @@ config SKMC
config NE2_MCA
tristate "NE/2 (ne2000 MCA version) support"
- depends on NET_ETHERNET && MCA
+ depends on NET_ETHERNET && MCA_LEGACY
select CRC32
help
If you have a network (Ethernet) card of this type, say Y and read
@@ -1858,6 +1876,8 @@ config NE_H8300
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
+source "drivers/net/fec_8xx/Kconfig"
+
endmenu
#
@@ -2577,3 +2597,4 @@ config NETCONSOLE
---help---
If you want to log kernel messages over the network, enable this.
See Documentation/networking/netconsole.txt for details.
+
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b6ae311ee882..2ae71cf8b4b0 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -175,6 +175,8 @@ obj-$(CONFIG_R8169) += r8169.o
obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
obj-$(CONFIG_IBMVETH) += ibmveth.o
obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_FEC_8XX) += fec_8xx/
obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_NET_FC) += fc/
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index e17ddb7728b4..b70c2f0ee5f7 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -1634,7 +1634,7 @@ static void ace_tasklet(unsigned long dev)
cur_size = atomic_read(&ap->cur_rx_bufs);
if ((cur_size < RX_LOW_STD_THRES) &&
!test_and_set_bit(0, &ap->std_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling buffers (current %i)\n", cur_size);
#endif
ace_load_std_rx_ring(ap, RX_RING_SIZE - cur_size);
@@ -1644,7 +1644,7 @@ static void ace_tasklet(unsigned long dev)
cur_size = atomic_read(&ap->cur_mini_bufs);
if ((cur_size < RX_LOW_MINI_THRES) &&
!test_and_set_bit(0, &ap->mini_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling mini buffers (current %i)\n",
cur_size);
#endif
@@ -1655,7 +1655,7 @@ static void ace_tasklet(unsigned long dev)
cur_size = atomic_read(&ap->cur_jumbo_bufs);
if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) &&
!test_and_set_bit(0, &ap->jumbo_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling jumbo buffers (current %i)\n", cur_size);
#endif
ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size);
@@ -2255,7 +2255,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if (cur_size < RX_LOW_STD_THRES) {
if ((cur_size < RX_PANIC_STD_THRES) &&
!test_and_set_bit(0, &ap->std_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("low on std buffers %i\n", cur_size);
#endif
ace_load_std_rx_ring(ap,
@@ -2270,7 +2270,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if ((cur_size < RX_PANIC_MINI_THRES) &&
!test_and_set_bit(0,
&ap->mini_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("low on mini buffers %i\n",
cur_size);
#endif
@@ -2286,7 +2286,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if ((cur_size < RX_PANIC_JUMBO_THRES) &&
!test_and_set_bit(0,
&ap->jumbo_refill_busy)){
-#if DEBUG
+#ifdef DEBUG
printk("low on jumbo buffers %i\n",
cur_size);
#endif
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 1ba12ab47284..470364deded0 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -44,21 +44,3 @@ config ARM_ETHER00
will generate a suitable hw address based on the board serial
number (MTD support is required for this). Otherwise you will
need to set a suitable hw address using ifconfig.
-
-config SMC91X
- tristate "SMC 91C9x/91C1xxx support"
- select CRC32
- select MII
- depends on ARM
- help
- This is a driver for SMC's 91x series of Ethernet chipsets,
- including the SMC91C94 and the SMC91C111. Say Y if you want it
- compiled into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.linuxdoc.org/docs.html#howto>.
-
- This driver is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called smc91x. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt> as well
- as <file:Documentation/networking/net-modules.txt>.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index d6d87c03ef72..b0d706834d89 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -8,4 +8,3 @@ obj-$(CONFIG_ARM_ETHER00) += ether00.o
obj-$(CONFIG_ARM_ETHERH) += etherh.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o
-obj-$(CONFIG_SMC91X) += smc91x.o
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 56fc87881626..6af982b60397 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -87,12 +87,6 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
#define PKT_BUF_SZ 1536
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index e81e0afda6f8..ecf5b8af096b 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -116,12 +116,6 @@ static int rx_copybreak;
#define TX_FIFO_THRESH 256
#define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */
-#if !defined(__OPTIMIZE__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
new file mode 100644
index 000000000000..db36ac3ea453
--- /dev/null
+++ b/drivers/net/fec_8xx/Kconfig
@@ -0,0 +1,14 @@
+config FEC_8XX
+ tristate "Motorola 8xx FEC driver"
+ depends on NET_ETHERNET && 8xx && (NETTA || NETPHONE)
+ select MII
+
+config FEC_8XX_GENERIC_PHY
+ bool "Support any generic PHY"
+ depends on FEC_8XX
+ default y
+
+config FEC_8XX_DM9161_PHY
+ bool "Support DM9161 PHY"
+ depends on FEC_8XX
+ default n
diff --git a/drivers/net/fec_8xx/Makefile b/drivers/net/fec_8xx/Makefile
new file mode 100644
index 000000000000..70c54f8c48e5
--- /dev/null
+++ b/drivers/net/fec_8xx/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Motorola 8xx FEC ethernet controller
+#
+
+obj-$(CONFIG_FEC_8XX) += fec_8xx.o
+
+fec_8xx-objs := fec_main.o fec_mii.o
+
+# the platform instantatiation objects
+ifeq ($(CONFIG_NETTA),y)
+fec_8xx-objs += fec_8xx-netta.o
+endif
diff --git a/drivers/net/fec_8xx/fec_8xx-netta.c b/drivers/net/fec_8xx/fec_8xx-netta.c
new file mode 100644
index 000000000000..7d73661aa367
--- /dev/null
+++ b/drivers/net/fec_8xx/fec_8xx-netta.c
@@ -0,0 +1,153 @@
+/*
+ * FEC instantatiation file for NETTA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/commproc.h>
+
+#include "fec_8xx.h"
+
+/*************************************************/
+
+static struct fec_platform_info fec1_info = {
+ .fec_no = 0,
+ .use_mdio = 1,
+ .phy_addr = 8,
+ .fec_irq = SIU_LEVEL1,
+ .phy_irq = CPM_IRQ_OFFSET + CPMVEC_PIO_PC6,
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+ .use_napi = 1,
+ .napi_weight = 17,
+};
+
+static struct fec_platform_info fec2_info = {
+ .fec_no = 1,
+ .use_mdio = 1,
+ .phy_addr = 2,
+ .fec_irq = SIU_LEVEL3,
+ .phy_irq = CPM_IRQ_OFFSET + CPMVEC_PIO_PC7,
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+ .use_napi = 1,
+ .napi_weight = 17,
+};
+
+static struct net_device *fec1_dev;
+static struct net_device *fec2_dev;
+
+/* XXX custom u-boot & Linux startup needed */
+extern const char *__fw_getenv(const char *var);
+
+/* access ports */
+#define setbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) | (_v))
+#define clrbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) & ~(_v))
+
+#define setbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) | (_v))
+#define clrbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) & ~(_v))
+
+int fec_8xx_platform_init(void)
+{
+ immap_t *immap = (immap_t *)IMAP_ADDR;
+ bd_t *bd = (bd_t *) __res;
+ const char *s;
+ char *e;
+ int i;
+
+ /* use MDC for MII */
+ setbits16(immap->im_ioport.iop_pdpar, 0x0080);
+ clrbits16(immap->im_ioport.iop_pddir, 0x0080);
+
+ /* configure FEC1 pins */
+ setbits16(immap->im_ioport.iop_papar, 0xe810);
+ setbits16(immap->im_ioport.iop_padir, 0x0810);
+ clrbits16(immap->im_ioport.iop_padir, 0xe000);
+
+ setbits32(immap->im_cpm.cp_pbpar, 0x00000001);
+ clrbits32(immap->im_cpm.cp_pbdir, 0x00000001);
+
+ setbits32(immap->im_cpm.cp_cptr, 0x00000100);
+ clrbits32(immap->im_cpm.cp_cptr, 0x00000050);
+
+ clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
+ clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
+ clrbits16(immap->im_ioport.iop_pcso, 0x0200);
+ setbits16(immap->im_ioport.iop_pcint, 0x0200);
+
+ /* configure FEC2 pins */
+ setbits32(immap->im_cpm.cp_pepar, 0x00039620);
+ setbits32(immap->im_cpm.cp_pedir, 0x00039620);
+ setbits32(immap->im_cpm.cp_peso, 0x00031000);
+ clrbits32(immap->im_cpm.cp_peso, 0x00008620);
+
+ setbits32(immap->im_cpm.cp_cptr, 0x00000080);
+ clrbits32(immap->im_cpm.cp_cptr, 0x00000028);
+
+ clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
+ clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
+ clrbits16(immap->im_ioport.iop_pcso, 0x0200);
+ setbits16(immap->im_ioport.iop_pcint, 0x0200);
+
+ /* fill up */
+ fec1_info.sys_clk = bd->bi_intfreq;
+ fec2_info.sys_clk = bd->bi_intfreq;
+
+ s = __fw_getenv("ethaddr");
+ if (s != NULL) {
+ for (i = 0; i < 6; i++) {
+ fec1_info.macaddr[i] = simple_strtoul(s, &e, 16);
+ if (*e)
+ s = e + 1;
+ }
+ }
+
+ s = __fw_getenv("eth1addr");
+ if (s != NULL) {
+ for (i = 0; i < 6; i++) {
+ fec2_info.macaddr[i] = simple_strtoul(s, &e, 16);
+ if (*e)
+ s = e + 1;
+ }
+ }
+
+ fec_8xx_init_one(&fec1_info, &fec1_dev);
+ fec_8xx_init_one(&fec2_info, &fec2_dev);
+
+ return fec1_dev != NULL && fec2_dev != NULL ? 0 : -1;
+}
+
+void fec_8xx_platform_cleanup(void)
+{
+ if (fec2_dev != NULL)
+ fec_8xx_cleanup_one(fec2_dev);
+
+ if (fec1_dev != NULL)
+ fec_8xx_cleanup_one(fec1_dev);
+}
diff --git a/drivers/net/fec_8xx/fec_8xx.h b/drivers/net/fec_8xx/fec_8xx.h
new file mode 100644
index 000000000000..5af60b0f9208
--- /dev/null
+++ b/drivers/net/fec_8xx/fec_8xx.h
@@ -0,0 +1,218 @@
+#ifndef FEC_8XX_H
+#define FEC_8XX_H
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+
+#include <linux/types.h>
+
+/* HW info */
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY 0x04C11DB7
+
+#define MII_ADVERTISE_HALF (ADVERTISE_100HALF | \
+ ADVERTISE_10HALF | ADVERTISE_CSMA)
+#define MII_ADVERTISE_ALL (ADVERTISE_100FULL | \
+ ADVERTISE_10FULL | MII_ADVERTISE_HALF)
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
+#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
+#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
+#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
+#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
+#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
+#define FEC_ENET_RXF 0x02000000U /* Full frame received */
+#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
+#define FEC_ENET_MII 0x00800000U /* MII interrupt */
+#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
+
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+#define FEC_ECNTRL_RESET 0x00000001
+
+#define FEC_RCNTRL_BC_REJ 0x00000010
+#define FEC_RCNTRL_PROM 0x00000008
+#define FEC_RCNTRL_MII_MODE 0x00000004
+#define FEC_RCNTRL_DRT 0x00000002
+#define FEC_RCNTRL_LOOP 0x00000001
+
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_GTS 0x00000001
+
+/* values for MII phy_status */
+
+#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */
+#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */
+#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */
+#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */
+#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */
+#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */
+#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */
+#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */
+#define PHY_STAT_SPMASK 0xf000 /* mask for speed */
+#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */
+#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */
+#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */
+#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */
+
+typedef struct phy_info {
+ unsigned int id;
+ const char *name;
+ void (*startup) (struct net_device * dev);
+ void (*shutdown) (struct net_device * dev);
+ void (*ack_int) (struct net_device * dev);
+} phy_info_t;
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define MAX_MTU 1508 /* Allow fullsized pppoe packets over VLAN */
+#define MIN_MTU 46 /* this is data size */
+#define CRC_LEN 4
+
+#define PKT_MAXBUF_SIZE (MAX_MTU+ETH_HLEN+CRC_LEN)
+#define PKT_MINBUF_SIZE (MIN_MTU+ETH_HLEN+CRC_LEN)
+
+/* Must be a multiple of 4 */
+#define PKT_MAXBLR_SIZE ((PKT_MAXBUF_SIZE+3) & ~3)
+/* This is needed so that invalidate_xxx wont invalidate too much */
+#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+
+/* platform interface */
+
+struct fec_platform_info {
+ int fec_no; /* FEC index */
+ int use_mdio; /* use external MII */
+ int phy_addr; /* the phy address */
+ int fec_irq, phy_irq; /* the irq for the controller */
+ int rx_ring, tx_ring; /* number of buffers on rx */
+ int sys_clk; /* system clock */
+ __u8 macaddr[6]; /* mac address */
+ int rx_copybreak; /* limit we copy small frames */
+ int use_napi; /* use NAPI */
+ int napi_weight; /* NAPI weight */
+};
+
+/* forward declaration */
+struct fec;
+
+struct fec_enet_private {
+ spinlock_t lock; /* during all ops except TX pckt processing */
+ spinlock_t tx_lock; /* during fec_start_xmit and fec_tx */
+ int fecno;
+ struct fec *fecp;
+ const struct fec_platform_info *fpi;
+ int rx_ring, tx_ring;
+ dma_addr_t ring_mem_addr;
+ void *ring_base;
+ struct sk_buff **rx_skbuff;
+ struct sk_buff **tx_skbuff;
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *dirty_tx; /* ring entries to be free()ed. */
+ cbd_t *cur_rx;
+ cbd_t *cur_tx;
+ int tx_free;
+ struct net_device_stats stats;
+ struct timer_list phy_timer_list;
+ const struct phy_info *phy;
+ unsigned int fec_phy_speed;
+ __u32 msg_enable;
+ struct mii_if_info mii_if;
+};
+
+/***************************************************************************/
+
+void fec_restart(struct net_device *dev, int duplex, int speed);
+void fec_stop(struct net_device *dev);
+
+/***************************************************************************/
+
+int fec_mii_read(struct net_device *dev, int phy_id, int location);
+void fec_mii_write(struct net_device *dev, int phy_id, int location, int value);
+
+int fec_mii_phy_id_detect(struct net_device *dev);
+void fec_mii_startup(struct net_device *dev);
+void fec_mii_shutdown(struct net_device *dev);
+void fec_mii_ack_int(struct net_device *dev);
+
+void fec_mii_link_status_change_check(struct net_device *dev, int init_media);
+
+/***************************************************************************/
+
+#define FEC1_NO 0x00
+#define FEC2_NO 0x01
+#define FEC3_NO 0x02
+
+int fec_8xx_init_one(const struct fec_platform_info *fpi,
+ struct net_device **devp);
+int fec_8xx_cleanup_one(struct net_device *dev);
+
+/***************************************************************************/
+
+#define DRV_MODULE_NAME "fec_8xx"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "0.1"
+#define DRV_MODULE_RELDATE "May 6, 2004"
+
+/***************************************************************************/
+
+int fec_8xx_platform_init(void);
+void fec_8xx_platform_cleanup(void);
+
+/***************************************************************************/
+
+/* FEC access macros */
+#if defined(CONFIG_8xx)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __fec_out32(addr, x) __raw_writel(x, addr)
+#define __fec_out16(addr, x) __raw_writew(x, addr)
+#define __fec_in32(addr) __raw_readl(addr)
+#define __fec_in16(addr) __raw_readw(addr)
+#else
+/* for others play it safe */
+#define __fec_out32(addr, x) out_be32(addr, x)
+#define __fec_out16(addr, x) out_be16(addr, x)
+#define __fec_in32(addr) in_be32(addr)
+#define __fec_in16(addr) in_be16(addr)
+#endif
+
+/* write */
+#define FW(_fecp, _reg, _v) __fec_out32(&(_fecp)->fec_ ## _reg, (_v))
+
+/* read */
+#define FR(_fecp, _reg) __fec_in32(&(_fecp)->fec_ ## _reg)
+
+/* set bits */
+#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
+
+/* clear bits */
+#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
+
+/* buffer descriptor access macros */
+
+/* write */
+#define CBDW_SC(_cbd, _sc) __fec_out16(&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen) __fec_out16(&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr) __fec_out32(&(_cbd)->cbd_bufaddr, (_bufaddr))
+
+/* read */
+#define CBDR_SC(_cbd) __fec_in16(&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd) __fec_in16(&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd) __fec_in32(&(_cbd)->cbd_bufaddr)
+
+/* set bits */
+#define CBDS_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
+
+/* clear bits */
+#define CBDC_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc))
+
+/***************************************************************************/
+
+#endif
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
new file mode 100644
index 000000000000..1bf15eed626a
--- /dev/null
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -0,0 +1,1275 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/commproc.h>
+#include <asm/dma-mapping.h>
+
+#include "fec_8xx.h"
+
+/*************************************************/
+
+#define FEC_MAX_MULTICAST_ADDRS 64
+
+/*************************************************/
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
+MODULE_DESCRIPTION("Motorola 8xx FEC ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(fec_8xx_debug, "i");
+MODULE_PARM_DESC(fec_8xx_debug,
+ "FEC 8xx bitmapped debugging message enable value");
+
+int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */
+
+/*************************************************/
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY 50
+
+/*****************************************************************************************/
+
+static void fec_whack_reset(fec_t * fecp)
+{
+ int i;
+
+ /*
+ * Whack a reset. We should wait for this.
+ */
+ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
+ for (i = 0;
+ (FR(fecp, ecntrl) & FEC_ECNTRL_RESET) != 0 && i < FEC_RESET_DELAY;
+ i++)
+ udelay(1);
+
+ if (i == FEC_RESET_DELAY)
+ printk(KERN_WARNING "FEC Reset timeout!\n");
+
+}
+
+/****************************************************************************/
+
+/*
+ * Transmitter timeout.
+ */
+#define TX_TIMEOUT (2*HZ)
+
+/****************************************************************************/
+
+/*
+ * Returns the CRC needed when filling in the hash table for
+ * multicast group filtering
+ * pAddr must point to a MAC address (6 bytes)
+ */
+static __u32 fec_mulicast_calc_crc(char *pAddr)
+{
+ u8 byte;
+ int byte_count;
+ int bit_count;
+ __u32 crc = 0xffffffff;
+ u8 msb;
+
+ for (byte_count = 0; byte_count < 6; byte_count++) {
+ byte = pAddr[byte_count];
+ for (bit_count = 0; bit_count < 8; bit_count++) {
+ msb = crc >> 31;
+ crc <<= 1;
+ if (msb ^ (byte & 0x1)) {
+ crc ^= FEC_CRC_POLY;
+ }
+ byte >>= 1;
+ }
+ }
+ return (crc);
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+static void fec_set_multicast_list(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fecp;
+ struct dev_mc_list *pmc;
+ __u32 crc;
+ int temp;
+ __u32 csrVal;
+ int hash_index;
+ __u32 hthi, htlo;
+ unsigned long flags;
+
+
+ if ((dev->flags & IFF_PROMISC) != 0) {
+
+ spin_lock_irqsave(&fep->lock, flags);
+ FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ /*
+ * Log any net taps.
+ */
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s: Promiscuous mode enabled.\n", dev->name);
+ return;
+
+ }
+
+ if ((dev->flags & IFF_ALLMULTI) != 0 ||
+ dev->mc_count > FEC_MAX_MULTICAST_ADDRS) {
+ /*
+ * Catch all multicast addresses, set the filter to all 1's.
+ */
+ hthi = 0xffffffffU;
+ htlo = 0xffffffffU;
+ } else {
+ hthi = 0;
+ htlo = 0;
+
+ /*
+ * Now populate the hash table
+ */
+ for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next) {
+ crc = fec_mulicast_calc_crc(pmc->dmi_addr);
+ temp = (crc & 0x3f) >> 1;
+ hash_index = ((temp & 0x01) << 4) |
+ ((temp & 0x02) << 2) |
+ ((temp & 0x04)) |
+ ((temp & 0x08) >> 2) |
+ ((temp & 0x10) >> 4);
+ csrVal = (1 << hash_index);
+ if (crc & 1)
+ hthi |= csrVal;
+ else
+ htlo |= csrVal;
+ }
+ }
+
+ spin_lock_irqsave(&fep->lock, flags);
+ FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
+ FW(fecp, hash_table_high, hthi);
+ FW(fecp, hash_table_low, htlo);
+ spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+static int fec_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *mac = addr;
+ struct fec_enet_private *fep = netdev_priv(dev);
+ struct fec *fecp = fep->fecp;
+ int i;
+ __u32 addrhi, addrlo;
+ unsigned long flags;
+
+ /* Get pointer to SCC area in parameter RAM. */
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = mac->sa_data[i];
+
+ /*
+ * Set station address.
+ */
+ addrhi = ((__u32) dev->dev_addr[0] << 24) |
+ ((__u32) dev->dev_addr[1] << 16) |
+ ((__u32) dev->dev_addr[2] << 8) |
+ (__u32) dev->dev_addr[3];
+ addrlo = ((__u32) dev->dev_addr[4] << 24) |
+ ((__u32) dev->dev_addr[5] << 16);
+
+ spin_lock_irqsave(&fep->lock, flags);
+ FW(fecp, addr_low, addrhi);
+ FW(fecp, addr_high, addrlo);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return 0;
+}
+
+/*
+ * This function is called to start or restart the FEC during a link
+ * change. This only happens when switching between half and full
+ * duplex.
+ */
+void fec_restart(struct net_device *dev, int duplex, int speed)
+{
+#ifdef CONFIG_DUET
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ __u32 cptr;
+#endif
+ struct fec_enet_private *fep = netdev_priv(dev);
+ struct fec *fecp = fep->fecp;
+ const struct fec_platform_info *fpi = fep->fpi;
+ cbd_t *bdp;
+ struct sk_buff *skb;
+ int i;
+ __u32 addrhi, addrlo;
+
+ fec_whack_reset(fep->fecp);
+
+ /*
+ * Set station address.
+ */
+ addrhi = ((__u32) dev->dev_addr[0] << 24) |
+ ((__u32) dev->dev_addr[1] << 16) |
+ ((__u32) dev->dev_addr[2] << 8) |
+ (__u32) dev->dev_addr[3];
+ addrlo = ((__u32) dev->dev_addr[4] << 24) |
+ ((__u32) dev->dev_addr[5] << 16);
+ FW(fecp, addr_low, addrhi);
+ FW(fecp, addr_high, addrlo);
+
+ /*
+ * Reset all multicast.
+ */
+ FW(fecp, hash_table_high, 0);
+ FW(fecp, hash_table_low, 0);
+
+ /*
+ * Set maximum receive buffer size.
+ */
+ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
+ FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+
+ /*
+ * Set receive and transmit descriptor base.
+ */
+ FW(fecp, r_des_start, iopa((__u32) (fep->rx_bd_base)));
+ FW(fecp, x_des_start, iopa((__u32) (fep->tx_bd_base)));
+
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->tx_free = fep->tx_ring;
+ fep->cur_rx = fep->rx_bd_base;
+
+ /*
+ * Reset SKB receive buffers
+ */
+ for (i = 0; i < fep->rx_ring; i++) {
+ if ((skb = fep->rx_skbuff[i]) == NULL)
+ continue;
+ fep->rx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
+
+ /*
+ * Initialize the receive buffer descriptors.
+ */
+ for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
+ skb = dev_alloc_skb(ENET_RX_FRSIZE);
+ if (skb == NULL) {
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s Memory squeeze, unable to allocate skb\n",
+ dev->name);
+ fep->stats.rx_dropped++;
+ break;
+ }
+ fep->rx_skbuff[i] = skb;
+ skb->dev = dev;
+ CBDW_BUFADDR(bdp, dma_map_single(NULL, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE));
+ CBDW_DATLEN(bdp, 0); /* zero */
+ CBDW_SC(bdp, BD_ENET_RX_EMPTY |
+ ((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
+ }
+ /*
+ * if we failed, fillup remainder
+ */
+ for (; i < fep->rx_ring; i++, bdp++) {
+ fep->rx_skbuff[i] = NULL;
+ CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
+ }
+
+ /*
+ * Reset SKB transmit buffers.
+ */
+ for (i = 0; i < fep->tx_ring; i++) {
+ if ((skb = fep->tx_skbuff[i]) == NULL)
+ continue;
+ fep->tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
+
+ /*
+ * ...and the same for transmit.
+ */
+ for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
+ fep->tx_skbuff[i] = NULL;
+ CBDW_BUFADDR(bdp, virt_to_bus(NULL));
+ CBDW_DATLEN(bdp, 0);
+ CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
+ }
+
+ /*
+ * Enable big endian and don't care about SDMA FC.
+ */
+ FW(fecp, fun_code, 0x78000000);
+
+ /*
+ * Set MII speed.
+ */
+ FW(fecp, mii_speed, fep->fec_phy_speed);
+
+ /*
+ * Clear any outstanding interrupt.
+ */
+ FW(fecp, ievent, 0xffc0);
+ FW(fecp, ivec, (fpi->fec_irq / 2) << 29);
+
+ /*
+ * adjust to speed (only for DUET & RMII)
+ */
+#ifdef CONFIG_DUET
+ cptr = in_be32(&immap->im_cpm.cp_cptr);
+ switch (fpi->fec_no) {
+ case 0:
+ /*
+ * check if in RMII mode
+ */
+ if ((cptr & 0x100) == 0)
+ break;
+
+ if (speed == 10)
+ cptr |= 0x0000010;
+ else if (speed == 100)
+ cptr &= ~0x0000010;
+ break;
+ case 1:
+ /*
+ * check if in RMII mode
+ */
+ if ((cptr & 0x80) == 0)
+ break;
+
+ if (speed == 10)
+ cptr |= 0x0000008;
+ else if (speed == 100)
+ cptr &= ~0x0000008;
+ break;
+ default:
+ break;
+ }
+ out_be32(&immap->im_cpm.cp_cptr, cptr);
+#endif
+
+ FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ /*
+ * adjust to duplex mode
+ */
+ if (duplex) {
+ FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
+ FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
+ } else {
+ FS(fecp, r_cntrl, FEC_RCNTRL_DRT);
+ FC(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
+ }
+
+ /*
+ * Enable interrupts we wish to service.
+ */
+ FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB |
+ FEC_ENET_RXF | FEC_ENET_RXB);
+
+ /*
+ * And last, enable the transmit and receive processing.
+ */
+ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, r_des_active, 0x01000000);
+}
+
+void fec_stop(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fecp;
+ struct sk_buff *skb;
+ int i;
+
+ if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
+ return; /* already down */
+
+ FW(fecp, x_cntrl, 0x01); /* Graceful transmit stop */
+ for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) &&
+ i < FEC_RESET_DELAY; i++)
+ udelay(1);
+
+ if (i == FEC_RESET_DELAY)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s FEC timeout on graceful transmit stop\n",
+ dev->name);
+ /*
+ * Disable FEC. Let only MII interrupts.
+ */
+ FW(fecp, imask, 0);
+ FW(fecp, ecntrl, ~FEC_ECNTRL_ETHER_EN);
+
+ /*
+ * Reset SKB transmit buffers.
+ */
+ for (i = 0; i < fep->tx_ring; i++) {
+ if ((skb = fep->tx_skbuff[i]) == NULL)
+ continue;
+ fep->tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
+
+ /*
+ * Reset SKB receive buffers
+ */
+ for (i = 0; i < fep->rx_ring; i++) {
+ if ((skb = fep->rx_skbuff[i]) == NULL)
+ continue;
+ fep->rx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
+}
+
+/* common receive function */
+static int fec_enet_rx_common(struct net_device *dev, int *budget)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fecp;
+ const struct fec_platform_info *fpi = fep->fpi;
+ cbd_t *bdp;
+ struct sk_buff *skb, *skbn, *skbt;
+ int received = 0;
+ __u16 pkt_len, sc;
+ int curidx;
+ int rx_work_limit;
+
+ if (fpi->use_napi) {
+ rx_work_limit = min(dev->quota, *budget);
+
+ if (!netif_running(dev))
+ return 0;
+ }
+
+ /*
+ * First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = fep->cur_rx;
+
+ /* clear RX status bits for napi*/
+ if (fpi->use_napi)
+ FW(fecp, ievent, FEC_ENET_RXF | FEC_ENET_RXB);
+
+ while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+ curidx = bdp - fep->rx_bd_base;
+
+ /*
+ * Since we have allocated space to hold a complete frame,
+ * the last indicator should be set.
+ */
+ if ((sc & BD_ENET_RX_LAST) == 0)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s rcv is not +last\n",
+ dev->name);
+
+ /*
+ * Check for errors.
+ */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+ BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+ fep->stats.rx_errors++;
+ /* Frame too long or too short. */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ fep->stats.rx_length_errors++;
+ /* Frame alignment */
+ if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+ fep->stats.rx_frame_errors++;
+ /* CRC Error */
+ if (sc & BD_ENET_RX_CR)
+ fep->stats.rx_crc_errors++;
+ /* FIFO overrun */
+ if (sc & BD_ENET_RX_OV)
+ fep->stats.rx_crc_errors++;
+
+ skbn = fep->rx_skbuff[curidx];
+ BUG_ON(skbn == NULL);
+
+ } else {
+
+ /* napi, got packet but no quota */
+ if (fpi->use_napi && --rx_work_limit < 0)
+ break;
+
+ skb = fep->rx_skbuff[curidx];
+ BUG_ON(skb == NULL);
+
+ /*
+ * Process the incoming frame.
+ */
+ fep->stats.rx_packets++;
+ pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
+ fep->stats.rx_bytes += pkt_len + 4;
+
+ if (pkt_len <= fpi->rx_copybreak) {
+ /* +2 to make IP header L1 cache aligned */
+ skbn = dev_alloc_skb(pkt_len + 2);
+ if (skbn != NULL) {
+ skb_reserve(skbn, 2); /* align IP header */
+ memcpy(skbn->data, skb->data, pkt_len);
+ /* swap */
+ skbt = skb;
+ skb = skbn;
+ skbn = skbt;
+ }
+ } else
+ skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+ if (skbn != NULL) {
+ skb->dev = dev;
+ skb_put(skb, pkt_len); /* Make room */
+ skb->protocol = eth_type_trans(skb, dev);
+ received++;
+ if (!fpi->use_napi)
+ netif_rx(skb);
+ else
+ netif_receive_skb(skb);
+ } else {
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s Memory squeeze, dropping packet.\n",
+ dev->name);
+ fep->stats.rx_dropped++;
+ skbn = skb;
+ }
+ }
+
+ fep->rx_skbuff[curidx] = skbn;
+ CBDW_BUFADDR(bdp, dma_map_single(NULL, skbn->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE));
+ CBDW_DATLEN(bdp, 0);
+ CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+ /*
+ * Update BD pointer to next entry.
+ */
+ if ((sc & BD_ENET_RX_WRAP) == 0)
+ bdp++;
+ else
+ bdp = fep->rx_bd_base;
+
+ /*
+ * Doing this here will keep the FEC running while we process
+ * incoming frames. On a heavily loaded network, we should be
+ * able to keep up at the expense of system resources.
+ */
+ FW(fecp, r_des_active, 0x01000000);
+ }
+
+ fep->cur_rx = bdp;
+
+ if (fpi->use_napi) {
+ dev->quota -= received;
+ *budget -= received;
+
+ if (rx_work_limit < 0)
+ return 1; /* not done */
+
+ /* done */
+ netif_rx_complete(dev);
+
+ /* enable RX interrupt bits */
+ FS(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
+ }
+
+ return 0;
+}
+
+static void fec_enet_tx(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ cbd_t *bdp;
+ struct sk_buff *skb;
+ int dirtyidx, do_wake;
+ __u16 sc;
+
+ spin_lock(&fep->lock);
+ bdp = fep->dirty_tx;
+
+ do_wake = 0;
+ while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
+
+ dirtyidx = bdp - fep->tx_bd_base;
+
+ if (fep->tx_free == fep->tx_ring)
+ break;
+
+ skb = fep->tx_skbuff[dirtyidx];
+
+ /*
+ * Check for errors.
+ */
+ if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+ BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
+ fep->stats.tx_errors++;
+ if (sc & BD_ENET_TX_HB) /* No heartbeat */
+ fep->stats.tx_heartbeat_errors++;
+ if (sc & BD_ENET_TX_LC) /* Late collision */
+ fep->stats.tx_window_errors++;
+ if (sc & BD_ENET_TX_RL) /* Retrans limit */
+ fep->stats.tx_aborted_errors++;
+ if (sc & BD_ENET_TX_UN) /* Underrun */
+ fep->stats.tx_fifo_errors++;
+ if (sc & BD_ENET_TX_CSL) /* Carrier lost */
+ fep->stats.tx_carrier_errors++;
+ } else
+ fep->stats.tx_packets++;
+
+ if (sc & BD_ENET_TX_READY)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s HEY! Enet xmit interrupt and TX_READY.\n",
+ dev->name);
+
+ /*
+ * Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (sc & BD_ENET_TX_DEF)
+ fep->stats.collisions++;
+
+ /*
+ * Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(skb);
+ fep->tx_skbuff[dirtyidx] = NULL;
+
+ /*
+ * Update pointer to next buffer descriptor to be transmitted.
+ */
+ if ((sc & BD_ENET_TX_WRAP) == 0)
+ bdp++;
+ else
+ bdp = fep->tx_bd_base;
+
+ /*
+ * Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (!fep->tx_free++)
+ do_wake = 1;
+ }
+
+ fep->dirty_tx = bdp;
+
+ spin_unlock(&fep->lock);
+
+ if (do_wake && netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+}
+
+/*
+ * The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static irqreturn_t
+fec_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fec_enet_private *fep;
+ const struct fec_platform_info *fpi;
+ fec_t *fecp;
+ __u32 int_events;
+ __u32 int_events_napi;
+
+ if (unlikely(dev == NULL))
+ return IRQ_NONE;
+
+ fep = netdev_priv(dev);
+ fecp = fep->fecp;
+ fpi = fep->fpi;
+
+ /*
+ * Get the interrupt events that caused us to be here.
+ */
+ while ((int_events = FR(fecp, ievent) & FR(fecp, imask)) != 0) {
+
+ if (!fpi->use_napi)
+ FW(fecp, ievent, int_events);
+ else {
+ int_events_napi = int_events & ~(FEC_ENET_RXF | FEC_ENET_RXB);
+ FW(fecp, ievent, int_events_napi);
+ }
+
+ if ((int_events & (FEC_ENET_HBERR | FEC_ENET_BABR |
+ FEC_ENET_BABT | FEC_ENET_EBERR)) != 0)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s FEC ERROR(s) 0x%x\n",
+ dev->name, int_events);
+
+ if ((int_events & FEC_ENET_RXF) != 0) {
+ if (!fpi->use_napi)
+ fec_enet_rx_common(dev, NULL);
+ else {
+ if (netif_rx_schedule_prep(dev)) {
+ /* disable rx interrupts */
+ FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
+ __netif_rx_schedule(dev);
+ } else {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s driver bug! interrupt while in poll!\n",
+ dev->name);
+ FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
+ }
+ }
+ }
+
+ if ((int_events & FEC_ENET_TXF) != 0)
+ fec_enet_tx(dev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* This interrupt occurs when the PHY detects a link change. */
+static irqreturn_t
+fec_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fec_enet_private *fep;
+ const struct fec_platform_info *fpi;
+
+ if (unlikely(dev == NULL))
+ return IRQ_NONE;
+
+ fep = netdev_priv(dev);
+ fpi = fep->fpi;
+
+ if (!fpi->use_mdio)
+ return IRQ_NONE;
+
+ /*
+ * Acknowledge the interrupt if possible. If we have not
+ * found the PHY yet we can't process or acknowledge the
+ * interrupt now. Instead we ignore this interrupt for now,
+ * which we can do since it is edge triggered. It will be
+ * acknowledged later by fec_enet_open().
+ */
+ if (!fep->phy)
+ return IRQ_NONE;
+
+ fec_mii_ack_int(dev);
+ fec_mii_link_status_change_check(dev, 0);
+
+ return IRQ_HANDLED;
+}
+
+
+/**********************************************************************************/
+
+static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fecp;
+ cbd_t *bdp;
+ int curidx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fep->tx_lock, flags);
+
+ /*
+ * Fill in a Tx ring entry
+ */
+ bdp = fep->cur_tx;
+
+ if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+ /*
+ * Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since the tx queue should be stopped.
+ */
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s tx queue full!.\n", dev->name);
+ return 1;
+ }
+
+ curidx = bdp - fep->tx_bd_base;
+ /*
+ * Clear all of the status flags.
+ */
+ CBDC_SC(bdp, BD_ENET_TX_STATS);
+
+ /*
+ * Save skb pointer.
+ */
+ fep->tx_skbuff[curidx] = skb;
+
+ fep->stats.tx_bytes += skb->len;
+
+ /*
+ * Push the data cache so the CPM does not get stale memory data.
+ */
+ CBDW_BUFADDR(bdp, dma_map_single(NULL, skb->data,
+ skb->len, DMA_TO_DEVICE));
+ CBDW_DATLEN(bdp, skb->len);
+
+ dev->trans_start = jiffies;
+
+ /*
+ * If this was the last BD in the ring, start at the beginning again.
+ */
+ if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
+ fep->cur_tx++;
+ else
+ fep->cur_tx = fep->tx_bd_base;
+
+ if (!--fep->tx_free)
+ netif_stop_queue(dev);
+
+ /*
+ * Trigger transmission start
+ */
+ CBDS_SC(bdp, BD_ENET_TX_READY | BD_ENET_TX_INTR |
+ BD_ENET_TX_LAST | BD_ENET_TX_TC);
+ FW(fecp, x_des_active, 0x01000000);
+
+ spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+ return 0;
+}
+
+static void fec_timeout(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fep->stats.tx_errors++;
+
+ if (fep->tx_free)
+ netif_wake_queue(dev);
+
+ /* check link status again */
+ fec_mii_link_status_change_check(dev, 0);
+}
+
+static int fec_enet_open(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+ unsigned long flags;
+
+ /* Install our interrupt handler. */
+ if (request_irq(fpi->fec_irq, fec_enet_interrupt, 0, "fec", dev) != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s Could not allocate FEC IRQ!", dev->name);
+ return -EINVAL;
+ }
+
+ /* Install our phy interrupt handler */
+ if (fpi->phy_irq != -1 &&
+ request_irq(fpi->phy_irq, fec_mii_link_interrupt, 0, "fec-phy",
+ dev) != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s Could not allocate PHY IRQ!", dev->name);
+ free_irq(fpi->fec_irq, dev);
+ return -EINVAL;
+ }
+
+ if (fpi->use_mdio) {
+ fec_mii_startup(dev);
+ netif_carrier_off(dev);
+ fec_mii_link_status_change_check(dev, 1);
+ } else {
+ spin_lock_irqsave(&fep->lock, flags);
+ fec_restart(dev, 1, 100); /* XXX this sucks */
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+ }
+ return 0;
+}
+
+static int fec_enet_close(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ if (fpi->use_mdio)
+ fec_mii_shutdown(dev);
+
+ spin_lock_irqsave(&fep->lock, flags);
+ fec_stop(dev);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ /* release any irqs */
+ if (fpi->phy_irq != -1)
+ free_irq(fpi->phy_irq, dev);
+ free_irq(fpi->fec_irq, dev);
+
+ return 0;
+}
+
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ return &fep->stats;
+}
+
+static int fec_enet_poll(struct net_device *dev, int *budget)
+{
+ return fec_enet_rx_common(dev, budget);
+}
+
+/*************************************************************************/
+
+static void fec_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int fec_get_regs_len(struct net_device *dev)
+{
+ return sizeof(fec_t);
+}
+
+static void fec_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+
+ if (regs->len < sizeof(fec_t))
+ return;
+
+ regs->version = 0;
+ spin_lock_irqsave(&fep->lock, flags);
+ memcpy_fromio(p, fep->fecp, sizeof(fec_t));
+ spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+static int fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = mii_ethtool_gset(&fep->mii_if, cmd);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return rc;
+}
+
+static int fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = mii_ethtool_sset(&fep->mii_if, cmd);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return rc;
+}
+
+static int fec_nway_reset(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ return mii_nway_restart(&fep->mii_if);
+}
+
+static __u32 fec_get_msglevel(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ return fep->msg_enable;
+}
+
+static void fec_set_msglevel(struct net_device *dev, __u32 value)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fep->msg_enable = value;
+}
+
+static struct ethtool_ops fec_ethtool_ops = {
+ .get_drvinfo = fec_get_drvinfo,
+ .get_regs_len = fec_get_regs_len,
+ .get_settings = fec_get_settings,
+ .set_settings = fec_set_settings,
+ .nway_reset = fec_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = fec_get_msglevel,
+ .set_msglevel = fec_set_msglevel,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum, /* local! */
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_regs = fec_get_regs,
+};
+
+static int fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
+ unsigned long flags;
+ int rc;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+ spin_unlock_irqrestore(&fep->lock, flags);
+ return rc;
+}
+
+int fec_8xx_init_one(const struct fec_platform_info *fpi,
+ struct net_device **devp)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ static int fec_8xx_version_printed = 0;
+ struct net_device *dev = NULL;
+ struct fec_enet_private *fep = NULL;
+ fec_t *fecp = NULL;
+ int i;
+ int err = 0;
+ int registered = 0;
+ __u32 siel;
+
+ *devp = NULL;
+
+ switch (fpi->fec_no) {
+ case 0:
+ fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
+ break;
+#ifdef CONFIG_DUET
+ case 1:
+ fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec2;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ if (fec_8xx_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ i = sizeof(*fep) + (sizeof(struct sk_buff **) *
+ (fpi->rx_ring + fpi->tx_ring));
+
+ dev = alloc_etherdev(i);
+ if (!dev) {
+ err = -ENOMEM;
+ goto err;
+ }
+ SET_MODULE_OWNER(dev);
+
+ fep = netdev_priv(dev);
+
+ /* partial reset of FEC */
+ fec_whack_reset(fecp);
+
+ /* point rx_skbuff, tx_skbuff */
+ fep->rx_skbuff = (struct sk_buff **)&fep[1];
+ fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+ fep->fecp = fecp;
+ fep->fpi = fpi;
+
+ /* init locks */
+ spin_lock_init(&fep->lock);
+ spin_lock_init(&fep->tx_lock);
+
+ /*
+ * Set the Ethernet address.
+ */
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = fpi->macaddr[i];
+
+ fep->ring_base = dma_alloc_coherent(NULL,
+ (fpi->tx_ring + fpi->rx_ring) *
+ sizeof(cbd_t), &fep->ring_mem_addr,
+ GFP_KERNEL);
+ if (fep->ring_base == NULL) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s dma alloc failed.\n", dev->name);
+ err = -ENOMEM;
+ goto err;
+ }
+
+ /*
+ * Set receive and transmit descriptor base.
+ */
+ fep->rx_bd_base = fep->ring_base;
+ fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+ /* initialize ring size variables */
+ fep->tx_ring = fpi->tx_ring;
+ fep->rx_ring = fpi->rx_ring;
+
+ /* SIU interrupt */
+ if (fpi->phy_irq != -1 &&
+ (fpi->phy_irq >= SIU_IRQ0 && fpi->phy_irq < SIU_LEVEL7)) {
+
+ siel = in_be32(&immap->im_siu_conf.sc_siel);
+ if ((fpi->phy_irq & 1) == 0)
+ siel |= (0x80000000 >> fpi->phy_irq);
+ else
+ siel &= ~(0x80000000 >> (fpi->phy_irq & ~1));
+ out_be32(&immap->im_siu_conf.sc_siel, siel);
+ }
+
+ /*
+ * The FEC Ethernet specific entries in the device structure.
+ */
+ dev->open = fec_enet_open;
+ dev->hard_start_xmit = fec_enet_start_xmit;
+ dev->tx_timeout = fec_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = fec_enet_close;
+ dev->get_stats = fec_enet_get_stats;
+ dev->set_multicast_list = fec_set_multicast_list;
+ dev->set_mac_address = fec_set_mac_address;
+ if (fpi->use_napi) {
+ dev->poll = fec_enet_poll;
+ dev->weight = fpi->napi_weight;
+ }
+ dev->ethtool_ops = &fec_ethtool_ops;
+ dev->do_ioctl = fec_ioctl;
+
+ fep->fec_phy_speed =
+ ((((fpi->sys_clk + 4999999) / 2500000) / 2) & 0x3F) << 1;
+
+ init_timer(&fep->phy_timer_list);
+
+ /* partial reset of FEC so that only MII works */
+ FW(fecp, mii_speed, fep->fec_phy_speed);
+ FW(fecp, ievent, 0xffc0);
+ FW(fecp, ivec, (fpi->fec_irq / 2) << 29);
+ FW(fecp, imask, 0);
+ FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+
+ netif_carrier_off(dev);
+
+ err = register_netdev(dev);
+ if (err != 0)
+ goto err;
+ registered = 1;
+
+ if (fpi->use_mdio) {
+ fep->mii_if.dev = dev;
+ fep->mii_if.mdio_read = fec_mii_read;
+ fep->mii_if.mdio_write = fec_mii_write;
+ fep->mii_if.phy_id_mask = 0x1f;
+ fep->mii_if.reg_num_mask = 0x1f;
+ fep->mii_if.phy_id = fec_mii_phy_id_detect(dev);
+ }
+
+ *devp = dev;
+
+ return 0;
+
+ err:
+ if (dev != NULL) {
+ if (fecp != NULL)
+ fec_whack_reset(fecp);
+
+ if (registered)
+ unregister_netdev(dev);
+
+ if (fep != NULL) {
+ if (fep->ring_base)
+ dma_free_coherent(NULL,
+ (fpi->tx_ring +
+ fpi->rx_ring) *
+ sizeof(cbd_t), fep->ring_base,
+ fep->ring_mem_addr);
+ }
+ free_netdev(dev);
+ }
+ return err;
+}
+
+int fec_8xx_cleanup_one(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fecp;
+ const struct fec_platform_info *fpi = fep->fpi;
+
+ fec_whack_reset(fecp);
+
+ unregister_netdev(dev);
+
+ dma_free_coherent(NULL, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+ fep->ring_base, fep->ring_mem_addr);
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+/**************************************************************************************/
+/**************************************************************************************/
+/**************************************************************************************/
+
+static int __init fec_8xx_init(void)
+{
+ return fec_8xx_platform_init();
+}
+
+static void __exit fec_8xx_cleanup(void)
+{
+ fec_8xx_platform_cleanup();
+}
+
+/**************************************************************************************/
+/**************************************************************************************/
+/**************************************************************************************/
+
+module_init(fec_8xx_init);
+module_exit(fec_8xx_cleanup);
diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c
new file mode 100644
index 000000000000..700233655e52
--- /dev/null
+++ b/drivers/net/fec_8xx/fec_mii.c
@@ -0,0 +1,380 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/commproc.h>
+
+/*************************************************/
+
+#include "fec_8xx.h"
+
+/*************************************************/
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end 0
+
+/*************************************************/
+
+/* XXX both FECs use the MII interface of FEC1 */
+static spinlock_t fec_mii_lock = SPIN_LOCK_UNLOCKED;
+
+#define FEC_MII_LOOPS 10000
+
+int fec_mii_read(struct net_device *dev, int phy_id, int location)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp;
+ int i, ret = -1;
+ unsigned long flags;
+
+ /* XXX MII interface is only connected to FEC1 */
+ fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
+
+ spin_lock_irqsave(&fec_mii_lock, flags);
+
+ if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
+ FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, ievent, FEC_ENET_MII);
+ }
+
+ /* Add PHY address to register command. */
+ FW(fecp, mii_speed, fep->fec_phy_speed);
+ FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS) {
+ FW(fecp, ievent, FEC_ENET_MII);
+ ret = FR(fecp, mii_data) & 0xffff;
+ }
+
+ spin_unlock_irqrestore(&fec_mii_lock, flags);
+
+ return ret;
+}
+
+void fec_mii_write(struct net_device *dev, int phy_id, int location, int value)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp;
+ unsigned long flags;
+ int i;
+
+ /* XXX MII interface is only connected to FEC1 */
+ fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
+
+ spin_lock_irqsave(&fec_mii_lock, flags);
+
+ if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
+ FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, ievent, FEC_ENET_MII);
+ }
+
+ /* Add PHY address to register command. */
+ FW(fecp, mii_speed, fep->fec_phy_speed); /* always adapt mii speed */
+ FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS)
+ FW(fecp, ievent, FEC_ENET_MII);
+
+ spin_unlock_irqrestore(&fec_mii_lock, flags);
+}
+
+/*************************************************/
+
+#ifdef CONFIG_FEC_8XX_GENERIC_PHY
+
+/*
+ * Generic PHY support.
+ * Should work for all PHYs, but link change is detected by polling
+ */
+
+static void generic_timer_callback(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fep->phy_timer_list.expires = jiffies + HZ / 2;
+
+ add_timer(&fep->phy_timer_list);
+
+ fec_mii_link_status_change_check(dev, 0);
+}
+
+static void generic_startup(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
+ fep->phy_timer_list.data = (unsigned long)dev;
+ fep->phy_timer_list.function = generic_timer_callback;
+ add_timer(&fep->phy_timer_list);
+}
+
+static void generic_shutdown(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ del_timer_sync(&fep->phy_timer_list);
+}
+
+#endif
+
+#ifdef CONFIG_FEC_8XX_DM9161_PHY
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9161 is used on the NETTA board */
+
+/* register definitions */
+
+#define MII_DM9161_ACR 16 /* Aux. Config Register */
+#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
+#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
+#define MII_DM9161_INTR 21 /* Interrupt Register */
+#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
+#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
+
+static void dm9161_startup(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
+}
+
+static void dm9161_ack_int(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fec_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
+}
+
+static void dm9161_shutdown(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
+}
+
+#endif
+
+/**********************************************************************************/
+
+static const struct phy_info phy_info[] = {
+#ifdef CONFIG_FEC_8XX_DM9161_PHY
+ {
+ .id = 0x00181b88,
+ .name = "DM9161",
+ .startup = dm9161_startup,
+ .ack_int = dm9161_ack_int,
+ .shutdown = dm9161_shutdown,
+ },
+#endif
+#ifdef CONFIG_FEC_8XX_GENERIC_PHY
+ {
+ .id = 0,
+ .name = "GENERIC",
+ .startup = generic_startup,
+ .shutdown = generic_shutdown,
+ },
+#endif
+};
+
+/**********************************************************************************/
+
+int fec_mii_phy_id_detect(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+ int i, r, start, end, phytype, physubtype;
+ const struct phy_info *phy;
+ int phy_hwid, phy_id;
+
+ /* if no MDIO */
+ if (fpi->use_mdio == 0)
+ return -1;
+
+ phy_hwid = -1;
+ fep->phy = NULL;
+
+ /* auto-detect? */
+ if (fpi->phy_addr == -1) {
+ start = 0;
+ end = 32;
+ } else { /* direct */
+ start = fpi->phy_addr;
+ end = start + 1;
+ }
+
+ for (phy_id = start; phy_id < end; phy_id++) {
+ r = fec_mii_read(dev, phy_id, MII_PHYSID1);
+ if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
+ continue;
+ r = fec_mii_read(dev, phy_id, MII_PHYSID2);
+ if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
+ continue;
+ phy_hwid = (phytype << 16) | physubtype;
+ if (phy_hwid != -1)
+ break;
+ }
+
+ if (phy_hwid == -1) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s No PHY detected!\n", dev->name);
+ return -1;
+ }
+
+ for (i = 0, phy = phy_info; i < sizeof(phy_info) / sizeof(phy_info[0]);
+ i++, phy++)
+ if (phy->id == (phy_hwid >> 4) || phy->id == 0)
+ break;
+
+ if (i >= sizeof(phy_info) / sizeof(phy_info[0])) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s PHY id 0x%08x is not supported!\n",
+ dev->name, phy_hwid);
+ return -1;
+ }
+
+ fep->phy = phy;
+
+ printk(KERN_INFO DRV_MODULE_NAME
+ ": %s Phy @ 0x%x, type %s (0x%08x)\n",
+ dev->name, phy_id, fep->phy->name, phy_hwid);
+
+ return phy_id;
+}
+
+void fec_mii_startup(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+
+ if (!fpi->use_mdio || fep->phy == NULL)
+ return;
+
+ if (fep->phy->startup == NULL)
+ return;
+
+ (*fep->phy->startup) (dev);
+}
+
+void fec_mii_shutdown(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+
+ if (!fpi->use_mdio || fep->phy == NULL)
+ return;
+
+ if (fep->phy->shutdown == NULL)
+ return;
+
+ (*fep->phy->shutdown) (dev);
+}
+
+void fec_mii_ack_int(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ const struct fec_platform_info *fpi = fep->fpi;
+
+ if (!fpi->use_mdio || fep->phy == NULL)
+ return;
+
+ if (fep->phy->ack_int == NULL)
+ return;
+
+ (*fep->phy->ack_int) (dev);
+}
+
+/* helper function */
+static int mii_negotiated(struct mii_if_info *mii)
+{
+ int advert, lpa, val;
+
+ if (!mii_link_ok(mii))
+ return 0;
+
+ val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
+ if ((val & BMSR_ANEGCOMPLETE) == 0)
+ return 0;
+
+ advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
+ lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
+
+ return mii_nway_result(advert & lpa);
+}
+
+void fec_mii_link_status_change_check(struct net_device *dev, int init_media)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ unsigned int media;
+ unsigned long flags;
+
+ if (mii_check_media(&fep->mii_if, netif_msg_link(fep), init_media) == 0)
+ return;
+
+ media = mii_negotiated(&fep->mii_if);
+
+ if (netif_carrier_ok(dev)) {
+ spin_lock_irqsave(&fep->lock, flags);
+ fec_restart(dev, !!(media & ADVERTISE_FULL),
+ (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ?
+ 100 : 10);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ netif_start_queue(dev);
+ } else {
+ netif_stop_queue(dev);
+
+ spin_lock_irqsave(&fep->lock, flags);
+ fec_stop(dev);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ }
+}
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index d6c008b26a0a..5111c8e6badf 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -77,7 +77,7 @@ struct ixgb_adapter;
#include "ixgb_ee.h"
#include "ixgb_ids.h"
-#if _DEBUG_DRIVER_
+#ifdef _DEBUG_DRIVER_
#define IXGB_DBG(args...) printk(KERN_DEBUG "ixgb: " args)
#else
#define IXGB_DBG(args...)
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index e81ac44e7609..9eacbdec573e 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -139,12 +139,6 @@
* NAPI
*/
-#if !defined(__OPTIMIZE__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 59d80ebbe88c..7c4ed0ddd12a 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -360,7 +360,10 @@ static void tc574_detach(dev_link_t *link)
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
- return;
+ return;
+
+ if (link->dev)
+ unregister_netdev(dev);
if (link->state & DEV_CONFIG)
tc574_release(link);
@@ -370,8 +373,6 @@ static void tc574_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* tc574_detach */
@@ -580,10 +581,8 @@ static int tc574_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- tc574_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index be997bd296e7..2e0135dad547 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -276,6 +276,9 @@ static void tc589_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
tc589_release(link);
@@ -284,8 +287,6 @@ static void tc589_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* tc589_detach */
@@ -456,10 +457,8 @@ static int tc589_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- tc589_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index ea5a88cf73e6..bf70b18c58b1 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -231,6 +231,9 @@ static void axnet_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
axnet_release(link);
@@ -239,8 +242,6 @@ static void axnet_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* axnet_detach */
@@ -525,10 +526,8 @@ static int axnet_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- axnet_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 9ce8df6f2bcf..a824548388d8 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -262,6 +262,19 @@ static void com20020_detach(dev_link_t *link)
dev = info->dev;
+ if (link->dev) {
+ DEBUG(1,"unregister...\n");
+
+ unregister_netdev(dev);
+
+ /*
+ * this is necessary because we register our IRQ separately
+ * from card services.
+ */
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ }
+
if (link->state & DEV_CONFIG)
com20020_release(link);
@@ -276,21 +289,6 @@ static void com20020_detach(dev_link_t *link)
dev = info->dev;
if (dev)
{
- if (link->dev)
- {
- DEBUG(1,"unregister...\n");
-
- unregister_netdev(dev);
-
- /*
- * this is necessary because we register our IRQ separately
- * from card services.
- */
- if (dev->irq)
- free_irq(dev->irq, dev);
- /* ...but I/O ports are done automatically by card services */
- }
-
DEBUG(1,"kfree...\n");
free_netdev(dev);
}
@@ -461,10 +459,8 @@ static int com20020_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- link->state |= DEV_RELEASE_PENDING;
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 580af370930b..9c40e61fa1bc 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -332,6 +332,9 @@ static void fmvj18x_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
fmvj18x_release(link);
@@ -341,8 +344,6 @@ static void fmvj18x_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* fmvj18x_detach */
@@ -741,10 +742,8 @@ static int fmvj18x_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- fmvj18x_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index beccf9e9535d..884ee94ea279 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -446,7 +446,6 @@ static int ibmtr_event(event_t event, int priority,
struct tok_info *priv = netdev_priv(dev);
priv->sram_virt |= 1;
netif_device_detach(dev);
- ibmtr_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index bcf284bbb453..475d68dffc45 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -551,6 +551,9 @@ static void nmclan_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
nmclan_release(link);
@@ -559,8 +562,6 @@ static void nmclan_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* nmclan_detach */
@@ -834,10 +835,8 @@ static int nmclan_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- nmclan_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b53f5fcf5d12..2db4baabe9c9 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -326,6 +326,9 @@ static void pcnet_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
pcnet_release(link);
@@ -334,8 +337,6 @@ static void pcnet_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* pcnet_detach */
@@ -806,10 +807,8 @@ static int pcnet_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- pcnet_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 7c1bd346e09d..d3d35ef7d31d 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -411,6 +411,9 @@ static void smc91c92_detach(dev_link_t *link)
if (*linkp == NULL)
return;
+ if (link->dev)
+ unregister_netdev(dev);
+
if (link->state & DEV_CONFIG)
smc91c92_release(link);
@@ -419,8 +422,6 @@ static void smc91c92_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* smc91c92_detach */
@@ -1112,10 +1113,8 @@ static int smc91c92_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- smc91c92_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index d4cc269029df..870a2d25c1d2 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -668,6 +668,9 @@ xirc2ps_detach(dev_link_t * link)
return;
}
+ if (link->dev)
+ unregister_netdev(dev);
+
/*
* If the device is currently configured and active, we won't
* actually delete it yet. Instead, it is marked so that when
@@ -683,8 +686,6 @@ xirc2ps_detach(dev_link_t * link)
/* Unlink device structure, free it */
*linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
free_netdev(dev);
} /* xirc2ps_detach */
@@ -1203,10 +1204,8 @@ xirc2ps_event(event_t event, int priority,
break;
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
+ if (link->state & DEV_CONFIG)
netif_device_detach(dev);
- xirc2ps_release(link);
- }
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ed687ec42b28..c57cb341f769 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.30f"
-#define DRV_RELDATE "06.16.2004"
+#define DRV_VERSION "1.30i"
+#define DRV_RELDATE "06.28.2004"
#define PFX DRV_NAME ": "
static const char *version =
@@ -46,6 +46,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
#include <asm/bitops.h>
#include <asm/dma.h>
@@ -137,6 +138,7 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
#define MAX_UNITS 8 /* More are supported, limit only on options */
static int options[MAX_UNITS];
static int full_duplex[MAX_UNITS];
+static int homepna[MAX_UNITS];
/*
* Theory of Operation
@@ -250,6 +252,10 @@ static int full_duplex[MAX_UNITS];
* v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI,
* expanding on suggestions from Ralf Baechle <ralf@linux-mips.org>,
* and Brian Murphy <brian@murphy.dk>.
+ * v1.30g 22 Jun 2004 Patrick Simmons <psimmons@flash.net> added option
+ * homepna for selecting HomePNA mode for PCNet/Home 79C978.
+ * v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
+ * v1.30i 28 Jun 2004 Don Fry change to use module_param.
*/
@@ -1084,15 +1090,17 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
fdx = 1;
/*
* This is based on specs published at www.amd.com. This section
- * assumes that a card with a 79C978 wants to go into 1Mb HomePNA
- * mode. The 79C978 can also go into standard ethernet, and there
- * probably should be some sort of module option to select the
- * mode by which the card should operate
+ * assumes that a card with a 79C978 wants to go into standard
+ * ethernet mode. The 79C978 can also go into 1Mb HomePNA mode,
+ * and the module option homepna=1 can select this instead.
*/
- /* switch to home wiring mode */
media = a->read_bcr(ioaddr, 49);
+ media &= ~3; /* default to 10Mb ethernet */
+ if (cards_found < MAX_UNITS && homepna[cards_found])
+ media |= 1; /* switch to home wiring mode */
if (pcnet32_debug & NETIF_MSG_PROBE)
- printk(KERN_DEBUG PFX "media reset to %#x.\n", media);
+ printk(KERN_DEBUG PFX "media set to %sMbit mode.\n",
+ (media & 1) ? "1" : "10");
a->write_bcr(ioaddr, 49, media);
break;
case 0x2627:
@@ -1417,9 +1425,13 @@ pcnet32_open(struct net_device *dev)
val |= 0x10;
lp->a.write_csr (ioaddr, 124, val);
+ /* 24 Jun 2004 according AMD, in order to change the PHY,
+ * DANAS (or DISPM for 79C976) must be set; then select the speed,
+ * duplex, and/or enable auto negotiation, and clear DANAS */
if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
+ lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
/* disable Auto Negotiation, set 10Mpbs, HD */
- val = lp->a.read_bcr (ioaddr, 32) & ~0x38;
+ val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
if (lp->options & PCNET32_PORT_FD)
val |= 0x10;
if (lp->options & PCNET32_PORT_100)
@@ -1427,6 +1439,7 @@ pcnet32_open(struct net_device *dev)
lp->a.write_bcr (ioaddr, 32, val);
} else {
if (lp->options & PCNET32_PORT_ASEL) {
+ lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
/* enable auto negotiate, setup, disable fd */
val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
val |= 0x20;
@@ -1753,7 +1766,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
spin_lock(&lp->lock);
rap = lp->a.read_rap(ioaddr);
- while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
+ while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) {
if (csr0 == 0xffff) {
break; /* PCMCIA remove happened */
}
@@ -2247,20 +2260,29 @@ static struct pci_driver pcnet32_driver = {
.id_table = pcnet32_pci_tbl,
};
-MODULE_PARM(debug, "i");
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+static int tx_start_pt = -1;
+static int pcnet32_have_pci;
+static int num_params;
+
+module_param(debug, int, 0);
MODULE_PARM_DESC(debug, DRV_NAME " debug level");
-MODULE_PARM(max_interrupt_work, "i");
+module_param(max_interrupt_work, int, 0);
MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt");
-MODULE_PARM(rx_copybreak, "i");
+module_param(rx_copybreak, int, 0);
MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM(tx_start_pt, "i");
+module_param(tx_start_pt, int, 0);
MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)");
-MODULE_PARM(pcnet32vlb, "i");
+module_param(pcnet32vlb, int, 0);
MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+module_param_array(options, int, num_params, 0);
MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+module_param_array(full_duplex, int, num_params, 0);
MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)");
+/* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */
+module_param_array(homepna, int, num_params, 0);
+MODULE_PARM_DESC(homepna, DRV_NAME " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet");
MODULE_AUTHOR("Thomas Bogendoerfer");
MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
@@ -2268,11 +2290,6 @@ MODULE_LICENSE("GPL");
#define PCNET32_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
-/* An additional parameter that may be passed in... */
-static int debug = -1;
-static int tx_start_pt = -1;
-static int pcnet32_have_pci;
-
static int __init pcnet32_init_module(void)
{
printk(KERN_INFO "%s", version);
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 39b09cd6ba13..e0f88fbd33f5 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -55,12 +55,6 @@ static int int_timeout = 0;
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (2*HZ)
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
index 652775ecb3e6..ea76a95f4e9a 100644
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ b/drivers/net/sk98lin/h/skdrv1st.h
@@ -58,12 +58,6 @@ typedef struct s_AC SK_AC;
#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6))
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/version.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
index d2b43139375f..1f3b423f2635 100644
--- a/drivers/net/skfp/fplustm.c
+++ b/drivers/net/skfp/fplustm.c
@@ -141,16 +141,17 @@ void mac_update_counter(struct s_smc *smc)
/*
* write long value into buffer memory over memory data register (MDR),
*/
-void write_mdr(struct s_smc *smc, u_long val)
+static void write_mdr(struct s_smc *smc, u_long val)
{
CHECK_NPP() ;
MDRW(val) ;
}
+#if 0
/*
* read long value from buffer memory over memory data register (MDR),
*/
-u_long read_mdr(struct s_smc *smc, unsigned int addr)
+static u_long read_mdr(struct s_smc *smc, unsigned int addr)
{
long p ;
CHECK_NPP() ;
@@ -164,6 +165,8 @@ u_long read_mdr(struct s_smc *smc, unsigned int addr)
p += (u_long)inpw(FM_A(FM_MDRL)) ;
return(p) ;
}
+#endif
+
/*
* clear buffer memory
*/
@@ -529,7 +532,7 @@ static void build_claim_beacon(struct s_smc *smc, u_long t_request)
outpw(FM_A(FM_RPXSF),0) ;
}
-void formac_rcv_restart(struct s_smc *smc)
+static void formac_rcv_restart(struct s_smc *smc)
{
/* enable receive function */
SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
@@ -1018,25 +1021,6 @@ void sm_mac_check_beacon_claim(struct s_smc *smc)
/*-------------------------- interface functions ----------------------------*/
/*
- * control ODL output
- */
-void sm_pm_control(struct s_smc *smc, int mode)
-{
- SK_UNUSED(smc) ;
-
- /*
- * if PCM logic has set LS_REQUEST = Transmit QUIET Line State
- * /FOTOFF signal turn activ -> ODL disable
- */
- switch(mode) {
- case PM_TRANSMIT_DISABLE :
- break ;
- case PM_TRANSMIT_ENABLE :
- break ;
- }
-}
-
-/*
* control MAC layer (called by RMT)
*/
void sm_ma_control(struct s_smc *smc, int mode)
diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h
index 899c8c0413b0..603982debc71 100644
--- a/drivers/net/skfp/h/cmtdef.h
+++ b/drivers/net/skfp/h/cmtdef.h
@@ -571,10 +571,6 @@ int cfm_get_mac_output(struct s_smc *smc);
int port_to_mib(struct s_smc *smc, int p);
int cem_build_path(struct s_smc *smc, char *to, int path_index);
int sm_mac_get_tx_state(struct s_smc *smc);
-int is_individual(struct fddi_addr *addr);
-int is_my_addr(struct s_smc *smc, struct fddi_addr *addr);
-int is_broadcast(struct fddi_addr *addr);
-int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2);
char *get_pcmstate(struct s_smc *smc, int np);
int smt_action(struct s_smc *smc, int class, int code, int index);
u_short smt_online(struct s_smc *smc, int on);
diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/skfp/h/targetos.h
index 94a81eede792..59de39e293fa 100644
--- a/drivers/net/skfp/h/targetos.h
+++ b/drivers/net/skfp/h/targetos.h
@@ -110,7 +110,7 @@
struct s_skfp_ioctl {
unsigned short cmd; /* Command to run */
unsigned short len; /* Length of the data buffer */
- unsigned char *data; /* Pointer to the data buffer */
+ unsigned char __user *data; /* Pointer to the data buffer */
};
/*
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index a5e5d874c1f2..1eee9d37fd9d 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -909,7 +909,10 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
dmi = dev->mc_list;
for (i = 0; i < dev->mc_count; i++) {
- mac_add_multicast(smc, dmi->dmi_addr, 1);
+ mac_add_multicast(smc,
+ (struct fddi_addr *)dmi->dmi_addr,
+ 1);
+
PRINTK(KERN_INFO "ENABLE MC ADDRESS:");
PRINTK(" %02x %02x %02x ",
dmi->dmi_addr[0],
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index 8301daf21e48..43f78c74c845 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -76,8 +76,8 @@ static int mac_con_resource_index(struct s_smc *smc, int mac);
static int phy_con_resource_index(struct s_smc *smc, int phy);
static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
int local);
-static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc,
- u_long tid, int type, int local);
+static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest,
+ int fc, u_long tid, int type, int local);
static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
u_long tid, int type, int len);
static void smt_echo_test(struct s_smc *smc, int dna);
@@ -123,6 +123,45 @@ void hwm_conv_can(struct s_smc *smc, char *data, int len);
#define hwm_conv_can(smc,data,len)
#endif
+
+static inline int is_my_addr(const struct s_smc *smc,
+ const struct fddi_addr *addr)
+{
+ return(*(short *)(&addr->a[0]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
+ && *(short *)(&addr->a[2]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
+ && *(short *)(&addr->a[4]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
+}
+
+static inline int is_zero(const struct fddi_addr *addr)
+{
+ return(*(short *)(&addr->a[0]) == 0 &&
+ *(short *)(&addr->a[2]) == 0 &&
+ *(short *)(&addr->a[4]) == 0 ) ;
+}
+
+static inline int is_broadcast(const struct fddi_addr *addr)
+{
+ return(*(u_short *)(&addr->a[0]) == 0xffff &&
+ *(u_short *)(&addr->a[2]) == 0xffff &&
+ *(u_short *)(&addr->a[4]) == 0xffff ) ;
+}
+
+static inline int is_individual(const struct fddi_addr *addr)
+{
+ return(!(addr->a[0] & GROUP_ADDR)) ;
+}
+
+static inline int is_equal(const struct fddi_addr *addr1,
+ const struct fddi_addr *addr2)
+{
+ return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
+ *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
+ *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;
+}
+
/*
* list of mandatory paras in frames
*/
@@ -382,7 +421,7 @@ void smt_event(struct s_smc *smc, int event)
*/
if (!smc->sm.pend[SMT_TID_NIF])
smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
- smt_send_nif(smc,&fddi_broadcast,FC_SMT_NSA,
+ smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
smc->sm.smt_last_notify = time ;
}
@@ -926,8 +965,8 @@ static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
/*
* generate and send NIF
*/
-static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc,
- u_long tid, int type, int local)
+static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest,
+ int fc, u_long tid, int type, int local)
/* struct fddi_addr *dest; dest address */
/* int fc; frame control */
/* u_long tid; transaction id */
@@ -1688,43 +1727,6 @@ void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
return(0) ;
}
-int is_my_addr(struct s_smc *smc, struct fddi_addr *addr)
-{
- return(*(short *)(&addr->a[0]) ==
- *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
- && *(short *)(&addr->a[2]) ==
- *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
- && *(short *)(&addr->a[4]) ==
- *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
-}
-
-int is_zero(struct fddi_addr *addr)
-{
- return(*(short *)(&addr->a[0]) == 0 &&
- *(short *)(&addr->a[2]) == 0 &&
- *(short *)(&addr->a[4]) == 0 ) ;
-}
-
-int is_broadcast(struct fddi_addr *addr)
-{
- return(*(u_short *)(&addr->a[0]) == 0xffff &&
- *(u_short *)(&addr->a[2]) == 0xffff &&
- *(u_short *)(&addr->a[4]) == 0xffff ) ;
-}
-
-int is_individual(struct fddi_addr *addr)
-{
- return(!(addr->a[0] & GROUP_ADDR)) ;
-}
-
-int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2)
-{
- return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
- *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
- *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;
-}
-
-
#if 0
/*
* send ANTC data test frame
diff --git a/drivers/net/arm/smc91x.c b/drivers/net/smc91x.c
index 3968a1cd50d7..0bacd06a3d76 100644
--- a/drivers/net/arm/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -86,7 +86,9 @@ static const char version[] =
#include <linux/skbuff.h>
#include <asm/io.h>
+#ifdef CONFIG_ARM
#include <asm/hardware.h>
+#endif
#include <asm/irq.h>
#include "smc91x.h"
diff --git a/drivers/net/arm/smc91x.h b/drivers/net/smc91x.h
index 5212e3763bcb..7679022c0729 100644
--- a/drivers/net/arm/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -59,6 +59,43 @@
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+#elif defined(CONFIG_REDWOOD_5) || defined(CONFIG_REDWOOD_6)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_NOWAIT 1
+
+#define SMC_IO_SHIFT 0
+
+#define SMC_inw(a, r) in_be16((volatile u16 *)((a) + (r)))
+#define SMC_outw(v, a, r) out_be16((volatile u16 *)((a) + (r)), v)
+#define SMC_insw(a, r, p, l) \
+ do { \
+ unsigned long __port = (a) + (r); \
+ u16 *__p = (u16 *)(p); \
+ int __l = (l); \
+ insw(__port, __p, __l); \
+ while (__l > 0) { \
+ *__p = swab16(*__p); \
+ __p++; \
+ __l--; \
+ } \
+ } while (0)
+#define SMC_outsw(a, r, p, l) \
+ do { \
+ unsigned long __port = (a) + (r); \
+ u16 *__p = (u16 *)(p); \
+ int __l = (l); \
+ while (__l > 0) { \
+ /* Believe it or not, the swab isn't needed. */ \
+ outw( /* swab16 */ (*__p++), __port); \
+ __l--; \
+ } \
+ } while (0)
+#define set_irq_type(irq, type)
+
#elif defined(CONFIG_SA1100_ASSABET)
#include <asm/arch/neponset.h>
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index e5069fca1792..44c7aa512300 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -148,15 +148,6 @@ static char *media[MAX_UNITS];
#define TX_TIMEOUT (4*HZ)
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-#if !defined(__OPTIMIZE__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
/* Include files, designed to support most kernel versions 2.0.0 and later. */
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 6246e443f496..22d57c86a36d 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -111,15 +111,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-#if !defined(__OPTIMIZE__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
/* Include files, designed to support most kernel versions 2.0.0 and later. */
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 45ab1999ded9..142f5f52f31a 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -90,12 +90,6 @@ static const int multicast_filter_limit = 32;
#define PFX DRV_MODULE_NAME ": "
#define ERR_PFX KERN_ERR PFX
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 47443254c985..5589393ee682 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -183,12 +183,6 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/wan/sbni.h b/drivers/net/wan/sbni.h
index 8e83e274824d..27715e70f28b 100644
--- a/drivers/net/wan/sbni.h
+++ b/drivers/net/wan/sbni.h
@@ -6,7 +6,7 @@
#ifndef SBNI_H
#define SBNI_H
-#if SBNI_DEBUG
+#ifdef SBNI_DEBUG
#define DP( A ) A
#else
#define DP( A )
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index dc84928d946b..7aa05d696da3 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -577,7 +577,7 @@ prism54_set_scan(struct net_device *dev, struct iw_request_info *info,
* the "Aironet driver for 4500 and 4800 series cards" (GPL)
*/
-inline char *
+static char *
prism54_translate_bss(struct net_device *ndev, char *current_ev,
char *end_buf, struct obj_bss *bss, char noise)
{
@@ -1502,7 +1502,7 @@ prism54_kick_mac(struct net_device *ndev, struct iw_request_info *info,
/* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */
-static inline void
+static void
format_event(islpci_private *priv, char *dest, const char *str,
const struct obj_mlme *mlme, u16 *length, int error)
{
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index b980edccf163..62847f475237 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -41,6 +41,9 @@
#define ISL3877_IMAGE_FILE "isl3877"
#define ISL3890_IMAGE_FILE "isl3890"
+static int prism54_bring_down(islpci_private *);
+static int islpci_alloc_memory(islpci_private *);
+
/* Temporary dummy MAC address to use until firmware is loaded.
* The idea there is that some tools (such as nameif) may query
* the MAC address before the netdev is 'open'. By using a valid
@@ -390,7 +393,7 @@ islpci_close(struct net_device *ndev)
return prism54_bring_down(priv);
}
-int
+static int
prism54_bring_down(islpci_private *priv)
{
void *device_base = priv->device_base;
@@ -601,7 +604,7 @@ islpci_statistics(struct net_device *ndev)
/******************************************************************************
Network device configuration functions
******************************************************************************/
-int
+static int
islpci_alloc_memory(islpci_private *priv)
{
int counter;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 19fbd6bfdfff..e0ec5de036f5 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -210,8 +210,6 @@ islpci_trigger(islpci_private *priv)
struct net_device_stats *islpci_statistics(struct net_device *);
-int prism54_bring_down(islpci_private *);
-int islpci_alloc_memory(islpci_private *);
int islpci_free_memory(islpci_private *);
struct net_device *islpci_setup(struct pci_dev *);
#endif /* _ISLPCI_DEV_H */
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 4f82bfa1e6de..9ae71e92b08d 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -121,7 +121,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
/* Check alignment and WDS frame formatting. The start of the packet should
* be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes
* and add WDS address information */
- if (unlikely(((long) skb->data & 0x03) | init_wds)) {
+ if (likely(((long) skb->data & 0x03) | init_wds)) {
/* get the number of bytes to add and re-allign */
offset = (4 - (long) skb->data) & 0x03;
offset += init_wds ? 6 : 0;
@@ -156,6 +156,12 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
} else {
newskb =
dev_alloc_skb(init_wds ? skb->len + 6 : skb->len);
+ if (unlikely(newskb == NULL)) {
+ printk(KERN_ERR "%s: Cannot allocate skb\n",
+ ndev->name);
+ err = -ENOMEM;
+ goto drop_free;
+ }
newskb_offset = (4 - (long) newskb->data) & 0x03;
/* Check if newskb->data is aligned */
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 3fe59fb8ffa8..35bde675a6a1 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -38,81 +38,111 @@ MODULE_LICENSE("GPL");
/* In this order: vendor, device, subvendor, subdevice, class, class_mask,
* driver_data
- * Note: for driver_data we put the device's name
* If you have an update for this please contact prism54-devel@prism54.org
* The latest list can be found at http://prism54.org/supported_cards.php */
static const struct pci_device_id prism54_id_tbl[] = {
+ /* 3COM 3CRWE154G72 Wireless LAN adapter */
{
PCIVENDOR_3COM, PCIDEVICE_3COM6001,
PCIVENDOR_3COM, PCIDEVICE_3COM6001,
- 0, 0,
- (unsigned long) "3COM 3CRWE154G72 Wireless LAN adapter"},
+ 0, 0, 0
+ },
+
+ /* D-Link Air Plus Xtreme G A1 - DWL-g650 A1 */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_DLINK, 0x3202UL,
- 0, 0,
- (unsigned long) "D-Link Air Plus Xtreme G A1 - DWL-g650 A1"},
+ 0, 0, 0
+ },
+
+ /* I-O Data WN-G54/CB - WN-G54/CB */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_IODATA, 0xd019UL,
- 0, 0,
- (unsigned long) "I-O Data WN-G54/CB - WN-G54/CB"},
+ 0, 0, 0
+ },
+
+ /* Netgear WG511 */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_NETGEAR, 0x4800UL,
- 0, 0,
- (unsigned long) "Netgear WG511"},
+ 0, 0, 0
+ },
+
+ /* Tekram Technology clones, Allnet, Netcomm, Zyxel */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
- PCIVENDOR_I4, 0x0020UL,
- 0, 0,
- (unsigned long) "PLANEX GW-DS54G"},
+ PCIVENDOR_TTL, 0x1605UL,
+ 0, 0, 0
+ },
+
+ /* SMC2802W */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_SMC, 0x2802UL,
- 0, 0,
- (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card - SMC2802W"},
+ 0, 0, 0
+ },
+
+ /* SMC2835W */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_SMC, 0x2835UL,
- 0, 0,
- (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Adapter - SMC2835W"},
+ 0, 0, 0
+ },
+
+ /* Corega CG-WLCB54GT */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
- PCIVENDOR_INTERSIL, 0x0000UL, /* This was probably a bogus reading... */
- 0, 0,
- (unsigned long) "SparkLAN WL-850F"},
+ PCIVENDOR_ATI, 0xc104UL,
+ 0, 0, 0
+ },
+
+ /* I4 Z-Com XG-600 */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_I4, 0x0014UL,
- 0, 0,
- (unsigned long) "I4 Z-Com XG-600"},
+ 0, 0, 0
+ },
+
+ /* I4 Z-Com XG-900 and clones Macer, Ovislink, Planex, Peabird, */
+ /* Sitecom, Xterasys */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_I4, 0x0020UL,
- 0, 0,
- (unsigned long) "I4 Z-Com XG-900/PLANEX GW-DS54G"},
+ 0, 0, 0
+ },
+
+ /* SMC 2802W V2 */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_ACCTON, 0xee03UL,
- 0, 0,
- (unsigned long) "SMC 2802Wv2"},
+ 0, 0, 0
+ },
+
+ /* SMC 2835W V2 */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCIVENDOR_SMC, 0xa835UL,
- 0, 0,
- (unsigned long) "SMC 2835Wv2"},
+ 0, 0, 0
+ },
+
+ /* Intersil PRISM Indigo Wireless LAN adapter */
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3877,
PCI_ANY_ID, PCI_ANY_ID,
- 0, 0,
- (unsigned long) "Intersil PRISM Indigo Wireless LAN adapter"},
- { /* Default */
+ 0, 0, 0
+ },
+
+ /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
+ /* Default */
+ {
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
PCI_ANY_ID, PCI_ANY_ID,
- 0, 0,
- (unsigned long) "Intersil PRISM Duette/Prism GT Wireless LAN adapter"},
- {0,}
+ 0, 0, 0
+ },
+
+ /* End of list */
+ {0,0,0,0,0,0,0}
};
/* register the device with the Hotplug facilities of the kernel */
@@ -138,12 +168,16 @@ prism54_get_card_model(struct net_device *ndev)
{
islpci_private *priv;
char *modelp;
+ int notwork = 0;
priv = netdev_priv(ndev);
switch (priv->pdev->subsystem_device) {
case PCIDEVICE_ISL3877:
modelp = "PRISM Indigo";
break;
+ case PCIDEVICE_ISL3886:
+ modelp = "PRISM Javelin / Xbow";
+ break;
case PCIDEVICE_3COM6001:
modelp = "3COM 3CRWE154G72";
break;
@@ -161,12 +195,20 @@ prism54_get_card_model(struct net_device *ndev)
break;
case 0xee03UL:
modelp = "SMC2802W V2";
+ notwork = 1;
break;
case 0x2835UL:
modelp = "SMC2835W";
break;
case 0xa835UL:
modelp = "SMC2835W V2";
+ notwork = 1;
+ break;
+ case 0xc104UL:
+ modelp = "CG-WLCB54GT";
+ break;
+ case 0x1605UL:
+ modelp = "Tekram Technology clone";
break;
/* Let's leave this one out for now since it seems bogus/wrong
* Even if the manufacturer did use 0x0000UL it may not be correct
@@ -177,10 +219,10 @@ prism54_get_card_model(struct net_device *ndev)
/* We have two reported for the one below :( */
case 0x0014UL:
- modelp = "XG-600";
+ modelp = "I4 Z-Com XG-600 and clones";
break;
case 0x0020UL:
- modelp = "XG-900/GW-DS54G";
+ modelp = "I4 Z-Com XG-900 and clones";
break;
/* Default it */
/*
@@ -193,6 +235,10 @@ prism54_get_card_model(struct net_device *ndev)
}
printk(KERN_DEBUG "%s: %s driver detected card model: %s\n",
ndev->name, DRV_NAME, modelp);
+ if ( notwork ) {
+ printk(KERN_DEBUG "%s: %s Warning - This may not work\n",
+ ndev->name, DRV_NAME);
+ }
return;
}
@@ -247,8 +293,13 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* Writing zero to both these two registers will disable both timeouts and
* *can* solve problems caused by devices that are slow to respond.
*/
+ /* I am taking these out, we should not be poking around in the
+ * programmable timers - MSW
+ */
+/* Do not zero the programmable timers
pci_write_config_byte(pdev, 0x40, 0);
pci_write_config_byte(pdev, 0x41, 0);
+*/
/* request the pci device I/O regions */
rvalue = pci_request_regions(pdev, DRV_NAME);
@@ -270,6 +321,9 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME);
pci_set_master(pdev);
+ /* enable MWI */
+ pci_set_mwi(pdev);
+
/* setup the network device interface and its structure */
if (!(ndev = islpci_setup(pdev))) {
/* error configuring the driver as a network device */
diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
index 72cb87a9616d..2e8f8ea9c7de 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.h
+++ b/drivers/net/wireless/prism54/islpci_mgt.h
@@ -46,8 +46,11 @@ extern int pc_debug;
#define PCIVENDOR_NETGEAR 0x1385UL
#define PCIVENDOR_SMC 0x10b8UL
#define PCIVENDOR_ACCTON 0x1113UL
+#define PCIVENDOR_ATI 0x1259UL
+#define PCIVENDOR_TTL 0x16a5UL
#define PCIDEVICE_ISL3877 0x3877UL
+#define PCIDEVICE_ISL3886 0x3886UL
#define PCIDEVICE_ISL3890 0x3890UL
#define PCIDEVICE_3COM6001 0x6001UL
#define PCIDEVICE_LATENCY_TIMER_MIN 0x40
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index 470466d132f3..f4c2d1d4c015 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -675,7 +675,7 @@ mgt_commit(islpci_private *priv)
/* This will tell you if you are allowed to answer a mlme(ex) request .*/
-inline int
+int
mgt_mlme_answer(islpci_private *priv)
{
u32 mlmeautolevel;
@@ -692,7 +692,7 @@ mgt_mlme_answer(islpci_private *priv)
(mlmeautolevel >= DOT11_MLME_INTERMEDIATE));
}
-inline enum oid_num_t
+enum oid_num_t
mgt_oidtonum(u32 oid)
{
int i;
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index ef0c797fdf87..eaafb42eddf5 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -65,7 +65,7 @@ static int mtu;
static int bogus_rx;
static int dma_ctrl = 0x004A0263; /* Constrained by errata */
static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */
-#elif YF_NEW /* A future perfect board :->. */
+#elif defined(YF_NEW) /* A future perfect board :->. */
static int dma_ctrl = 0x00CAC277; /* Override when loading module! */
static int fifo_cfg = 0x0028;
#else
@@ -108,12 +108,6 @@ static int gx_fix;
#define yellowfin_debug debug
-#if !defined(__OPTIMIZE__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index b95fedb5b32d..a22128c2604e 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -285,7 +285,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* Chop off the NX bit (if present), and add the NX portion of
* the newprot (if present):
*/
- pte.pte_high &= -1 ^ (1 << (_PAGE_BIT_NX - 32));
+ pte.pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
pte.pte_high |= (pgprot_val(newprot) >> 32) & \
(__supported_pte_mask >> 32);
#endif
@@ -344,6 +344,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address))
+/*
+ * Helper function that returns the kernel pagetable entry controlling
+ * the virtual address 'address'. NULL means no pagetable entry present.
+ * NOTE: the return type is pte_t but if the pmd is PSE then we return it
+ * as a pte too.
+ */
+extern pte_t *lookup_address(unsigned long address);
+
+/*
+ * Make a given kernel text page executable/non-executable.
+ * Returns the previous executability setting of that page (which
+ * is used to restore the previous state). Used by the SMP bootup code.
+ * NOTE: this is an __init function for security reasons.
+ */
+#ifdef CONFIG_X86_PAE
+ extern int set_kernel_exec(unsigned long vaddr, int enable);
+#else
+ static inline int set_kernel_exec(unsigned long vaddr, int enable) { return 0;}
+#endif
+
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
diff --git a/include/asm-x86_64/bootsetup.h b/include/asm-x86_64/bootsetup.h
index 8fe68a93b798..c7e76baaaccb 100644
--- a/include/asm-x86_64/bootsetup.h
+++ b/include/asm-x86_64/bootsetup.h
@@ -26,8 +26,9 @@ extern char x86_boot_params[2048];
#define INITRD_START (*(unsigned int *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned int *) (PARAM+0x21c))
#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
-#define DISK80_SIGNATURE (*(unsigned int*) (PARAM+DISK80_SIG_BUFFER))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
+#define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
+#define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
#define COMMAND_LINE saved_command_line
diff --git a/kernel/exit.c b/kernel/exit.c
index 9cb99b471d2e..cf71b30d8bd5 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -594,7 +594,8 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
* group, and if no such member exists, give it to
* the global child reaper process (ie "init")
*/
-static inline void forget_original_parent(struct task_struct * father)
+static inline void forget_original_parent(struct task_struct * father,
+ struct list_head *to_release)
{
struct task_struct *p, *reaper = father;
struct list_head *_p, *_n;
@@ -612,16 +613,34 @@ static inline void forget_original_parent(struct task_struct * father)
* Search them and reparent children.
*/
list_for_each_safe(_p, _n, &father->children) {
+ int ptrace;
p = list_entry(_p,struct task_struct,sibling);
+
+ ptrace = p->ptrace;
+
+ /* if father isn't the real parent, then ptrace must be enabled */
+ BUG_ON(father != p->real_parent && !ptrace);
+
if (father == p->real_parent) {
+ /* reparent with a reaper, real father it's us */
choose_new_parent(p, reaper, child_reaper);
reparent_thread(p, father, 0);
} else {
- ptrace_unlink (p);
+ /* reparent ptraced task to its real parent */
+ __ptrace_unlink (p);
if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
thread_group_empty(p))
do_notify_parent(p, p->exit_signal);
}
+
+ /*
+ * if the ptraced child is a zombie with exit_signal == -1
+ * we must collect it before we exit, or it will remain
+ * zombie forever since we prevented it from self-reap itself
+ * while it was being traced by us, to be able to see it in wait4.
+ */
+ if (unlikely(ptrace && p->state == TASK_ZOMBIE && p->exit_signal == -1))
+ list_add(&p->ptrace_list, to_release);
}
list_for_each_safe(_p, _n, &father->ptrace_children) {
p = list_entry(_p,struct task_struct,ptrace_list);
@@ -638,6 +657,7 @@ static void exit_notify(struct task_struct *tsk)
{
int state;
struct task_struct *t;
+ struct list_head ptrace_dead, *_p, *_n;
if (signal_pending(tsk) && !tsk->signal->group_exit
&& !thread_group_empty(tsk)) {
@@ -673,8 +693,10 @@ static void exit_notify(struct task_struct *tsk)
* jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
- forget_original_parent(tsk);
+ INIT_LIST_HEAD(&ptrace_dead);
+ forget_original_parent(tsk, &ptrace_dead);
BUG_ON(!list_empty(&tsk->children));
+ BUG_ON(!list_empty(&tsk->ptrace_children));
/*
* Check to see if any process groups have become orphaned
@@ -759,6 +781,12 @@ static void exit_notify(struct task_struct *tsk)
_raw_write_unlock(&tasklist_lock);
local_irq_enable();
+ list_for_each_safe(_p, _n, &ptrace_dead) {
+ list_del_init(_p);
+ t = list_entry(_p,struct task_struct,ptrace_list);
+ release_task(t);
+ }
+
/* If the process is dead, release it - nobody will wait for it */
if (state == TASK_DEAD)
release_task(tsk);
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 19833d69dab8..4c3fb3e13787 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -818,7 +818,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
struct bootp_pkt *b;
struct iphdr *h;
struct ic_device *d;
- int len;
+ int len, ext_len;
/* Perform verifications before taking the lock. */
if (skb->pkt_type == PACKET_OTHERHOST)
@@ -859,7 +859,11 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
goto drop;
len = ntohs(b->udph.len) - sizeof(struct udphdr);
- if (len < 300)
+ ext_len = len - (sizeof(*b) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr) -
+ sizeof(b->exten));
+ if (ext_len < 0)
goto drop;
/* Ok the front looks good, make sure we can get at the rest. */
@@ -894,7 +898,8 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
}
/* Parse extensions */
- if (!memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
+ if (ext_len >= 4 &&
+ !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
u8 *ext;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a612865a5635..f24f17b8e03e 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1458,7 +1458,7 @@ tcp_find_option(u_int8_t option,
int *hotdrop)
{
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- char opt[60 - sizeof(struct tcphdr)];
+ u_int8_t opt[60 - sizeof(struct tcphdr)];
unsigned int i;
duprintf("tcp_match: finding option\n");
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 56f86c5ddb93..fd6cc97a446e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -259,7 +259,7 @@ tcp_grow_window(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
/* Check #1 */
if (tp->rcv_ssthresh < tp->window_clamp &&
(int)tp->rcv_ssthresh < tcp_space(sk) &&
- !tcp_prot.memory_pressure) {
+ !tcp_memory_pressure) {
int incr;
/* Check #2. Increase window, if skb with such overhead
@@ -349,7 +349,7 @@ static void tcp_clamp_window(struct sock *sk, struct tcp_opt *tp)
if (ofo_win) {
if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] &&
!(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
- !tcp_prot.memory_pressure &&
+ !tcp_memory_pressure &&
atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc),
sysctl_tcp_rmem[2]);
@@ -3764,7 +3764,7 @@ static int tcp_prune_queue(struct sock *sk)
if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
tcp_clamp_window(sk, tp);
- else if (tcp_prot.memory_pressure)
+ else if (tcp_memory_pressure)
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
tcp_collapse_ofo_queue(sk);
@@ -3844,7 +3844,7 @@ static void tcp_new_space(struct sock *sk)
if (tp->packets_out < tp->snd_cwnd &&
!(sk->sk_userlocks & SOCK_SNDBUF_LOCK) &&
- !tcp_prot.memory_pressure &&
+ !tcp_memory_pressure &&
atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
int sndmem = max_t(u32, tp->mss_clamp, tp->mss_cache) +
MAX_TCP_HEADER + 16 + sizeof(struct sk_buff),
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b6203742f97f..1fbe1edbba7b 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -672,7 +672,7 @@ u32 __tcp_select_window(struct sock *sk)
if (free_space < full_space/2) {
tp->ack.quick = 0;
- if (tcp_prot.memory_pressure)
+ if (tcp_memory_pressure)
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
if (free_space < mss)
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 840f621886c8..1b8fe67e65f4 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -257,7 +257,7 @@ static void tcp_delack_timer(unsigned long data)
TCP_CHECK_TIMER(sk);
out:
- if (tcp_prot.memory_pressure)
+ if (tcp_memory_pressure)
sk_stream_mem_reclaim(sk);
out_unlock:
bh_unlock_sock(sk);
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 74bdb4a228b2..b2c3544bf77b 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -84,9 +84,11 @@ MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
module_param_array(enable, bool, boot_devs, 0444);
MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
+#ifdef CONFIG_PNP
module_param_array(isapnp, bool, boot_devs, 0444);
MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
+#endif
module_param_array(port, long, boot_devs, 0444);
MODULE_PARM_DESC(port, "Port # for InterWave driver.");
MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list");