diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2004-07-02 13:20:46 +0100 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2004-07-02 13:20:46 +0100 |
| commit | 62054d49783cfe93c9cee9d90a0779f1f9054968 (patch) | |
| tree | 63234ac22723c76b84e629390fb230d499f41151 | |
| parent | 639b1a19248ed0aeb364f64fecbd24042a559bac (diff) | |
| parent | a2d708b887c8d932734f3c4ec600269f1252a3d1 (diff) | |
Merge cantab.net:/home/src/ntfs-2.6-devel
into cantab.net:/home/src/ntfs-2.6
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"); |
