diff options
160 files changed, 2423 insertions, 1695 deletions
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index 5bcbb6ee3bc0..f869b03929db 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl | |||
@@ -705,7 +705,7 @@ and other resources, etc. | |||
705 | 705 | ||
706 | <sect1><title>ata_scsi_error()</title> | 706 | <sect1><title>ata_scsi_error()</title> |
707 | <para> | 707 | <para> |
708 | ata_scsi_error() is the current hostt->eh_strategy_handler() | 708 | ata_scsi_error() is the current transportt->eh_strategy_handler() |
709 | for libata. As discussed above, this will be entered in two | 709 | for libata. As discussed above, this will be entered in two |
710 | cases - timeout and ATAPI error completion. This function | 710 | cases - timeout and ATAPI error completion. This function |
711 | calls low level libata driver's eng_timeout() callback, the | 711 | calls low level libata driver's eng_timeout() callback, the |
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index 331afd791cbb..ce767b90bb0d 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt | |||
@@ -19,9 +19,9 @@ TABLE OF CONTENTS | |||
19 | [2-1-1] Overview | 19 | [2-1-1] Overview |
20 | [2-1-2] Flow of scmds through EH | 20 | [2-1-2] Flow of scmds through EH |
21 | [2-1-3] Flow of control | 21 | [2-1-3] Flow of control |
22 | [2-2] EH through hostt->eh_strategy_handler() | 22 | [2-2] EH through transportt->eh_strategy_handler() |
23 | [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions | 23 | [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions |
24 | [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions | 24 | [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions |
25 | [2-2-3] Things to consider | 25 | [2-2-3] Things to consider |
26 | 26 | ||
27 | 27 | ||
@@ -413,9 +413,9 @@ scmd->allowed. | |||
413 | layer of failure of the scmds. | 413 | layer of failure of the scmds. |
414 | 414 | ||
415 | 415 | ||
416 | [2-2] EH through hostt->eh_strategy_handler() | 416 | [2-2] EH through transportt->eh_strategy_handler() |
417 | 417 | ||
418 | hostt->eh_strategy_handler() is invoked in the place of | 418 | transportt->eh_strategy_handler() is invoked in the place of |
419 | scsi_unjam_host() and it is responsible for whole recovery process. | 419 | scsi_unjam_host() and it is responsible for whole recovery process. |
420 | On completion, the handler should have made lower layers forget about | 420 | On completion, the handler should have made lower layers forget about |
421 | all failed scmds and either ready for new commands or offline. Also, | 421 | all failed scmds and either ready for new commands or offline. Also, |
@@ -424,7 +424,7 @@ SCSI midlayer. IOW, of the steps described in [2-1-2], all steps | |||
424 | except for #1 must be implemented by eh_strategy_handler(). | 424 | except for #1 must be implemented by eh_strategy_handler(). |
425 | 425 | ||
426 | 426 | ||
427 | [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions | 427 | [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions |
428 | 428 | ||
429 | The following conditions are true on entry to the handler. | 429 | The following conditions are true on entry to the handler. |
430 | 430 | ||
@@ -437,7 +437,7 @@ except for #1 must be implemented by eh_strategy_handler(). | |||
437 | - shost->host_failed == shost->host_busy | 437 | - shost->host_failed == shost->host_busy |
438 | 438 | ||
439 | 439 | ||
440 | [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions | 440 | [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions |
441 | 441 | ||
442 | The following conditions must be true on exit from the handler. | 442 | The following conditions must be true on exit from the handler. |
443 | 443 | ||
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 8bbae3e1abdf..75a535a975c3 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt | |||
@@ -804,7 +804,6 @@ Summary: | |||
804 | eh_bus_reset_handler - issue SCSI bus reset | 804 | eh_bus_reset_handler - issue SCSI bus reset |
805 | eh_device_reset_handler - issue SCSI device reset | 805 | eh_device_reset_handler - issue SCSI device reset |
806 | eh_host_reset_handler - reset host (host bus adapter) | 806 | eh_host_reset_handler - reset host (host bus adapter) |
807 | eh_strategy_handler - driver supplied alternate to scsi_unjam_host() | ||
808 | info - supply information about given host | 807 | info - supply information about given host |
809 | ioctl - driver can respond to ioctls | 808 | ioctl - driver can respond to ioctls |
810 | proc_info - supports /proc/scsi/{driver_name}/{host_no} | 809 | proc_info - supports /proc/scsi/{driver_name}/{host_no} |
@@ -970,24 +969,6 @@ Details: | |||
970 | 969 | ||
971 | 970 | ||
972 | /** | 971 | /** |
973 | * eh_strategy_handler - driver supplied alternate to scsi_unjam_host() | ||
974 | * @shp: host on which error has occurred | ||
975 | * | ||
976 | * Returns TRUE if host unjammed, else FALSE. | ||
977 | * | ||
978 | * Locks: none | ||
979 | * | ||
980 | * Calling context: kernel thread | ||
981 | * | ||
982 | * Notes: Invoked from scsi_eh thread. LLD supplied alternate to | ||
983 | * scsi_unjam_host() found in scsi_error.c | ||
984 | * | ||
985 | * Optionally defined in: LLD | ||
986 | **/ | ||
987 | int eh_strategy_handler(struct Scsi_Host * shp) | ||
988 | |||
989 | |||
990 | /** | ||
991 | * info - supply information about given host: driver name plus data | 972 | * info - supply information about given host: driver name plus data |
992 | * to distinguish given host | 973 | * to distinguish given host |
993 | * @shp: host to supply information about | 974 | * @shp: host to supply information about |
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 1921353259ae..f2cd6ef53ff3 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt | |||
@@ -151,6 +151,11 @@ NUMA | |||
151 | 151 | ||
152 | numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine. | 152 | numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine. |
153 | 153 | ||
154 | numa=hotadd=percent | ||
155 | Only allow hotadd memory to preallocate page structures upto | ||
156 | percent of already available memory. | ||
157 | numa=hotadd=0 will disable hotadd memory. | ||
158 | |||
154 | ACPI | 159 | ACPI |
155 | 160 | ||
156 | acpi=off Don't enable ACPI | 161 | acpi=off Don't enable ACPI |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 033066176b3e..8dab3527bc97 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -215,7 +215,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size) | |||
215 | { | 215 | { |
216 | struct acpi_table_madt *madt = NULL; | 216 | struct acpi_table_madt *madt = NULL; |
217 | 217 | ||
218 | if (!phys_addr || !size) | 218 | if (!phys_addr || !size || !cpu_has_apic) |
219 | return -EINVAL; | 219 | return -EINVAL; |
220 | 220 | ||
221 | madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size); | 221 | madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size); |
@@ -751,6 +751,9 @@ static int __init acpi_parse_madt_ioapic_entries(void) | |||
751 | return -ENODEV; | 751 | return -ENODEV; |
752 | } | 752 | } |
753 | 753 | ||
754 | if (!cpu_has_apic) | ||
755 | return -ENODEV; | ||
756 | |||
754 | /* | 757 | /* |
755 | * if "noapic" boot option, don't look for IO-APICs | 758 | * if "noapic" boot option, don't look for IO-APICs |
756 | */ | 759 | */ |
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 6273bf74c203..254cee9f0b7b 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -62,6 +62,18 @@ int apic_verbosity; | |||
62 | 62 | ||
63 | static void apic_pm_activate(void); | 63 | static void apic_pm_activate(void); |
64 | 64 | ||
65 | int modern_apic(void) | ||
66 | { | ||
67 | unsigned int lvr, version; | ||
68 | /* AMD systems use old APIC versions, so check the CPU */ | ||
69 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && | ||
70 | boot_cpu_data.x86 >= 0xf) | ||
71 | return 1; | ||
72 | lvr = apic_read(APIC_LVR); | ||
73 | version = GET_APIC_VERSION(lvr); | ||
74 | return version >= 0x14; | ||
75 | } | ||
76 | |||
65 | /* | 77 | /* |
66 | * 'what should we do if we get a hw irq event on an illegal vector'. | 78 | * 'what should we do if we get a hw irq event on an illegal vector'. |
67 | * each architecture has to answer this themselves. | 79 | * each architecture has to answer this themselves. |
@@ -119,10 +131,7 @@ void enable_NMI_through_LVT0 (void * dummy) | |||
119 | 131 | ||
120 | int get_physical_broadcast(void) | 132 | int get_physical_broadcast(void) |
121 | { | 133 | { |
122 | unsigned int lvr, version; | 134 | if (modern_apic()) |
123 | lvr = apic_read(APIC_LVR); | ||
124 | version = GET_APIC_VERSION(lvr); | ||
125 | if (!APIC_INTEGRATED(version) || version >= 0x14) | ||
126 | return 0xff; | 135 | return 0xff; |
127 | else | 136 | else |
128 | return 0xf; | 137 | return 0xf; |
@@ -349,9 +358,9 @@ int __init verify_local_APIC(void) | |||
349 | 358 | ||
350 | void __init sync_Arb_IDs(void) | 359 | void __init sync_Arb_IDs(void) |
351 | { | 360 | { |
352 | /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ | 361 | /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 |
353 | unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); | 362 | And not needed on AMD */ |
354 | if (ver >= 0x14) /* P4 or higher */ | 363 | if (modern_apic()) |
355 | return; | 364 | return; |
356 | /* | 365 | /* |
357 | * Wait for idle. | 366 | * Wait for idle. |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 712a26bd4457..7c0e160a2145 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | #define PFX "powernow-k8: " | 47 | #define PFX "powernow-k8: " |
48 | #define BFX PFX "BIOS error: " | 48 | #define BFX PFX "BIOS error: " |
49 | #define VERSION "version 1.60.1" | 49 | #define VERSION "version 1.60.2" |
50 | #include "powernow-k8.h" | 50 | #include "powernow-k8.h" |
51 | 51 | ||
52 | /* serialize freq changes */ | 52 | /* serialize freq changes */ |
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(fidvid_mutex); | |||
55 | static struct powernow_k8_data *powernow_data[NR_CPUS]; | 55 | static struct powernow_k8_data *powernow_data[NR_CPUS]; |
56 | 56 | ||
57 | #ifndef CONFIG_SMP | 57 | #ifndef CONFIG_SMP |
58 | static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL }; | 58 | static cpumask_t cpu_core_map[1]; |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | /* Return a frequency in MHz, given an input fid */ | 61 | /* Return a frequency in MHz, given an input fid */ |
@@ -910,6 +910,9 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi | |||
910 | unsigned int newstate; | 910 | unsigned int newstate; |
911 | int ret = -EIO; | 911 | int ret = -EIO; |
912 | 912 | ||
913 | if (!data) | ||
914 | return -EINVAL; | ||
915 | |||
913 | /* only run on specific CPU from here on */ | 916 | /* only run on specific CPU from here on */ |
914 | oldmask = current->cpus_allowed; | 917 | oldmask = current->cpus_allowed; |
915 | set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); | 918 | set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); |
@@ -969,6 +972,9 @@ static int powernowk8_verify(struct cpufreq_policy *pol) | |||
969 | { | 972 | { |
970 | struct powernow_k8_data *data = powernow_data[pol->cpu]; | 973 | struct powernow_k8_data *data = powernow_data[pol->cpu]; |
971 | 974 | ||
975 | if (!data) | ||
976 | return -EINVAL; | ||
977 | |||
972 | return cpufreq_frequency_table_verify(pol, data->powernow_table); | 978 | return cpufreq_frequency_table_verify(pol, data->powernow_table); |
973 | } | 979 | } |
974 | 980 | ||
@@ -977,7 +983,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
977 | { | 983 | { |
978 | struct powernow_k8_data *data; | 984 | struct powernow_k8_data *data; |
979 | cpumask_t oldmask = CPU_MASK_ALL; | 985 | cpumask_t oldmask = CPU_MASK_ALL; |
980 | int rc, i; | 986 | int rc; |
981 | 987 | ||
982 | if (!cpu_online(pol->cpu)) | 988 | if (!cpu_online(pol->cpu)) |
983 | return -ENODEV; | 989 | return -ENODEV; |
@@ -1063,8 +1069,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1063 | printk("cpu_init done, current fid 0x%x, vid 0x%x\n", | 1069 | printk("cpu_init done, current fid 0x%x, vid 0x%x\n", |
1064 | data->currfid, data->currvid); | 1070 | data->currfid, data->currvid); |
1065 | 1071 | ||
1066 | for_each_cpu_mask(i, cpu_core_map[pol->cpu]) | 1072 | powernow_data[pol->cpu] = data; |
1067 | powernow_data[i] = data; | ||
1068 | 1073 | ||
1069 | return 0; | 1074 | return 0; |
1070 | 1075 | ||
@@ -1104,6 +1109,9 @@ static unsigned int powernowk8_get (unsigned int cpu) | |||
1104 | if (!data) | 1109 | if (!data) |
1105 | return -EINVAL; | 1110 | return -EINVAL; |
1106 | 1111 | ||
1112 | if (!data) | ||
1113 | return -EINVAL; | ||
1114 | |||
1107 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 1115 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
1108 | if (smp_processor_id() != cpu) { | 1116 | if (smp_processor_id() != cpu) { |
1109 | printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu); | 1117 | printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu); |
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 8d8aa9d1796d..db120174aa7e 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c | |||
@@ -110,21 +110,6 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
110 | static int mpc_record; | 110 | static int mpc_record; |
111 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; | 111 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; |
112 | 112 | ||
113 | #ifdef CONFIG_X86_NUMAQ | ||
114 | static int MP_valid_apicid(int apicid, int version) | ||
115 | { | ||
116 | return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf; | ||
117 | } | ||
118 | #else | ||
119 | static int MP_valid_apicid(int apicid, int version) | ||
120 | { | ||
121 | if (version >= 0x14) | ||
122 | return apicid < 0xff; | ||
123 | else | ||
124 | return apicid < 0xf; | ||
125 | } | ||
126 | #endif | ||
127 | |||
128 | static void __devinit MP_processor_info (struct mpc_config_processor *m) | 113 | static void __devinit MP_processor_info (struct mpc_config_processor *m) |
129 | { | 114 | { |
130 | int ver, apicid; | 115 | int ver, apicid; |
@@ -190,12 +175,6 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) | |||
190 | 175 | ||
191 | ver = m->mpc_apicver; | 176 | ver = m->mpc_apicver; |
192 | 177 | ||
193 | if (!MP_valid_apicid(apicid, ver)) { | ||
194 | printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", | ||
195 | m->mpc_apicid, MAX_APICS); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | /* | 178 | /* |
200 | * Validate version | 179 | * Validate version |
201 | */ | 180 | */ |
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c index 10e21a4773dd..99aab41a05b0 100644 --- a/arch/i386/kernel/reboot_fixups.c +++ b/arch/i386/kernel/reboot_fixups.c | |||
@@ -51,7 +51,5 @@ void mach_reboot_fixups(void) | |||
51 | 51 | ||
52 | cur->reboot_fixup(dev); | 52 | cur->reboot_fixup(dev); |
53 | } | 53 | } |
54 | |||
55 | printk(KERN_WARNING "No reboot fixup found for your hardware\n"); | ||
56 | } | 54 | } |
57 | 55 | ||
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index eacc3f0a2ea4..80cb3b2d0997 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -963,6 +963,36 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) | |||
963 | return 0; | 963 | return 0; |
964 | } | 964 | } |
965 | 965 | ||
966 | /* | ||
967 | * This function checks if the entire range <start,end> is mapped with type. | ||
968 | * | ||
969 | * Note: this function only works correct if the e820 table is sorted and | ||
970 | * not-overlapping, which is the case | ||
971 | */ | ||
972 | int __init | ||
973 | e820_all_mapped(unsigned long start, unsigned long end, unsigned type) | ||
974 | { | ||
975 | int i; | ||
976 | for (i = 0; i < e820.nr_map; i++) { | ||
977 | struct e820entry *ei = &e820.map[i]; | ||
978 | if (type && ei->type != type) | ||
979 | continue; | ||
980 | /* is the region (part) in overlap with the current region ?*/ | ||
981 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
982 | continue; | ||
983 | /* if the region is at the beginning of <start,end> we move | ||
984 | * start to the end of the region since it's ok until there | ||
985 | */ | ||
986 | if (ei->addr <= start) | ||
987 | start = ei->addr + ei->size; | ||
988 | /* if start is now at or beyond end, we're done, full | ||
989 | * coverage */ | ||
990 | if (start >= end) | ||
991 | return 1; /* we're done */ | ||
992 | } | ||
993 | return 0; | ||
994 | } | ||
995 | |||
966 | /* | 996 | /* |
967 | * Find the highest page frame number we have available | 997 | * Find the highest page frame number we have available |
968 | */ | 998 | */ |
@@ -1317,8 +1347,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat | |||
1317 | /* | 1347 | /* |
1318 | * Request address space for all standard resources | 1348 | * Request address space for all standard resources |
1319 | * | 1349 | * |
1320 | * This is called just before pcibios_assign_resources(), which is also | 1350 | * This is called just before pcibios_init(), which is also a |
1321 | * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c). | 1351 | * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). |
1322 | */ | 1352 | */ |
1323 | static int __init request_standard_resources(void) | 1353 | static int __init request_standard_resources(void) |
1324 | { | 1354 | { |
@@ -1339,7 +1369,7 @@ static int __init request_standard_resources(void) | |||
1339 | return 0; | 1369 | return 0; |
1340 | } | 1370 | } |
1341 | 1371 | ||
1342 | fs_initcall(request_standard_resources); | 1372 | subsys_initcall(request_standard_resources); |
1343 | 1373 | ||
1344 | static void __init register_memory(void) | 1374 | static void __init register_memory(void) |
1345 | { | 1375 | { |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 9f66ac582a8b..ae6534ad8161 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -651,6 +651,7 @@ void __init mem_init(void) | |||
651 | * Specifically, in the case of x86, we will always add | 651 | * Specifically, in the case of x86, we will always add |
652 | * memory to the highmem for now. | 652 | * memory to the highmem for now. |
653 | */ | 653 | */ |
654 | #ifdef CONFIG_HOTPLUG_MEMORY | ||
654 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 655 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
655 | int add_memory(u64 start, u64 size) | 656 | int add_memory(u64 start, u64 size) |
656 | { | 657 | { |
@@ -667,6 +668,7 @@ int remove_memory(u64 start, u64 size) | |||
667 | return -EINVAL; | 668 | return -EINVAL; |
668 | } | 669 | } |
669 | #endif | 670 | #endif |
671 | #endif | ||
670 | 672 | ||
671 | kmem_cache_t *pgd_cache; | 673 | kmem_cache_t *pgd_cache; |
672 | kmem_cache_t *pmd_cache; | 674 | kmem_cache_t *pmd_cache; |
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c index 99012b93bd12..0659ced01185 100644 --- a/arch/i386/pci/direct.c +++ b/arch/i386/pci/direct.c | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | #include <linux/dmi.h> | ||
7 | #include "pci.h" | 8 | #include "pci.h" |
8 | 9 | ||
9 | /* | 10 | /* |
@@ -18,8 +19,10 @@ int pci_conf1_read(unsigned int seg, unsigned int bus, | |||
18 | { | 19 | { |
19 | unsigned long flags; | 20 | unsigned long flags; |
20 | 21 | ||
21 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) | 22 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) { |
23 | *value = -1; | ||
22 | return -EINVAL; | 24 | return -EINVAL; |
25 | } | ||
23 | 26 | ||
24 | spin_lock_irqsave(&pci_config_lock, flags); | 27 | spin_lock_irqsave(&pci_config_lock, flags); |
25 | 28 | ||
@@ -188,6 +191,10 @@ static int __init pci_sanity_check(struct pci_raw_ops *o) | |||
188 | 191 | ||
189 | if (pci_probe & PCI_NO_CHECKS) | 192 | if (pci_probe & PCI_NO_CHECKS) |
190 | return 1; | 193 | return 1; |
194 | /* Assume Type 1 works for newer systems. | ||
195 | This handles machines that don't have anything on PCI Bus 0. */ | ||
196 | if (dmi_get_year(DMI_BIOS_DATE) >= 2001) | ||
197 | return 1; | ||
191 | 198 | ||
192 | for (devfn = 0; devfn < 0x100; devfn++) { | 199 | for (devfn = 0; devfn < 0x100; devfn++) { |
193 | if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x)) | 200 | if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x)) |
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 613789071f30..f77d7f8b9bf6 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -12,14 +12,20 @@ | |||
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <asm/e820.h> | ||
15 | #include "pci.h" | 16 | #include "pci.h" |
16 | 17 | ||
18 | #define MMCONFIG_APER_SIZE (256*1024*1024) | ||
19 | |||
20 | /* Assume systems with more busses have correct MCFG */ | ||
21 | #define MAX_CHECK_BUS 16 | ||
22 | |||
17 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 23 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
18 | 24 | ||
19 | /* The base address of the last MMCONFIG device accessed */ | 25 | /* The base address of the last MMCONFIG device accessed */ |
20 | static u32 mmcfg_last_accessed_device; | 26 | static u32 mmcfg_last_accessed_device; |
21 | 27 | ||
22 | static DECLARE_BITMAP(fallback_slots, 32); | 28 | static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32); |
23 | 29 | ||
24 | /* | 30 | /* |
25 | * Functions for accessing PCI configuration space with MMCONFIG accesses | 31 | * Functions for accessing PCI configuration space with MMCONFIG accesses |
@@ -29,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) | |||
29 | int cfg_num = -1; | 35 | int cfg_num = -1; |
30 | struct acpi_table_mcfg_config *cfg; | 36 | struct acpi_table_mcfg_config *cfg; |
31 | 37 | ||
32 | if (seg == 0 && bus == 0 && | 38 | if (seg == 0 && bus < MAX_CHECK_BUS && |
33 | test_bit(PCI_SLOT(devfn), fallback_slots)) | 39 | test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots)) |
34 | return 0; | 40 | return 0; |
35 | 41 | ||
36 | while (1) { | 42 | while (1) { |
@@ -74,8 +80,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
74 | unsigned long flags; | 80 | unsigned long flags; |
75 | u32 base; | 81 | u32 base; |
76 | 82 | ||
77 | if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) | 83 | if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) { |
84 | *value = -1; | ||
78 | return -EINVAL; | 85 | return -EINVAL; |
86 | } | ||
79 | 87 | ||
80 | base = get_base_addr(seg, bus, devfn); | 88 | base = get_base_addr(seg, bus, devfn); |
81 | if (!base) | 89 | if (!base) |
@@ -146,29 +154,34 @@ static struct pci_raw_ops pci_mmcfg = { | |||
146 | Normally this can be expressed in the MCFG by not listing them | 154 | Normally this can be expressed in the MCFG by not listing them |
147 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | 155 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. |
148 | Instead try to discover all devices on bus 0 that are unreachable using MM | 156 | Instead try to discover all devices on bus 0 that are unreachable using MM |
149 | and fallback for them. | 157 | and fallback for them. */ |
150 | We only do this for bus 0/seg 0 */ | ||
151 | static __init void unreachable_devices(void) | 158 | static __init void unreachable_devices(void) |
152 | { | 159 | { |
153 | int i; | 160 | int i, k; |
154 | unsigned long flags; | 161 | unsigned long flags; |
155 | 162 | ||
156 | for (i = 0; i < 32; i++) { | 163 | for (k = 0; k < MAX_CHECK_BUS; k++) { |
157 | u32 val1; | 164 | for (i = 0; i < 32; i++) { |
158 | u32 addr; | 165 | u32 val1; |
159 | 166 | u32 addr; | |
160 | pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1); | 167 | |
161 | if (val1 == 0xffffffff) | 168 | pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1); |
162 | continue; | 169 | if (val1 == 0xffffffff) |
163 | 170 | continue; | |
164 | /* Locking probably not needed, but safer */ | 171 | |
165 | spin_lock_irqsave(&pci_config_lock, flags); | 172 | /* Locking probably not needed, but safer */ |
166 | addr = get_base_addr(0, 0, PCI_DEVFN(i, 0)); | 173 | spin_lock_irqsave(&pci_config_lock, flags); |
167 | if (addr != 0) | 174 | addr = get_base_addr(0, k, PCI_DEVFN(i, 0)); |
168 | pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0)); | 175 | if (addr != 0) |
169 | if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1) | 176 | pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); |
170 | set_bit(i, fallback_slots); | 177 | if (addr == 0 || |
171 | spin_unlock_irqrestore(&pci_config_lock, flags); | 178 | readl((u32 __iomem *)mmcfg_virt_addr) != val1) { |
179 | set_bit(i, fallback_slots); | ||
180 | printk(KERN_NOTICE | ||
181 | "PCI: No mmconfig possible on %x:%x\n", k, i); | ||
182 | } | ||
183 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
184 | } | ||
172 | } | 185 | } |
173 | } | 186 | } |
174 | 187 | ||
@@ -183,6 +196,14 @@ void __init pci_mmcfg_init(void) | |||
183 | (pci_mmcfg_config[0].base_address == 0)) | 196 | (pci_mmcfg_config[0].base_address == 0)) |
184 | return; | 197 | return; |
185 | 198 | ||
199 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
200 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | ||
201 | E820_RESERVED)) { | ||
202 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | ||
203 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
204 | return; | ||
205 | } | ||
206 | |||
186 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | 207 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); |
187 | raw_pci_ops = &pci_mmcfg; | 208 | raw_pci_ops = &pci_mmcfg; |
188 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 209 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index d1e2fc566486..648047a0bce3 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -194,6 +194,9 @@ endchoice | |||
194 | 194 | ||
195 | endmenu | 195 | endmenu |
196 | 196 | ||
197 | config ARCH_SELECT_MEMORY_MODEL | ||
198 | def_bool y | ||
199 | |||
197 | config ARCH_SPARSEMEM_ENABLE | 200 | config ARCH_SPARSEMEM_ENABLE |
198 | def_bool y | 201 | def_bool y |
199 | 202 | ||
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 30389085a359..1317380fa937 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.16 | 3 | # Linux kernel version: 2.6.16 |
4 | # Fri Mar 31 01:40:57 2006 | 4 | # Sun Apr 2 19:31:04 2006 |
5 | # | 5 | # |
6 | CONFIG_SPARC=y | 6 | CONFIG_SPARC=y |
7 | CONFIG_SPARC64=y | 7 | CONFIG_SPARC64=y |
@@ -838,7 +838,6 @@ CONFIG_FB_TILEBLITTING=y | |||
838 | # CONFIG_FB_NVIDIA is not set | 838 | # CONFIG_FB_NVIDIA is not set |
839 | # CONFIG_FB_RIVA is not set | 839 | # CONFIG_FB_RIVA is not set |
840 | # CONFIG_FB_MATROX is not set | 840 | # CONFIG_FB_MATROX is not set |
841 | # CONFIG_FB_RADEON_OLD is not set | ||
842 | CONFIG_FB_RADEON=y | 841 | CONFIG_FB_RADEON=y |
843 | CONFIG_FB_RADEON_I2C=y | 842 | CONFIG_FB_RADEON_I2C=y |
844 | # CONFIG_FB_RADEON_DEBUG is not set | 843 | # CONFIG_FB_RADEON_DEBUG is not set |
@@ -924,6 +923,7 @@ CONFIG_SND_MTPAV=m | |||
924 | # PCI devices | 923 | # PCI devices |
925 | # | 924 | # |
926 | # CONFIG_SND_AD1889 is not set | 925 | # CONFIG_SND_AD1889 is not set |
926 | # CONFIG_SND_ALS300 is not set | ||
927 | CONFIG_SND_ALI5451=m | 927 | CONFIG_SND_ALI5451=m |
928 | # CONFIG_SND_ATIIXP is not set | 928 | # CONFIG_SND_ATIIXP is not set |
929 | # CONFIG_SND_ATIIXP_MODEM is not set | 929 | # CONFIG_SND_ATIIXP_MODEM is not set |
@@ -955,6 +955,7 @@ CONFIG_SND_ALI5451=m | |||
955 | # CONFIG_SND_MIXART is not set | 955 | # CONFIG_SND_MIXART is not set |
956 | # CONFIG_SND_NM256 is not set | 956 | # CONFIG_SND_NM256 is not set |
957 | # CONFIG_SND_PCXHR is not set | 957 | # CONFIG_SND_PCXHR is not set |
958 | # CONFIG_SND_RIPTIDE is not set | ||
958 | # CONFIG_SND_RME32 is not set | 959 | # CONFIG_SND_RME32 is not set |
959 | # CONFIG_SND_RME96 is not set | 960 | # CONFIG_SND_RME96 is not set |
960 | # CONFIG_SND_RME9652 is not set | 961 | # CONFIG_SND_RME9652 is not set |
@@ -1109,6 +1110,11 @@ CONFIG_USB_HIDDEV=y | |||
1109 | # CONFIG_MMC is not set | 1110 | # CONFIG_MMC is not set |
1110 | 1111 | ||
1111 | # | 1112 | # |
1113 | # LED devices | ||
1114 | # | ||
1115 | # CONFIG_NEW_LEDS is not set | ||
1116 | |||
1117 | # | ||
1112 | # InfiniBand support | 1118 | # InfiniBand support |
1113 | # | 1119 | # |
1114 | # CONFIG_INFINIBAND is not set | 1120 | # CONFIG_INFINIBAND is not set |
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index eb93e9c52846..49e6dedd027d 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
@@ -244,6 +244,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs) | |||
244 | } | 244 | } |
245 | 245 | ||
246 | switch(request) { | 246 | switch(request) { |
247 | case PTRACE_PEEKUSR: | ||
248 | if (addr != 0) | ||
249 | pt_error_return(regs, EIO); | ||
250 | else | ||
251 | pt_succ_return(regs, 0); | ||
252 | goto out_tsk; | ||
253 | |||
247 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 254 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
248 | case PTRACE_PEEKDATA: { | 255 | case PTRACE_PEEKDATA: { |
249 | unsigned long tmp64; | 256 | unsigned long tmp64; |
@@ -602,6 +609,22 @@ asmlinkage void do_ptrace(struct pt_regs *regs) | |||
602 | 609 | ||
603 | /* PTRACE_DUMPCORE unsupported... */ | 610 | /* PTRACE_DUMPCORE unsupported... */ |
604 | 611 | ||
612 | case PTRACE_GETEVENTMSG: { | ||
613 | int err; | ||
614 | |||
615 | if (test_thread_flag(TIF_32BIT)) | ||
616 | err = put_user(child->ptrace_message, | ||
617 | (unsigned int __user *) data); | ||
618 | else | ||
619 | err = put_user(child->ptrace_message, | ||
620 | (unsigned long __user *) data); | ||
621 | if (err) | ||
622 | pt_error_return(regs, -err); | ||
623 | else | ||
624 | pt_succ_return(regs, 0); | ||
625 | break; | ||
626 | } | ||
627 | |||
605 | default: { | 628 | default: { |
606 | int err = ptrace_request(child, request, addr, data); | 629 | int err = ptrace_request(child, request, addr, data); |
607 | if (err) | 630 | if (err) |
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 8175a6968c6b..eb36f7988ff7 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
@@ -745,12 +745,21 @@ struct call_data_struct { | |||
745 | int wait; | 745 | int wait; |
746 | }; | 746 | }; |
747 | 747 | ||
748 | static DEFINE_SPINLOCK(call_lock); | 748 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock); |
749 | static struct call_data_struct *call_data; | 749 | static struct call_data_struct *call_data; |
750 | 750 | ||
751 | extern unsigned long xcall_call_function; | 751 | extern unsigned long xcall_call_function; |
752 | 752 | ||
753 | /* | 753 | /** |
754 | * smp_call_function(): Run a function on all other CPUs. | ||
755 | * @func: The function to run. This must be fast and non-blocking. | ||
756 | * @info: An arbitrary pointer to pass to the function. | ||
757 | * @nonatomic: currently unused. | ||
758 | * @wait: If true, wait (atomically) until function has completed on other CPUs. | ||
759 | * | ||
760 | * Returns 0 on success, else a negative status code. Does not return until | ||
761 | * remote CPUs are nearly ready to execute <<func>> or are or have executed. | ||
762 | * | ||
754 | * You must not call this function with disabled interrupts or from a | 763 | * You must not call this function with disabled interrupts or from a |
755 | * hardware interrupt handler or from a bottom half handler. | 764 | * hardware interrupt handler or from a bottom half handler. |
756 | */ | 765 | */ |
@@ -759,7 +768,6 @@ static int smp_call_function_mask(void (*func)(void *info), void *info, | |||
759 | { | 768 | { |
760 | struct call_data_struct data; | 769 | struct call_data_struct data; |
761 | int cpus; | 770 | int cpus; |
762 | long timeout; | ||
763 | 771 | ||
764 | /* Can deadlock when called with interrupts disabled */ | 772 | /* Can deadlock when called with interrupts disabled */ |
765 | WARN_ON(irqs_disabled()); | 773 | WARN_ON(irqs_disabled()); |
@@ -777,31 +785,18 @@ static int smp_call_function_mask(void (*func)(void *info), void *info, | |||
777 | goto out_unlock; | 785 | goto out_unlock; |
778 | 786 | ||
779 | call_data = &data; | 787 | call_data = &data; |
788 | mb(); | ||
780 | 789 | ||
781 | smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask); | 790 | smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask); |
782 | 791 | ||
783 | /* | 792 | /* Wait for response */ |
784 | * Wait for other cpus to complete function or at | 793 | while (atomic_read(&data.finished) != cpus) |
785 | * least snap the call data. | 794 | cpu_relax(); |
786 | */ | ||
787 | timeout = 1000000; | ||
788 | while (atomic_read(&data.finished) != cpus) { | ||
789 | if (--timeout <= 0) | ||
790 | goto out_timeout; | ||
791 | barrier(); | ||
792 | udelay(1); | ||
793 | } | ||
794 | 795 | ||
795 | out_unlock: | 796 | out_unlock: |
796 | spin_unlock(&call_lock); | 797 | spin_unlock(&call_lock); |
797 | 798 | ||
798 | return 0; | 799 | return 0; |
799 | |||
800 | out_timeout: | ||
801 | spin_unlock(&call_lock); | ||
802 | printk("XCALL: Remote cpus not responding, ncpus=%d finished=%d\n", | ||
803 | cpus, atomic_read(&data.finished)); | ||
804 | return 0; | ||
805 | } | 800 | } |
806 | 801 | ||
807 | int smp_call_function(void (*func)(void *info), void *info, | 802 | int smp_call_function(void (*func)(void *info), void *info, |
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index ff090bb9734b..2793a5d82380 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
@@ -1130,9 +1130,9 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in | |||
1130 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), | 1130 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), |
1131 | afsr, afar, | 1131 | afsr, afar, |
1132 | (afsr & CHAFSR_TL1) ? 1 : 0); | 1132 | (afsr & CHAFSR_TL1) ? 1 : 0); |
1133 | printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", | 1133 | printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n", |
1134 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), | 1134 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), |
1135 | regs->tpc, regs->tnpc, regs->tstate); | 1135 | regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate); |
1136 | printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", | 1136 | printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", |
1137 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), | 1137 | (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), |
1138 | (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, | 1138 | (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4310b4a311a5..7df2fe1844be 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -136,6 +136,11 @@ config X86_L1_CACHE_SHIFT | |||
136 | default "7" if GENERIC_CPU || MPSC | 136 | default "7" if GENERIC_CPU || MPSC |
137 | default "6" if MK8 | 137 | default "6" if MK8 |
138 | 138 | ||
139 | config X86_INTERNODE_CACHE_BYTES | ||
140 | int | ||
141 | default "4096" if X86_VSMP | ||
142 | default X86_L1_CACHE_BYTES if !X86_VSMP | ||
143 | |||
139 | config X86_TSC | 144 | config X86_TSC |
140 | bool | 145 | bool |
141 | default y | 146 | default y |
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 585fd4a559c8..e573e2ab5510 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile | |||
@@ -24,37 +24,37 @@ | |||
24 | LDFLAGS := -m elf_x86_64 | 24 | LDFLAGS := -m elf_x86_64 |
25 | OBJCOPYFLAGS := -O binary -R .note -R .comment -S | 25 | OBJCOPYFLAGS := -O binary -R .note -R .comment -S |
26 | LDFLAGS_vmlinux := | 26 | LDFLAGS_vmlinux := |
27 | |||
28 | CHECKFLAGS += -D__x86_64__ -m64 | 27 | CHECKFLAGS += -D__x86_64__ -m64 |
29 | 28 | ||
29 | cflags-y := | ||
30 | cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) | 30 | cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) |
31 | cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) | 31 | cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) |
32 | cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) | 32 | cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) |
33 | CFLAGS += $(cflags-y) | ||
34 | 33 | ||
35 | CFLAGS += -m64 | 34 | cflags-y += -m64 |
36 | CFLAGS += -mno-red-zone | 35 | cflags-y += -mno-red-zone |
37 | CFLAGS += -mcmodel=kernel | 36 | cflags-y += -mcmodel=kernel |
38 | CFLAGS += -pipe | 37 | cflags-y += -pipe |
39 | cflags-$(CONFIG_REORDER) += -ffunction-sections | 38 | cflags-$(CONFIG_REORDER) += -ffunction-sections |
40 | # this makes reading assembly source easier, but produces worse code | 39 | # this makes reading assembly source easier, but produces worse code |
41 | # actually it makes the kernel smaller too. | 40 | # actually it makes the kernel smaller too. |
42 | CFLAGS += -fno-reorder-blocks | 41 | cflags-y += -fno-reorder-blocks |
43 | CFLAGS += -Wno-sign-compare | 42 | cflags-y += -Wno-sign-compare |
44 | ifneq ($(CONFIG_UNWIND_INFO),y) | 43 | ifneq ($(CONFIG_UNWIND_INFO),y) |
45 | CFLAGS += -fno-asynchronous-unwind-tables | 44 | cflags-y += -fno-asynchronous-unwind-tables |
46 | endif | 45 | endif |
47 | ifneq ($(CONFIG_DEBUG_INFO),y) | 46 | ifneq ($(CONFIG_DEBUG_INFO),y) |
48 | # -fweb shrinks the kernel a bit, but the difference is very small | 47 | # -fweb shrinks the kernel a bit, but the difference is very small |
49 | # it also messes up debugging, so don't use it for now. | 48 | # it also messes up debugging, so don't use it for now. |
50 | #CFLAGS += $(call cc-option,-fweb) | 49 | #cflags-y += $(call cc-option,-fweb) |
51 | endif | 50 | endif |
52 | # -funit-at-a-time shrinks the kernel .text considerably | 51 | # -funit-at-a-time shrinks the kernel .text considerably |
53 | # unfortunately it makes reading oopses harder. | 52 | # unfortunately it makes reading oopses harder. |
54 | CFLAGS += $(call cc-option,-funit-at-a-time) | 53 | cflags-y += $(call cc-option,-funit-at-a-time) |
55 | # prevent gcc from generating any FP code by mistake | 54 | # prevent gcc from generating any FP code by mistake |
56 | CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) | 55 | cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) |
57 | 56 | ||
57 | CFLAGS += $(cflags-y) | ||
58 | AFLAGS += -m64 | 58 | AFLAGS += -m64 |
59 | 59 | ||
60 | head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o | 60 | head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o |
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 566ecc97ee5a..3c45ec22b3fe 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.16-git9 | 3 | # Linux kernel version: 2.6.17-rc1 |
4 | # Sat Mar 25 15:18:40 2006 | 4 | # Mon Apr 3 16:11:14 2006 |
5 | # | 5 | # |
6 | CONFIG_X86_64=y | 6 | CONFIG_X86_64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -9,6 +9,7 @@ CONFIG_X86=y | |||
9 | CONFIG_SEMAPHORE_SLEEPERS=y | 9 | CONFIG_SEMAPHORE_SLEEPERS=y |
10 | CONFIG_MMU=y | 10 | CONFIG_MMU=y |
11 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 11 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
12 | CONFIG_GENERIC_HWEIGHT=y | ||
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 13 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
13 | CONFIG_X86_CMPXCHG=y | 14 | CONFIG_X86_CMPXCHG=y |
14 | CONFIG_EARLY_PRINTK=y | 15 | CONFIG_EARLY_PRINTK=y |
@@ -55,10 +56,6 @@ CONFIG_BASE_FULL=y | |||
55 | CONFIG_FUTEX=y | 56 | CONFIG_FUTEX=y |
56 | CONFIG_EPOLL=y | 57 | CONFIG_EPOLL=y |
57 | CONFIG_SHMEM=y | 58 | CONFIG_SHMEM=y |
58 | CONFIG_CC_ALIGN_FUNCTIONS=0 | ||
59 | CONFIG_CC_ALIGN_LABELS=0 | ||
60 | CONFIG_CC_ALIGN_LOOPS=0 | ||
61 | CONFIG_CC_ALIGN_JUMPS=0 | ||
62 | CONFIG_SLAB=y | 59 | CONFIG_SLAB=y |
63 | # CONFIG_TINY_SHMEM is not set | 60 | # CONFIG_TINY_SHMEM is not set |
64 | CONFIG_BASE_SMALL=0 | 61 | CONFIG_BASE_SMALL=0 |
@@ -70,7 +67,6 @@ CONFIG_BASE_SMALL=0 | |||
70 | CONFIG_MODULES=y | 67 | CONFIG_MODULES=y |
71 | CONFIG_MODULE_UNLOAD=y | 68 | CONFIG_MODULE_UNLOAD=y |
72 | CONFIG_MODULE_FORCE_UNLOAD=y | 69 | CONFIG_MODULE_FORCE_UNLOAD=y |
73 | CONFIG_OBSOLETE_MODPARM=y | ||
74 | # CONFIG_MODVERSIONS is not set | 70 | # CONFIG_MODVERSIONS is not set |
75 | # CONFIG_MODULE_SRCVERSION_ALL is not set | 71 | # CONFIG_MODULE_SRCVERSION_ALL is not set |
76 | # CONFIG_KMOD is not set | 72 | # CONFIG_KMOD is not set |
@@ -81,6 +77,7 @@ CONFIG_STOP_MACHINE=y | |||
81 | # | 77 | # |
82 | CONFIG_LBD=y | 78 | CONFIG_LBD=y |
83 | # CONFIG_BLK_DEV_IO_TRACE is not set | 79 | # CONFIG_BLK_DEV_IO_TRACE is not set |
80 | # CONFIG_LSF is not set | ||
84 | 81 | ||
85 | # | 82 | # |
86 | # IO Schedulers | 83 | # IO Schedulers |
@@ -105,6 +102,7 @@ CONFIG_X86_PC=y | |||
105 | CONFIG_GENERIC_CPU=y | 102 | CONFIG_GENERIC_CPU=y |
106 | CONFIG_X86_L1_CACHE_BYTES=128 | 103 | CONFIG_X86_L1_CACHE_BYTES=128 |
107 | CONFIG_X86_L1_CACHE_SHIFT=7 | 104 | CONFIG_X86_L1_CACHE_SHIFT=7 |
105 | CONFIG_X86_INTERNODE_CACHE_BYTES=128 | ||
108 | CONFIG_X86_TSC=y | 106 | CONFIG_X86_TSC=y |
109 | CONFIG_X86_GOOD_APIC=y | 107 | CONFIG_X86_GOOD_APIC=y |
110 | # CONFIG_MICROCODE is not set | 108 | # CONFIG_MICROCODE is not set |
@@ -116,6 +114,7 @@ CONFIG_X86_LOCAL_APIC=y | |||
116 | CONFIG_MTRR=y | 114 | CONFIG_MTRR=y |
117 | CONFIG_SMP=y | 115 | CONFIG_SMP=y |
118 | CONFIG_SCHED_SMT=y | 116 | CONFIG_SCHED_SMT=y |
117 | CONFIG_SCHED_MC=y | ||
119 | # CONFIG_PREEMPT_NONE is not set | 118 | # CONFIG_PREEMPT_NONE is not set |
120 | CONFIG_PREEMPT_VOLUNTARY=y | 119 | CONFIG_PREEMPT_VOLUNTARY=y |
121 | # CONFIG_PREEMPT is not set | 120 | # CONFIG_PREEMPT is not set |
@@ -138,6 +137,7 @@ CONFIG_NEED_MULTIPLE_NODES=y | |||
138 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 137 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
139 | CONFIG_MIGRATION=y | 138 | CONFIG_MIGRATION=y |
140 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y | 139 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y |
140 | CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y | ||
141 | CONFIG_NR_CPUS=32 | 141 | CONFIG_NR_CPUS=32 |
142 | CONFIG_HOTPLUG_CPU=y | 142 | CONFIG_HOTPLUG_CPU=y |
143 | CONFIG_HPET_TIMER=y | 143 | CONFIG_HPET_TIMER=y |
@@ -289,6 +289,7 @@ CONFIG_IP_PNP_DHCP=y | |||
289 | # CONFIG_INET_AH is not set | 289 | # CONFIG_INET_AH is not set |
290 | # CONFIG_INET_ESP is not set | 290 | # CONFIG_INET_ESP is not set |
291 | # CONFIG_INET_IPCOMP is not set | 291 | # CONFIG_INET_IPCOMP is not set |
292 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
292 | # CONFIG_INET_TUNNEL is not set | 293 | # CONFIG_INET_TUNNEL is not set |
293 | CONFIG_INET_DIAG=y | 294 | CONFIG_INET_DIAG=y |
294 | CONFIG_INET_TCP_DIAG=y | 295 | CONFIG_INET_TCP_DIAG=y |
@@ -300,6 +301,7 @@ CONFIG_IPV6=y | |||
300 | # CONFIG_INET6_AH is not set | 301 | # CONFIG_INET6_AH is not set |
301 | # CONFIG_INET6_ESP is not set | 302 | # CONFIG_INET6_ESP is not set |
302 | # CONFIG_INET6_IPCOMP is not set | 303 | # CONFIG_INET6_IPCOMP is not set |
304 | # CONFIG_INET6_XFRM_TUNNEL is not set | ||
303 | # CONFIG_INET6_TUNNEL is not set | 305 | # CONFIG_INET6_TUNNEL is not set |
304 | # CONFIG_IPV6_TUNNEL is not set | 306 | # CONFIG_IPV6_TUNNEL is not set |
305 | # CONFIG_NETFILTER is not set | 307 | # CONFIG_NETFILTER is not set |
@@ -704,7 +706,6 @@ CONFIG_S2IO=m | |||
704 | # Wireless LAN (non-hamradio) | 706 | # Wireless LAN (non-hamradio) |
705 | # | 707 | # |
706 | # CONFIG_NET_RADIO is not set | 708 | # CONFIG_NET_RADIO is not set |
707 | # CONFIG_NET_WIRELESS_RTNETLINK is not set | ||
708 | 709 | ||
709 | # | 710 | # |
710 | # Wan interfaces | 711 | # Wan interfaces |
@@ -791,7 +792,7 @@ CONFIG_HW_CONSOLE=y | |||
791 | # | 792 | # |
792 | CONFIG_SERIAL_8250=y | 793 | CONFIG_SERIAL_8250=y |
793 | CONFIG_SERIAL_8250_CONSOLE=y | 794 | CONFIG_SERIAL_8250_CONSOLE=y |
794 | # CONFIG_SERIAL_8250_ACPI is not set | 795 | CONFIG_SERIAL_8250_PCI=y |
795 | CONFIG_SERIAL_8250_NR_UARTS=4 | 796 | CONFIG_SERIAL_8250_NR_UARTS=4 |
796 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | 797 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 |
797 | # CONFIG_SERIAL_8250_EXTENDED is not set | 798 | # CONFIG_SERIAL_8250_EXTENDED is not set |
@@ -921,6 +922,7 @@ CONFIG_HWMON=y | |||
921 | # Digital Video Broadcasting Devices | 922 | # Digital Video Broadcasting Devices |
922 | # | 923 | # |
923 | # CONFIG_DVB is not set | 924 | # CONFIG_DVB is not set |
925 | # CONFIG_USB_DABUSB is not set | ||
924 | 926 | ||
925 | # | 927 | # |
926 | # Graphics support | 928 | # Graphics support |
@@ -932,6 +934,8 @@ CONFIG_VIDEO_SELECT=y | |||
932 | # Console display driver support | 934 | # Console display driver support |
933 | # | 935 | # |
934 | CONFIG_VGA_CONSOLE=y | 936 | CONFIG_VGA_CONSOLE=y |
937 | CONFIG_VGACON_SOFT_SCROLLBACK=y | ||
938 | CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256 | ||
935 | CONFIG_DUMMY_CONSOLE=y | 939 | CONFIG_DUMMY_CONSOLE=y |
936 | 940 | ||
937 | # | 941 | # |
@@ -1058,15 +1062,6 @@ CONFIG_USB_HIDINPUT=y | |||
1058 | # CONFIG_USB_MICROTEK is not set | 1062 | # CONFIG_USB_MICROTEK is not set |
1059 | 1063 | ||
1060 | # | 1064 | # |
1061 | # USB Multimedia devices | ||
1062 | # | ||
1063 | # CONFIG_USB_DABUSB is not set | ||
1064 | |||
1065 | # | ||
1066 | # Video4Linux support is needed for USB Multimedia device support | ||
1067 | # | ||
1068 | |||
1069 | # | ||
1070 | # USB Network Adapters | 1065 | # USB Network Adapters |
1071 | # | 1066 | # |
1072 | # CONFIG_USB_CATC is not set | 1067 | # CONFIG_USB_CATC is not set |
@@ -1118,9 +1113,15 @@ CONFIG_USB_MON=y | |||
1118 | # CONFIG_MMC is not set | 1113 | # CONFIG_MMC is not set |
1119 | 1114 | ||
1120 | # | 1115 | # |
1116 | # LED devices | ||
1117 | # | ||
1118 | # CONFIG_NEW_LEDS is not set | ||
1119 | |||
1120 | # | ||
1121 | # InfiniBand support | 1121 | # InfiniBand support |
1122 | # | 1122 | # |
1123 | # CONFIG_INFINIBAND is not set | 1123 | # CONFIG_INFINIBAND is not set |
1124 | # CONFIG_IPATH_CORE is not set | ||
1124 | 1125 | ||
1125 | # | 1126 | # |
1126 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | 1127 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
@@ -1128,6 +1129,11 @@ CONFIG_USB_MON=y | |||
1128 | # CONFIG_EDAC is not set | 1129 | # CONFIG_EDAC is not set |
1129 | 1130 | ||
1130 | # | 1131 | # |
1132 | # Real Time Clock | ||
1133 | # | ||
1134 | # CONFIG_RTC_CLASS is not set | ||
1135 | |||
1136 | # | ||
1131 | # Firmware Drivers | 1137 | # Firmware Drivers |
1132 | # | 1138 | # |
1133 | # CONFIG_EDD is not set | 1139 | # CONFIG_EDD is not set |
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 35b2faccdc6c..5a9802676689 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <asm/vsyscall32.h> | 15 | #include <asm/vsyscall32.h> |
16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
17 | 17 | ||
18 | #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) | ||
19 | |||
18 | .macro IA32_ARG_FIXUP noebp=0 | 20 | .macro IA32_ARG_FIXUP noebp=0 |
19 | movl %edi,%r8d | 21 | movl %edi,%r8d |
20 | .if \noebp | 22 | .if \noebp |
@@ -109,8 +111,8 @@ ENTRY(ia32_sysenter_target) | |||
109 | CFI_REMEMBER_STATE | 111 | CFI_REMEMBER_STATE |
110 | jnz sysenter_tracesys | 112 | jnz sysenter_tracesys |
111 | sysenter_do_call: | 113 | sysenter_do_call: |
112 | cmpl $(IA32_NR_syscalls),%eax | 114 | cmpl $(IA32_NR_syscalls-1),%eax |
113 | jae ia32_badsys | 115 | ja ia32_badsys |
114 | IA32_ARG_FIXUP 1 | 116 | IA32_ARG_FIXUP 1 |
115 | call *ia32_sys_call_table(,%rax,8) | 117 | call *ia32_sys_call_table(,%rax,8) |
116 | movq %rax,RAX-ARGOFFSET(%rsp) | 118 | movq %rax,RAX-ARGOFFSET(%rsp) |
@@ -210,8 +212,8 @@ ENTRY(ia32_cstar_target) | |||
210 | CFI_REMEMBER_STATE | 212 | CFI_REMEMBER_STATE |
211 | jnz cstar_tracesys | 213 | jnz cstar_tracesys |
212 | cstar_do_call: | 214 | cstar_do_call: |
213 | cmpl $IA32_NR_syscalls,%eax | 215 | cmpl $IA32_NR_syscalls-1,%eax |
214 | jae ia32_badsys | 216 | ja ia32_badsys |
215 | IA32_ARG_FIXUP 1 | 217 | IA32_ARG_FIXUP 1 |
216 | call *ia32_sys_call_table(,%rax,8) | 218 | call *ia32_sys_call_table(,%rax,8) |
217 | movq %rax,RAX-ARGOFFSET(%rsp) | 219 | movq %rax,RAX-ARGOFFSET(%rsp) |
@@ -296,8 +298,8 @@ ENTRY(ia32_syscall) | |||
296 | testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10) | 298 | testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10) |
297 | jnz ia32_tracesys | 299 | jnz ia32_tracesys |
298 | ia32_do_syscall: | 300 | ia32_do_syscall: |
299 | cmpl $(IA32_NR_syscalls),%eax | 301 | cmpl $(IA32_NR_syscalls-1),%eax |
300 | jae ia32_badsys | 302 | ja ia32_badsys |
301 | IA32_ARG_FIXUP | 303 | IA32_ARG_FIXUP |
302 | call *ia32_sys_call_table(,%rax,8) # xxx: rip relative | 304 | call *ia32_sys_call_table(,%rax,8) # xxx: rip relative |
303 | ia32_sysret: | 305 | ia32_sysret: |
@@ -685,12 +687,11 @@ ia32_sys_call_table: | |||
685 | .quad sys_readlinkat /* 305 */ | 687 | .quad sys_readlinkat /* 305 */ |
686 | .quad sys_fchmodat | 688 | .quad sys_fchmodat |
687 | .quad sys_faccessat | 689 | .quad sys_faccessat |
688 | .quad sys_ni_syscall /* pselect6 for now */ | 690 | .quad quiet_ni_syscall /* pselect6 for now */ |
689 | .quad sys_ni_syscall /* ppoll for now */ | 691 | .quad quiet_ni_syscall /* ppoll for now */ |
690 | .quad sys_unshare /* 310 */ | 692 | .quad sys_unshare /* 310 */ |
691 | .quad compat_sys_set_robust_list | 693 | .quad compat_sys_set_robust_list |
692 | .quad compat_sys_get_robust_list | 694 | .quad compat_sys_get_robust_list |
695 | .quad sys_splice | ||
696 | .quad sys_sync_file_range | ||
693 | ia32_syscall_end: | 697 | ia32_syscall_end: |
694 | .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 | ||
695 | .quad ni_syscall | ||
696 | .endr | ||
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index fffd6b0a2fab..70b9d21ed675 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c | |||
@@ -80,7 +80,7 @@ static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size) | |||
80 | printk("Aperture from %s beyond 4GB. Ignoring.\n",name); | 80 | printk("Aperture from %s beyond 4GB. Ignoring.\n",name); |
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) { | 83 | if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { |
84 | printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name); | 84 | printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name); |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 293cd71a266a..62776c07cff1 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -80,7 +80,12 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) | |||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | int __init e820_mapped(unsigned long start, unsigned long end, unsigned type) | 83 | /* |
84 | * This function checks if any part of the range <start,end> is mapped | ||
85 | * with type. | ||
86 | */ | ||
87 | int __meminit | ||
88 | e820_any_mapped(unsigned long start, unsigned long end, unsigned type) | ||
84 | { | 89 | { |
85 | int i; | 90 | int i; |
86 | for (i = 0; i < e820.nr_map; i++) { | 91 | for (i = 0; i < e820.nr_map; i++) { |
@@ -94,6 +99,35 @@ int __init e820_mapped(unsigned long start, unsigned long end, unsigned type) | |||
94 | return 0; | 99 | return 0; |
95 | } | 100 | } |
96 | 101 | ||
102 | /* | ||
103 | * This function checks if the entire range <start,end> is mapped with type. | ||
104 | * | ||
105 | * Note: this function only works correct if the e820 table is sorted and | ||
106 | * not-overlapping, which is the case | ||
107 | */ | ||
108 | int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type) | ||
109 | { | ||
110 | int i; | ||
111 | for (i = 0; i < e820.nr_map; i++) { | ||
112 | struct e820entry *ei = &e820.map[i]; | ||
113 | if (type && ei->type != type) | ||
114 | continue; | ||
115 | /* is the region (part) in overlap with the current region ?*/ | ||
116 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
117 | continue; | ||
118 | |||
119 | /* if the region is at the beginning of <start,end> we move | ||
120 | * start to the end of the region since it's ok until there | ||
121 | */ | ||
122 | if (ei->addr <= start) | ||
123 | start = ei->addr + ei->size; | ||
124 | /* if start is now at or beyond end, we're done, full coverage */ | ||
125 | if (start >= end) | ||
126 | return 1; /* we're done */ | ||
127 | } | ||
128 | return 0; | ||
129 | } | ||
130 | |||
97 | /* | 131 | /* |
98 | * Find a free area in a specific range. | 132 | * Find a free area in a specific range. |
99 | */ | 133 | */ |
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 8538bfea30e6..c946e4fe67a7 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S | |||
@@ -180,6 +180,10 @@ rff_trace: | |||
180 | * | 180 | * |
181 | * XXX if we had a free scratch register we could save the RSP into the stack frame | 181 | * XXX if we had a free scratch register we could save the RSP into the stack frame |
182 | * and report it properly in ps. Unfortunately we haven't. | 182 | * and report it properly in ps. Unfortunately we haven't. |
183 | * | ||
184 | * When user can change the frames always force IRET. That is because | ||
185 | * it deals with uncanonical addresses better. SYSRET has trouble | ||
186 | * with them due to bugs in both AMD and Intel CPUs. | ||
183 | */ | 187 | */ |
184 | 188 | ||
185 | ENTRY(system_call) | 189 | ENTRY(system_call) |
@@ -254,7 +258,10 @@ sysret_signal: | |||
254 | xorl %esi,%esi # oldset -> arg2 | 258 | xorl %esi,%esi # oldset -> arg2 |
255 | call ptregscall_common | 259 | call ptregscall_common |
256 | 1: movl $_TIF_NEED_RESCHED,%edi | 260 | 1: movl $_TIF_NEED_RESCHED,%edi |
257 | jmp sysret_check | 261 | /* Use IRET because user could have changed frame. This |
262 | works because ptregscall_common has called FIXUP_TOP_OF_STACK. */ | ||
263 | cli | ||
264 | jmp int_with_check | ||
258 | 265 | ||
259 | badsys: | 266 | badsys: |
260 | movq $-ENOSYS,RAX-ARGOFFSET(%rsp) | 267 | movq $-ENOSYS,RAX-ARGOFFSET(%rsp) |
@@ -280,7 +287,8 @@ tracesys: | |||
280 | call syscall_trace_leave | 287 | call syscall_trace_leave |
281 | RESTORE_TOP_OF_STACK %rbx | 288 | RESTORE_TOP_OF_STACK %rbx |
282 | RESTORE_REST | 289 | RESTORE_REST |
283 | jmp ret_from_sys_call | 290 | /* Use IRET because user could have changed frame */ |
291 | jmp int_ret_from_sys_call | ||
284 | CFI_ENDPROC | 292 | CFI_ENDPROC |
285 | 293 | ||
286 | /* | 294 | /* |
@@ -408,25 +416,9 @@ ENTRY(stub_execve) | |||
408 | CFI_ADJUST_CFA_OFFSET -8 | 416 | CFI_ADJUST_CFA_OFFSET -8 |
409 | CFI_REGISTER rip, r11 | 417 | CFI_REGISTER rip, r11 |
410 | SAVE_REST | 418 | SAVE_REST |
411 | movq %r11, %r15 | ||
412 | CFI_REGISTER rip, r15 | ||
413 | FIXUP_TOP_OF_STACK %r11 | 419 | FIXUP_TOP_OF_STACK %r11 |
414 | call sys_execve | 420 | call sys_execve |
415 | GET_THREAD_INFO(%rcx) | ||
416 | bt $TIF_IA32,threadinfo_flags(%rcx) | ||
417 | CFI_REMEMBER_STATE | ||
418 | jc exec_32bit | ||
419 | RESTORE_TOP_OF_STACK %r11 | 421 | RESTORE_TOP_OF_STACK %r11 |
420 | movq %r15, %r11 | ||
421 | CFI_REGISTER rip, r11 | ||
422 | RESTORE_REST | ||
423 | pushq %r11 | ||
424 | CFI_ADJUST_CFA_OFFSET 8 | ||
425 | CFI_REL_OFFSET rip, 0 | ||
426 | ret | ||
427 | |||
428 | exec_32bit: | ||
429 | CFI_RESTORE_STATE | ||
430 | movq %rax,RAX(%rsp) | 422 | movq %rax,RAX(%rsp) |
431 | RESTORE_REST | 423 | RESTORE_REST |
432 | jmp int_ret_from_sys_call | 424 | jmp int_ret_from_sys_call |
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 10b3e348fc99..6f0790e8b6d3 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #define MISC_MCELOG_MINOR 227 | 29 | #define MISC_MCELOG_MINOR 227 |
30 | #define NR_BANKS 6 | 30 | #define NR_BANKS 6 |
31 | 31 | ||
32 | atomic_t mce_entry; | ||
33 | |||
32 | static int mce_dont_init; | 34 | static int mce_dont_init; |
33 | 35 | ||
34 | /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic, | 36 | /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic, |
@@ -172,10 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code) | |||
172 | int i; | 174 | int i; |
173 | int panicm_found = 0; | 175 | int panicm_found = 0; |
174 | 176 | ||
177 | atomic_inc(&mce_entry); | ||
178 | |||
175 | if (regs) | 179 | if (regs) |
176 | notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL); | 180 | notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL); |
177 | if (!banks) | 181 | if (!banks) |
178 | return; | 182 | goto out2; |
179 | 183 | ||
180 | memset(&m, 0, sizeof(struct mce)); | 184 | memset(&m, 0, sizeof(struct mce)); |
181 | m.cpu = safe_smp_processor_id(); | 185 | m.cpu = safe_smp_processor_id(); |
@@ -266,6 +270,8 @@ void do_machine_check(struct pt_regs * regs, long error_code) | |||
266 | out: | 270 | out: |
267 | /* Last thing done in the machine check exception to clear state. */ | 271 | /* Last thing done in the machine check exception to clear state. */ |
268 | wrmsrl(MSR_IA32_MCG_STATUS, 0); | 272 | wrmsrl(MSR_IA32_MCG_STATUS, 0); |
273 | out2: | ||
274 | atomic_dec(&mce_entry); | ||
269 | } | 275 | } |
270 | 276 | ||
271 | /* | 277 | /* |
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index d9e4067faf05..4e6357fe0ec3 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/proto.h> | 34 | #include <asm/proto.h> |
35 | #include <asm/kdebug.h> | 35 | #include <asm/kdebug.h> |
36 | #include <asm/local.h> | 36 | #include <asm/local.h> |
37 | #include <asm/mce.h> | ||
37 | 38 | ||
38 | /* | 39 | /* |
39 | * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: | 40 | * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: |
@@ -480,6 +481,12 @@ void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
480 | __get_cpu_var(nmi_touch) = 0; | 481 | __get_cpu_var(nmi_touch) = 0; |
481 | touched = 1; | 482 | touched = 1; |
482 | } | 483 | } |
484 | #ifdef CONFIG_X86_MCE | ||
485 | /* Could check oops_in_progress here too, but it's safer | ||
486 | not too */ | ||
487 | if (atomic_read(&mce_entry) > 0) | ||
488 | touched = 1; | ||
489 | #endif | ||
483 | if (!touched && __get_cpu_var(last_irq_sum) == sum) { | 490 | if (!touched && __get_cpu_var(last_irq_sum) == sum) { |
484 | /* | 491 | /* |
485 | * Ayiee, looks like this CPU is stuck ... | 492 | * Ayiee, looks like this CPU is stuck ... |
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index 03c9eeedb0f3..af035ede70cd 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c | |||
@@ -48,9 +48,11 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order) | |||
48 | { | 48 | { |
49 | struct page *page; | 49 | struct page *page; |
50 | int node; | 50 | int node; |
51 | #ifdef CONFIG_PCI | ||
51 | if (dev->bus == &pci_bus_type) | 52 | if (dev->bus == &pci_bus_type) |
52 | node = pcibus_to_node(to_pci_dev(dev)->bus); | 53 | node = pcibus_to_node(to_pci_dev(dev)->bus); |
53 | else | 54 | else |
55 | #endif | ||
54 | node = numa_node_id(); | 56 | node = numa_node_id(); |
55 | page = alloc_pages_node(node, gfp, order); | 57 | page = alloc_pages_node(node, gfp, order); |
56 | return page ? page_address(page) : NULL; | 58 | return page ? page_address(page) : NULL; |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 70dd8e5c6889..1c44b53cb15b 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -781,10 +781,16 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
781 | } | 781 | } |
782 | case ARCH_GET_GS: { | 782 | case ARCH_GET_GS: { |
783 | unsigned long base; | 783 | unsigned long base; |
784 | unsigned gsindex; | ||
784 | if (task->thread.gsindex == GS_TLS_SEL) | 785 | if (task->thread.gsindex == GS_TLS_SEL) |
785 | base = read_32bit_tls(task, GS_TLS); | 786 | base = read_32bit_tls(task, GS_TLS); |
786 | else if (doit) | 787 | else if (doit) { |
787 | rdmsrl(MSR_KERNEL_GS_BASE, base); | 788 | asm("movl %%gs,%0" : "=r" (gsindex)); |
789 | if (gsindex) | ||
790 | rdmsrl(MSR_KERNEL_GS_BASE, base); | ||
791 | else | ||
792 | base = task->thread.gs; | ||
793 | } | ||
788 | else | 794 | else |
789 | base = task->thread.gs; | 795 | base = task->thread.gs; |
790 | ret = put_user(base, (unsigned long __user *)addr); | 796 | ret = put_user(base, (unsigned long __user *)addr); |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 0856ad444f90..c50b06765a80 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -353,8 +353,10 @@ static __init void parse_cmdline_early (char ** cmdline_p) | |||
353 | if (fullarg(from, "enable_timer_pin_1")) | 353 | if (fullarg(from, "enable_timer_pin_1")) |
354 | disable_timer_pin_1 = -1; | 354 | disable_timer_pin_1 = -1; |
355 | 355 | ||
356 | if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) | 356 | if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) { |
357 | clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); | ||
357 | disable_apic = 1; | 358 | disable_apic = 1; |
359 | } | ||
358 | 360 | ||
359 | if (fullarg(from, "noapic")) | 361 | if (fullarg(from, "noapic")) |
360 | skip_ioapic_setup = 1; | 362 | skip_ioapic_setup = 1; |
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index ef8bc46dc140..7392570f975d 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
@@ -726,7 +726,7 @@ static __init int late_hpet_init(void) | |||
726 | unsigned int ntimer; | 726 | unsigned int ntimer; |
727 | 727 | ||
728 | if (!vxtime.hpet_address) | 728 | if (!vxtime.hpet_address) |
729 | return -1; | 729 | return 0; |
730 | 730 | ||
731 | memset(&hd, 0, sizeof (hd)); | 731 | memset(&hd, 0, sizeof (hd)); |
732 | 732 | ||
@@ -917,6 +917,8 @@ void __init time_init(void) | |||
917 | vxtime.hpet_address = 0; | 917 | vxtime.hpet_address = 0; |
918 | 918 | ||
919 | if (hpet_use_timer) { | 919 | if (hpet_use_timer) { |
920 | /* set tick_nsec to use the proper rate for HPET */ | ||
921 | tick_nsec = TICK_NSEC_HPET; | ||
920 | cpu_khz = hpet_calibrate_tsc(); | 922 | cpu_khz = hpet_calibrate_tsc(); |
921 | timename = "HPET"; | 923 | timename = "HPET"; |
922 | #ifdef CONFIG_X86_PM_TIMER | 924 | #ifdef CONFIG_X86_PM_TIMER |
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 39ff0708f803..b81f473c4a19 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S | |||
@@ -65,7 +65,7 @@ SECTIONS | |||
65 | .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { | 65 | .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { |
66 | *(.data.cacheline_aligned) | 66 | *(.data.cacheline_aligned) |
67 | } | 67 | } |
68 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); | 68 | . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES); |
69 | .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { | 69 | .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { |
70 | *(.data.read_mostly) | 70 | *(.data.read_mostly) |
71 | } | 71 | } |
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index d78f46056bda..fec4e521c01c 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c | |||
@@ -112,7 +112,6 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback); | |||
112 | #undef memcpy | 112 | #undef memcpy |
113 | #undef memset | 113 | #undef memset |
114 | #undef memmove | 114 | #undef memmove |
115 | #undef strlen | ||
116 | 115 | ||
117 | extern void * memset(void *,int,__kernel_size_t); | 116 | extern void * memset(void *,int,__kernel_size_t); |
118 | extern size_t strlen(const char *); | 117 | extern size_t strlen(const char *); |
@@ -121,7 +120,6 @@ extern void * memcpy(void *,const void *,__kernel_size_t); | |||
121 | extern void * __memcpy(void *,const void *,__kernel_size_t); | 120 | extern void * __memcpy(void *,const void *,__kernel_size_t); |
122 | 121 | ||
123 | EXPORT_SYMBOL(memset); | 122 | EXPORT_SYMBOL(memset); |
124 | EXPORT_SYMBOL(strlen); | ||
125 | EXPORT_SYMBOL(strpbrk); | 123 | EXPORT_SYMBOL(strpbrk); |
126 | EXPORT_SYMBOL(memmove); | 124 | EXPORT_SYMBOL(memmove); |
127 | EXPORT_SYMBOL(memcpy); | 125 | EXPORT_SYMBOL(memcpy); |
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index e5f7f1c34462..4ba34e95d835 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -305,7 +305,7 @@ static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned | |||
305 | if (paddr >= end) | 305 | if (paddr >= end) |
306 | break; | 306 | break; |
307 | 307 | ||
308 | if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) { | 308 | if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) { |
309 | set_pud(pud, __pud(0)); | 309 | set_pud(pud, __pud(0)); |
310 | continue; | 310 | continue; |
311 | } | 311 | } |
@@ -507,9 +507,8 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) | |||
507 | 507 | ||
508 | /* | 508 | /* |
509 | * Memory hotplug specific functions | 509 | * Memory hotplug specific functions |
510 | * These are only for non-NUMA machines right now. | ||
511 | */ | 510 | */ |
512 | #ifdef CONFIG_MEMORY_HOTPLUG | 511 | #if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) |
513 | 512 | ||
514 | void online_page(struct page *page) | 513 | void online_page(struct page *page) |
515 | { | 514 | { |
@@ -520,6 +519,38 @@ void online_page(struct page *page) | |||
520 | num_physpages++; | 519 | num_physpages++; |
521 | } | 520 | } |
522 | 521 | ||
522 | #ifndef CONFIG_MEMORY_HOTPLUG | ||
523 | /* | ||
524 | * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance, | ||
525 | * just online the pages. | ||
526 | */ | ||
527 | int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) | ||
528 | { | ||
529 | int err = -EIO; | ||
530 | unsigned long pfn; | ||
531 | unsigned long total = 0, mem = 0; | ||
532 | for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) { | ||
533 | if (pfn_valid(pfn)) { | ||
534 | online_page(pfn_to_page(pfn)); | ||
535 | err = 0; | ||
536 | mem++; | ||
537 | } | ||
538 | total++; | ||
539 | } | ||
540 | if (!err) { | ||
541 | z->spanned_pages += total; | ||
542 | z->present_pages += mem; | ||
543 | z->zone_pgdat->node_spanned_pages += total; | ||
544 | z->zone_pgdat->node_present_pages += mem; | ||
545 | } | ||
546 | return err; | ||
547 | } | ||
548 | #endif | ||
549 | |||
550 | /* | ||
551 | * Memory is added always to NORMAL zone. This means you will never get | ||
552 | * additional DMA/DMA32 memory. | ||
553 | */ | ||
523 | int add_memory(u64 start, u64 size) | 554 | int add_memory(u64 start, u64 size) |
524 | { | 555 | { |
525 | struct pglist_data *pgdat = NODE_DATA(0); | 556 | struct pglist_data *pgdat = NODE_DATA(0); |
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 4be82d6e2b48..cc02573a3271 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -100,11 +100,30 @@ int early_pfn_to_nid(unsigned long pfn) | |||
100 | } | 100 | } |
101 | #endif | 101 | #endif |
102 | 102 | ||
103 | static void * __init | ||
104 | early_node_mem(int nodeid, unsigned long start, unsigned long end, | ||
105 | unsigned long size) | ||
106 | { | ||
107 | unsigned long mem = find_e820_area(start, end, size); | ||
108 | void *ptr; | ||
109 | if (mem != -1L) | ||
110 | return __va(mem); | ||
111 | ptr = __alloc_bootmem_nopanic(size, | ||
112 | SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); | ||
113 | if (ptr == 0) { | ||
114 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", | ||
115 | size, nodeid); | ||
116 | return NULL; | ||
117 | } | ||
118 | return ptr; | ||
119 | } | ||
120 | |||
103 | /* Initialize bootmem allocator for a node */ | 121 | /* Initialize bootmem allocator for a node */ |
104 | void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | 122 | void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) |
105 | { | 123 | { |
106 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; | 124 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; |
107 | unsigned long nodedata_phys; | 125 | unsigned long nodedata_phys; |
126 | void *bootmap; | ||
108 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); | 127 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); |
109 | 128 | ||
110 | start = round_up(start, ZONE_ALIGN); | 129 | start = round_up(start, ZONE_ALIGN); |
@@ -114,13 +133,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
114 | start_pfn = start >> PAGE_SHIFT; | 133 | start_pfn = start >> PAGE_SHIFT; |
115 | end_pfn = end >> PAGE_SHIFT; | 134 | end_pfn = end >> PAGE_SHIFT; |
116 | 135 | ||
117 | nodedata_phys = find_e820_area(start, end, pgdat_size); | 136 | node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size); |
118 | if (nodedata_phys == -1L) | 137 | if (node_data[nodeid] == NULL) |
119 | panic("Cannot find memory pgdat in node %d\n", nodeid); | 138 | return; |
120 | 139 | nodedata_phys = __pa(node_data[nodeid]); | |
121 | Dprintk("nodedata_phys %lx\n", nodedata_phys); | ||
122 | 140 | ||
123 | node_data[nodeid] = phys_to_virt(nodedata_phys); | ||
124 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); | 141 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); |
125 | NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid]; | 142 | NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid]; |
126 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; | 143 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; |
@@ -129,9 +146,15 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
129 | /* Find a place for the bootmem map */ | 146 | /* Find a place for the bootmem map */ |
130 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 147 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
131 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); | 148 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); |
132 | bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT); | 149 | bootmap = early_node_mem(nodeid, bootmap_start, end, |
133 | if (bootmap_start == -1L) | 150 | bootmap_pages<<PAGE_SHIFT); |
134 | panic("Not enough continuous space for bootmap on node %d", nodeid); | 151 | if (bootmap == NULL) { |
152 | if (nodedata_phys < start || nodedata_phys >= end) | ||
153 | free_bootmem((unsigned long)node_data[nodeid],pgdat_size); | ||
154 | node_data[nodeid] = NULL; | ||
155 | return; | ||
156 | } | ||
157 | bootmap_start = __pa(bootmap); | ||
135 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); | 158 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); |
136 | 159 | ||
137 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), | 160 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), |
@@ -142,6 +165,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
142 | 165 | ||
143 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); | 166 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); |
144 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT); | 167 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT); |
168 | #ifdef CONFIG_ACPI_NUMA | ||
169 | srat_reserve_add_area(nodeid); | ||
170 | #endif | ||
145 | node_set_online(nodeid); | 171 | node_set_online(nodeid); |
146 | } | 172 | } |
147 | 173 | ||
@@ -335,6 +361,8 @@ __init int numa_setup(char *opt) | |||
335 | #ifdef CONFIG_ACPI_NUMA | 361 | #ifdef CONFIG_ACPI_NUMA |
336 | if (!strncmp(opt,"noacpi",6)) | 362 | if (!strncmp(opt,"noacpi",6)) |
337 | acpi_numa = -1; | 363 | acpi_numa = -1; |
364 | if (!strncmp(opt,"hotadd=", 7)) | ||
365 | hotadd_percent = simple_strtoul(opt+7, NULL, 10); | ||
338 | #endif | 366 | #endif |
339 | return 1; | 367 | return 1; |
340 | } | 368 | } |
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 2eb879590dc4..15ae9fcd65a7 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -15,15 +15,26 @@ | |||
15 | #include <linux/bitmap.h> | 15 | #include <linux/bitmap.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/topology.h> | 17 | #include <linux/topology.h> |
18 | #include <linux/bootmem.h> | ||
19 | #include <linux/mm.h> | ||
18 | #include <asm/proto.h> | 20 | #include <asm/proto.h> |
19 | #include <asm/numa.h> | 21 | #include <asm/numa.h> |
20 | #include <asm/e820.h> | 22 | #include <asm/e820.h> |
21 | 23 | ||
24 | #if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \ | ||
25 | defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \ | ||
26 | && !defined(CONFIG_MEMORY_HOTPLUG) | ||
27 | #define RESERVE_HOTADD 1 | ||
28 | #endif | ||
29 | |||
22 | static struct acpi_table_slit *acpi_slit; | 30 | static struct acpi_table_slit *acpi_slit; |
23 | 31 | ||
24 | static nodemask_t nodes_parsed __initdata; | 32 | static nodemask_t nodes_parsed __initdata; |
25 | static nodemask_t nodes_found __initdata; | 33 | static nodemask_t nodes_found __initdata; |
26 | static struct bootnode nodes[MAX_NUMNODES] __initdata; | 34 | static struct bootnode nodes[MAX_NUMNODES] __initdata; |
35 | static struct bootnode nodes_add[MAX_NUMNODES] __initdata; | ||
36 | static int found_add_area __initdata; | ||
37 | int hotadd_percent __initdata = 10; | ||
27 | static u8 pxm2node[256] = { [0 ... 255] = 0xff }; | 38 | static u8 pxm2node[256] = { [0 ... 255] = 0xff }; |
28 | 39 | ||
29 | /* Too small nodes confuse the VM badly. Usually they result | 40 | /* Too small nodes confuse the VM badly. Usually they result |
@@ -71,6 +82,10 @@ static __init int conflicting_nodes(unsigned long start, unsigned long end) | |||
71 | static __init void cutoff_node(int i, unsigned long start, unsigned long end) | 82 | static __init void cutoff_node(int i, unsigned long start, unsigned long end) |
72 | { | 83 | { |
73 | struct bootnode *nd = &nodes[i]; | 84 | struct bootnode *nd = &nodes[i]; |
85 | |||
86 | if (found_add_area) | ||
87 | return; | ||
88 | |||
74 | if (nd->start < start) { | 89 | if (nd->start < start) { |
75 | nd->start = start; | 90 | nd->start = start; |
76 | if (nd->end < nd->start) | 91 | if (nd->end < nd->start) |
@@ -90,6 +105,8 @@ static __init void bad_srat(void) | |||
90 | acpi_numa = -1; | 105 | acpi_numa = -1; |
91 | for (i = 0; i < MAX_LOCAL_APIC; i++) | 106 | for (i = 0; i < MAX_LOCAL_APIC; i++) |
92 | apicid_to_node[i] = NUMA_NO_NODE; | 107 | apicid_to_node[i] = NUMA_NO_NODE; |
108 | for (i = 0; i < MAX_NUMNODES; i++) | ||
109 | nodes_add[i].start = nodes[i].end = 0; | ||
93 | } | 110 | } |
94 | 111 | ||
95 | static __init inline int srat_disabled(void) | 112 | static __init inline int srat_disabled(void) |
@@ -155,11 +172,114 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) | |||
155 | pxm, pa->apic_id, node); | 172 | pxm, pa->apic_id, node); |
156 | } | 173 | } |
157 | 174 | ||
175 | #ifdef RESERVE_HOTADD | ||
176 | /* | ||
177 | * Protect against too large hotadd areas that would fill up memory. | ||
178 | */ | ||
179 | static int hotadd_enough_memory(struct bootnode *nd) | ||
180 | { | ||
181 | static unsigned long allocated; | ||
182 | static unsigned long last_area_end; | ||
183 | unsigned long pages = (nd->end - nd->start) >> PAGE_SHIFT; | ||
184 | long mem = pages * sizeof(struct page); | ||
185 | unsigned long addr; | ||
186 | unsigned long allowed; | ||
187 | unsigned long oldpages = pages; | ||
188 | |||
189 | if (mem < 0) | ||
190 | return 0; | ||
191 | allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE; | ||
192 | allowed = (allowed / 100) * hotadd_percent; | ||
193 | if (allocated + mem > allowed) { | ||
194 | /* Give them at least part of their hotadd memory upto hotadd_percent | ||
195 | It would be better to spread the limit out | ||
196 | over multiple hotplug areas, but that is too complicated | ||
197 | right now */ | ||
198 | if (allocated >= allowed) | ||
199 | return 0; | ||
200 | pages = (allowed - allocated + mem) / sizeof(struct page); | ||
201 | mem = pages * sizeof(struct page); | ||
202 | nd->end = nd->start + pages*PAGE_SIZE; | ||
203 | } | ||
204 | /* Not completely fool proof, but a good sanity check */ | ||
205 | addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem); | ||
206 | if (addr == -1UL) | ||
207 | return 0; | ||
208 | if (pages != oldpages) | ||
209 | printk(KERN_NOTICE "SRAT: Hotadd area limited to %lu bytes\n", | ||
210 | pages << PAGE_SHIFT); | ||
211 | last_area_end = addr + mem; | ||
212 | allocated += mem; | ||
213 | return 1; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * It is fine to add this area to the nodes data it will be used later | ||
218 | * This code supports one contigious hot add area per node. | ||
219 | */ | ||
220 | static int reserve_hotadd(int node, unsigned long start, unsigned long end) | ||
221 | { | ||
222 | unsigned long s_pfn = start >> PAGE_SHIFT; | ||
223 | unsigned long e_pfn = end >> PAGE_SHIFT; | ||
224 | int changed = 0; | ||
225 | struct bootnode *nd = &nodes_add[node]; | ||
226 | |||
227 | /* I had some trouble with strange memory hotadd regions breaking | ||
228 | the boot. Be very strict here and reject anything unexpected. | ||
229 | If you want working memory hotadd write correct SRATs. | ||
230 | |||
231 | The node size check is a basic sanity check to guard against | ||
232 | mistakes */ | ||
233 | if ((signed long)(end - start) < NODE_MIN_SIZE) { | ||
234 | printk(KERN_ERR "SRAT: Hotplug area too small\n"); | ||
235 | return -1; | ||
236 | } | ||
237 | |||
238 | /* This check might be a bit too strict, but I'm keeping it for now. */ | ||
239 | if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) { | ||
240 | printk(KERN_ERR "SRAT: Hotplug area has existing memory\n"); | ||
241 | return -1; | ||
242 | } | ||
243 | |||
244 | if (!hotadd_enough_memory(&nodes_add[node])) { | ||
245 | printk(KERN_ERR "SRAT: Hotplug area too large\n"); | ||
246 | return -1; | ||
247 | } | ||
248 | |||
249 | /* Looks good */ | ||
250 | |||
251 | found_add_area = 1; | ||
252 | if (nd->start == nd->end) { | ||
253 | nd->start = start; | ||
254 | nd->end = end; | ||
255 | changed = 1; | ||
256 | } else { | ||
257 | if (nd->start == end) { | ||
258 | nd->start = start; | ||
259 | changed = 1; | ||
260 | } | ||
261 | if (nd->end == start) { | ||
262 | nd->end = end; | ||
263 | changed = 1; | ||
264 | } | ||
265 | if (!changed) | ||
266 | printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n"); | ||
267 | } | ||
268 | |||
269 | if ((nd->end >> PAGE_SHIFT) > end_pfn) | ||
270 | end_pfn = nd->end >> PAGE_SHIFT; | ||
271 | |||
272 | if (changed) | ||
273 | printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end); | ||
274 | return 0; | ||
275 | } | ||
276 | #endif | ||
277 | |||
158 | /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ | 278 | /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ |
159 | void __init | 279 | void __init |
160 | acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | 280 | acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) |
161 | { | 281 | { |
162 | struct bootnode *nd; | 282 | struct bootnode *nd, oldnode; |
163 | unsigned long start, end; | 283 | unsigned long start, end; |
164 | int node, pxm; | 284 | int node, pxm; |
165 | int i; | 285 | int i; |
@@ -172,6 +292,8 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
172 | } | 292 | } |
173 | if (ma->flags.enabled == 0) | 293 | if (ma->flags.enabled == 0) |
174 | return; | 294 | return; |
295 | if (ma->flags.hot_pluggable && hotadd_percent == 0) | ||
296 | return; | ||
175 | start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); | 297 | start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); |
176 | end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); | 298 | end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); |
177 | pxm = ma->proximity_domain; | 299 | pxm = ma->proximity_domain; |
@@ -181,10 +303,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
181 | bad_srat(); | 303 | bad_srat(); |
182 | return; | 304 | return; |
183 | } | 305 | } |
184 | /* It is fine to add this area to the nodes data it will be used later*/ | ||
185 | if (ma->flags.hot_pluggable == 1) | ||
186 | printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n", | ||
187 | start, end); | ||
188 | i = conflicting_nodes(start, end); | 306 | i = conflicting_nodes(start, end); |
189 | if (i == node) { | 307 | if (i == node) { |
190 | printk(KERN_WARNING | 308 | printk(KERN_WARNING |
@@ -199,6 +317,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
199 | return; | 317 | return; |
200 | } | 318 | } |
201 | nd = &nodes[node]; | 319 | nd = &nodes[node]; |
320 | oldnode = *nd; | ||
202 | if (!node_test_and_set(node, nodes_parsed)) { | 321 | if (!node_test_and_set(node, nodes_parsed)) { |
203 | nd->start = start; | 322 | nd->start = start; |
204 | nd->end = end; | 323 | nd->end = end; |
@@ -208,8 +327,19 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
208 | if (nd->end < end) | 327 | if (nd->end < end) |
209 | nd->end = end; | 328 | nd->end = end; |
210 | } | 329 | } |
330 | |||
211 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, | 331 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, |
212 | nd->start, nd->end); | 332 | nd->start, nd->end); |
333 | |||
334 | #ifdef RESERVE_HOTADD | ||
335 | if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) { | ||
336 | /* Ignore hotadd region. Undo damage */ | ||
337 | printk(KERN_NOTICE "SRAT: Hotplug region ignored\n"); | ||
338 | *nd = oldnode; | ||
339 | if ((nd->start | nd->end) == 0) | ||
340 | node_clear(node, nodes_parsed); | ||
341 | } | ||
342 | #endif | ||
213 | } | 343 | } |
214 | 344 | ||
215 | /* Sanity check to catch more bad SRATs (they are amazingly common). | 345 | /* Sanity check to catch more bad SRATs (they are amazingly common). |
@@ -225,6 +355,9 @@ static int nodes_cover_memory(void) | |||
225 | unsigned long e = nodes[i].end >> PAGE_SHIFT; | 355 | unsigned long e = nodes[i].end >> PAGE_SHIFT; |
226 | pxmram += e - s; | 356 | pxmram += e - s; |
227 | pxmram -= e820_hole_size(s, e); | 357 | pxmram -= e820_hole_size(s, e); |
358 | pxmram -= nodes_add[i].end - nodes_add[i].start; | ||
359 | if ((long)pxmram < 0) | ||
360 | pxmram = 0; | ||
228 | } | 361 | } |
229 | 362 | ||
230 | e820ram = end_pfn - e820_hole_size(0, end_pfn); | 363 | e820ram = end_pfn - e820_hole_size(0, end_pfn); |
@@ -258,7 +391,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
258 | 391 | ||
259 | /* First clean up the node list */ | 392 | /* First clean up the node list */ |
260 | for (i = 0; i < MAX_NUMNODES; i++) { | 393 | for (i = 0; i < MAX_NUMNODES; i++) { |
261 | cutoff_node(i, start, end); | 394 | cutoff_node(i, start, end); |
262 | if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) | 395 | if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) |
263 | unparse_node(i); | 396 | unparse_node(i); |
264 | } | 397 | } |
@@ -282,6 +415,12 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
282 | /* Finally register nodes */ | 415 | /* Finally register nodes */ |
283 | for_each_node_mask(i, nodes_parsed) | 416 | for_each_node_mask(i, nodes_parsed) |
284 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 417 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
418 | /* Try again in case setup_node_bootmem missed one due | ||
419 | to missing bootmem */ | ||
420 | for_each_node_mask(i, nodes_parsed) | ||
421 | if (!node_online(i)) | ||
422 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | ||
423 | |||
285 | for (i = 0; i < NR_CPUS; i++) { | 424 | for (i = 0; i < NR_CPUS; i++) { |
286 | if (cpu_to_node[i] == NUMA_NO_NODE) | 425 | if (cpu_to_node[i] == NUMA_NO_NODE) |
287 | continue; | 426 | continue; |
@@ -303,6 +442,25 @@ static int node_to_pxm(int n) | |||
303 | return 0; | 442 | return 0; |
304 | } | 443 | } |
305 | 444 | ||
445 | void __init srat_reserve_add_area(int nodeid) | ||
446 | { | ||
447 | if (found_add_area && nodes_add[nodeid].end) { | ||
448 | u64 total_mb; | ||
449 | |||
450 | printk(KERN_INFO "SRAT: Reserving hot-add memory space " | ||
451 | "for node %d at %Lx-%Lx\n", | ||
452 | nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end); | ||
453 | total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start) | ||
454 | >> PAGE_SHIFT; | ||
455 | total_mb *= sizeof(struct page); | ||
456 | total_mb >>= 20; | ||
457 | printk(KERN_INFO "SRAT: This will cost you %Lu MB of " | ||
458 | "pre-allocated memory.\n", (unsigned long long)total_mb); | ||
459 | reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start, | ||
460 | nodes_add[nodeid].end - nodes_add[nodeid].start); | ||
461 | } | ||
462 | } | ||
463 | |||
306 | int __node_distance(int a, int b) | 464 | int __node_distance(int a, int b) |
307 | { | 465 | { |
308 | int index; | 466 | int index; |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index e616500207e4..b493ed977e7c 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
@@ -9,11 +9,16 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/acpi.h> | 10 | #include <linux/acpi.h> |
11 | #include <linux/bitmap.h> | 11 | #include <linux/bitmap.h> |
12 | #include <asm/e820.h> | ||
13 | |||
12 | #include "pci.h" | 14 | #include "pci.h" |
13 | 15 | ||
14 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 16 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
17 | /* Verify the first 16 busses. We assume that systems with more busses | ||
18 | get MCFG right. */ | ||
19 | #define MAX_CHECK_BUS 16 | ||
15 | 20 | ||
16 | static DECLARE_BITMAP(fallback_slots, 32); | 21 | static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS); |
17 | 22 | ||
18 | /* Static virtual mapping of the MMCONFIG aperture */ | 23 | /* Static virtual mapping of the MMCONFIG aperture */ |
19 | struct mmcfg_virt { | 24 | struct mmcfg_virt { |
@@ -55,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) | |||
55 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | 60 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) |
56 | { | 61 | { |
57 | char __iomem *addr; | 62 | char __iomem *addr; |
58 | if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots)) | 63 | if (seg == 0 && bus < MAX_CHECK_BUS && |
64 | test_bit(32*bus + PCI_SLOT(devfn), fallback_slots)) | ||
59 | return NULL; | 65 | return NULL; |
60 | addr = get_virt(seg, bus); | 66 | addr = get_virt(seg, bus); |
61 | if (!addr) | 67 | if (!addr) |
@@ -69,8 +75,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
69 | char __iomem *addr; | 75 | char __iomem *addr; |
70 | 76 | ||
71 | /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ | 77 | /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ |
72 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) | 78 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) { |
79 | *value = -1; | ||
73 | return -EINVAL; | 80 | return -EINVAL; |
81 | } | ||
74 | 82 | ||
75 | addr = pci_dev_base(seg, bus, devfn); | 83 | addr = pci_dev_base(seg, bus, devfn); |
76 | if (!addr) | 84 | if (!addr) |
@@ -129,21 +137,26 @@ static struct pci_raw_ops pci_mmcfg = { | |||
129 | Normally this can be expressed in the MCFG by not listing them | 137 | Normally this can be expressed in the MCFG by not listing them |
130 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | 138 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. |
131 | Instead try to discover all devices on bus 0 that are unreachable using MM | 139 | Instead try to discover all devices on bus 0 that are unreachable using MM |
132 | and fallback for them. | 140 | and fallback for them. */ |
133 | We only do this for bus 0/seg 0 */ | ||
134 | static __init void unreachable_devices(void) | 141 | static __init void unreachable_devices(void) |
135 | { | 142 | { |
136 | int i; | 143 | int i, k; |
137 | for (i = 0; i < 32; i++) { | 144 | /* Use the max bus number from ACPI here? */ |
138 | u32 val1; | 145 | for (k = 0; i < MAX_CHECK_BUS; k++) { |
139 | char __iomem *addr; | 146 | for (i = 0; i < 32; i++) { |
140 | 147 | u32 val1; | |
141 | pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); | 148 | char __iomem *addr; |
142 | if (val1 == 0xffffffff) | 149 | |
143 | continue; | 150 | pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1); |
144 | addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); | 151 | if (val1 == 0xffffffff) |
145 | if (addr == NULL|| readl(addr) != val1) { | 152 | continue; |
146 | set_bit(i, fallback_slots); | 153 | addr = pci_dev_base(0, k, PCI_DEVFN(i, 0)); |
154 | if (addr == NULL|| readl(addr) != val1) { | ||
155 | set_bit(i + 32*k, fallback_slots); | ||
156 | printk(KERN_NOTICE | ||
157 | "PCI: No mmconfig possible on device %x:%x\n", | ||
158 | k, i); | ||
159 | } | ||
147 | } | 160 | } |
148 | } | 161 | } |
149 | } | 162 | } |
@@ -161,6 +174,14 @@ void __init pci_mmcfg_init(void) | |||
161 | (pci_mmcfg_config[0].base_address == 0)) | 174 | (pci_mmcfg_config[0].base_address == 0)) |
162 | return; | 175 | return; |
163 | 176 | ||
177 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
178 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | ||
179 | E820_RESERVED)) { | ||
180 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | ||
181 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
182 | return; | ||
183 | } | ||
184 | |||
164 | /* RED-PEN i386 doesn't do _nocache right now */ | 185 | /* RED-PEN i386 doesn't do _nocache right now */ |
165 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); | 186 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); |
166 | if (pci_mmcfg_virt == NULL) { | 187 | if (pci_mmcfg_virt == NULL) { |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5cb96300eb0f..c24652d31bf9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -329,7 +329,7 @@ config ACPI_CONTAINER | |||
329 | config ACPI_HOTPLUG_MEMORY | 329 | config ACPI_HOTPLUG_MEMORY |
330 | tristate "Memory Hotplug" | 330 | tristate "Memory Hotplug" |
331 | depends on ACPI | 331 | depends on ACPI |
332 | depends on MEMORY_HOTPLUG | 332 | depends on MEMORY_HOTPLUG || X86_64 |
333 | default n | 333 | default n |
334 | help | 334 | help |
335 | This driver adds supports for ACPI Memory Hotplug. This driver | 335 | This driver adds supports for ACPI Memory Hotplug. This driver |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 86be04b241e1..58f3512c52e1 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo | |||
1584 | 1584 | ||
1585 | return twothirdsMD4Transform(daddr, hash); | 1585 | return twothirdsMD4Transform(daddr, hash); |
1586 | } | 1586 | } |
1587 | EXPORT_SYMBOL(secure_ipv6_port_ephemeral); | ||
1588 | #endif | 1587 | #endif |
1589 | 1588 | ||
1590 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) | 1589 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) |
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 6e2ec56cde0b..606243d11793 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Filename: irda-usb.c | 3 | * Filename: irda-usb.c |
4 | * Version: 0.9b | 4 | * Version: 0.10 |
5 | * Description: IrDA-USB Driver | 5 | * Description: IrDA-USB Driver |
6 | * Status: Experimental | 6 | * Status: Experimental |
7 | * Author: Dag Brattli <dag@brattli.net> | 7 | * Author: Dag Brattli <dag@brattli.net> |
@@ -9,6 +9,9 @@ | |||
9 | * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> | 9 | * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> |
10 | * Copyright (C) 2001, Dag Brattli <dag@brattli.net> | 10 | * Copyright (C) 2001, Dag Brattli <dag@brattli.net> |
11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> | 11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> |
12 | * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> | ||
13 | * Copyright (C) 2005, Milan Beno <beno@pobox.sk> | ||
14 | * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua> | ||
12 | * | 15 | * |
13 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -61,6 +64,7 @@ | |||
61 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
62 | #include <linux/rtnetlink.h> | 65 | #include <linux/rtnetlink.h> |
63 | #include <linux/usb.h> | 66 | #include <linux/usb.h> |
67 | #include <linux/firmware.h> | ||
64 | 68 | ||
65 | #include "irda-usb.h" | 69 | #include "irda-usb.h" |
66 | 70 | ||
@@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = { | |||
78 | { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, | 82 | { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, |
79 | /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ | 83 | /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ |
80 | { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, | 84 | { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, |
85 | /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ | ||
86 | { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
87 | { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
88 | { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
81 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | | 89 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | |
82 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | 90 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, |
83 | .bInterfaceClass = USB_CLASS_APP_SPEC, | 91 | .bInterfaceClass = USB_CLASS_APP_SPEC, |
84 | .bInterfaceSubClass = USB_CLASS_IRDA, | 92 | .bInterfaceSubClass = USB_CLASS_IRDA, |
85 | .driver_info = IUC_DEFAULT, }, | 93 | .driver_info = IUC_DEFAULT, }, |
@@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles); | |||
99 | 107 | ||
100 | /*------------------------------------------------------------------*/ | 108 | /*------------------------------------------------------------------*/ |
101 | 109 | ||
110 | static void irda_usb_init_qos(struct irda_usb_cb *self) ; | ||
102 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); | 111 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); |
103 | static void irda_usb_disconnect(struct usb_interface *intf); | 112 | static void irda_usb_disconnect(struct usb_interface *intf); |
104 | static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); | 113 | static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); |
@@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
141 | __u8 *header, | 150 | __u8 *header, |
142 | int force) | 151 | int force) |
143 | { | 152 | { |
144 | /* Set the negotiated link speed */ | 153 | /* Here we check if we have an STIR421x chip, |
154 | * and if either speed or xbofs (or both) needs | ||
155 | * to be changed. | ||
156 | */ | ||
157 | if (self->capability & IUC_STIR_4210 && | ||
158 | ((self->new_speed != -1) || (self->new_xbofs != -1))) { | ||
159 | |||
160 | /* With STIR421x, speed and xBOFs must be set at the same | ||
161 | * time, even if only one of them changes. | ||
162 | */ | ||
163 | if (self->new_speed == -1) | ||
164 | self->new_speed = self->speed ; | ||
165 | |||
166 | if (self->new_xbofs == -1) | ||
167 | self->new_xbofs = self->xbofs ; | ||
168 | } | ||
169 | |||
170 | /* Set the link speed */ | ||
145 | if (self->new_speed != -1) { | 171 | if (self->new_speed != -1) { |
146 | /* Hum... Ugly hack :-( | 172 | /* Hum... Ugly hack :-( |
147 | * Some device are not compliant with the spec and change | 173 | * Some device are not compliant with the spec and change |
@@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
191 | *header = SPEED_4000000; | 217 | *header = SPEED_4000000; |
192 | self->new_xbofs = 0; | 218 | self->new_xbofs = 0; |
193 | break; | 219 | break; |
194 | } | 220 | case 16000000: |
221 | *header = SPEED_16000000; | ||
222 | self->new_xbofs = 0; | ||
223 | break; | ||
224 | } | ||
195 | } else | 225 | } else |
196 | /* No change */ | 226 | /* No change */ |
197 | *header = 0; | 227 | *header = 0; |
@@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
235 | } | 265 | } |
236 | } | 266 | } |
237 | 267 | ||
268 | /* | ||
269 | * calculate turnaround time for SigmaTel header | ||
270 | */ | ||
271 | static __u8 get_turnaround_time(struct sk_buff *skb) | ||
272 | { | ||
273 | int turnaround_time = irda_get_mtt(skb); | ||
274 | |||
275 | if ( turnaround_time == 0 ) | ||
276 | return 0; | ||
277 | else if ( turnaround_time <= 10 ) | ||
278 | return 1; | ||
279 | else if ( turnaround_time <= 50 ) | ||
280 | return 2; | ||
281 | else if ( turnaround_time <= 100 ) | ||
282 | return 3; | ||
283 | else if ( turnaround_time <= 500 ) | ||
284 | return 4; | ||
285 | else if ( turnaround_time <= 1000 ) | ||
286 | return 5; | ||
287 | else if ( turnaround_time <= 5000 ) | ||
288 | return 6; | ||
289 | else | ||
290 | return 7; | ||
291 | } | ||
292 | |||
293 | |||
238 | /*------------------------------------------------------------------*/ | 294 | /*------------------------------------------------------------------*/ |
239 | /* | 295 | /* |
240 | * Send a command to change the speed of the dongle | 296 | * Send a command to change the speed of the dongle |
@@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) | |||
262 | /* Set the new speed and xbofs in this fake frame */ | 318 | /* Set the new speed and xbofs in this fake frame */ |
263 | irda_usb_build_header(self, frame, 1); | 319 | irda_usb_build_header(self, frame, 1); |
264 | 320 | ||
321 | if ( self->capability & IUC_STIR_4210 ) { | ||
322 | if (frame[0] == 0) return ; // do nothing if no change | ||
323 | frame[1] = 0; // other parameters don't change here | ||
324 | frame[2] = 0; | ||
325 | } | ||
326 | |||
265 | /* Submit the 0 length IrDA frame to trigger new speed settings */ | 327 | /* Submit the 0 length IrDA frame to trigger new speed settings */ |
266 | usb_fill_bulk_urb(urb, self->usbdev, | 328 | usb_fill_bulk_urb(urb, self->usbdev, |
267 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), | 329 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), |
268 | frame, IRDA_USB_SPEED_MTU, | 330 | frame, IRDA_USB_SPEED_MTU, |
269 | speed_bulk_callback, self); | 331 | speed_bulk_callback, self); |
270 | urb->transfer_buffer_length = USB_IRDA_HEADER; | 332 | urb->transfer_buffer_length = self->header_length; |
271 | urb->transfer_flags = 0; | 333 | urb->transfer_flags = 0; |
272 | 334 | ||
273 | /* Irq disabled -> GFP_ATOMIC */ | 335 | /* Irq disabled -> GFP_ATOMIC */ |
@@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
383 | * allocation will be done lower in skb_push(). | 445 | * allocation will be done lower in skb_push(). |
384 | * Also, we don't use directly skb_cow(), because it require | 446 | * Also, we don't use directly skb_cow(), because it require |
385 | * headroom >= 16, which force unnecessary copies - Jean II */ | 447 | * headroom >= 16, which force unnecessary copies - Jean II */ |
386 | if (skb_headroom(skb) < USB_IRDA_HEADER) { | 448 | if (skb_headroom(skb) < self->header_length) { |
387 | IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); | 449 | IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); |
388 | if (skb_cow(skb, USB_IRDA_HEADER)) { | 450 | if (skb_cow(skb, self->header_length)) { |
389 | IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); | 451 | IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); |
390 | goto drop; | 452 | goto drop; |
391 | } | 453 | } |
392 | } | 454 | } |
393 | 455 | ||
394 | /* Change setting for next frame */ | 456 | /* Change setting for next frame */ |
395 | irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); | 457 | |
458 | if ( self->capability & IUC_STIR_4210 ) { | ||
459 | __u8 turnaround_time; | ||
460 | __u8* frame; | ||
461 | turnaround_time = get_turnaround_time( skb ); | ||
462 | frame= skb_push(skb, self->header_length); | ||
463 | irda_usb_build_header(self, frame, 0); | ||
464 | frame[2] = turnaround_time; | ||
465 | if ((skb->len != 0) && | ||
466 | ((skb->len % 128) == 0) && | ||
467 | ((skb->len % 512) != 0)) { | ||
468 | /* add extra byte for special SigmaTel feature */ | ||
469 | frame[1] = 1; | ||
470 | skb_put(skb, 1); | ||
471 | } else { | ||
472 | frame[1] = 0; | ||
473 | } | ||
474 | } else { | ||
475 | irda_usb_build_header(self, skb_push(skb, self->header_length), 0); | ||
476 | } | ||
396 | 477 | ||
397 | /* FIXME: Make macro out of this one */ | 478 | /* FIXME: Make macro out of this one */ |
398 | ((struct irda_skb_cb *)skb->cb)->context = self; | 479 | ((struct irda_skb_cb *)skb->cb)->context = self; |
@@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
795 | } | 876 | } |
796 | 877 | ||
797 | /* Check for empty frames */ | 878 | /* Check for empty frames */ |
798 | if (urb->actual_length <= USB_IRDA_HEADER) { | 879 | if (urb->actual_length <= self->header_length) { |
799 | IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); | 880 | IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); |
800 | goto done; | 881 | goto done; |
801 | } | 882 | } |
@@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
816 | docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); | 897 | docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); |
817 | 898 | ||
818 | /* Allocate a new skb */ | 899 | /* Allocate a new skb */ |
819 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); | 900 | if ( self->capability & IUC_STIR_4210 ) |
901 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER); | ||
902 | else | ||
903 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); | ||
904 | |||
820 | if (!newskb) { | 905 | if (!newskb) { |
821 | self->stats.rx_dropped++; | 906 | self->stats.rx_dropped++; |
822 | /* We could deliver the current skb, but this would stall | 907 | /* We could deliver the current skb, but this would stall |
@@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
845 | 930 | ||
846 | /* Set proper length on skb & remove USB-IrDA header */ | 931 | /* Set proper length on skb & remove USB-IrDA header */ |
847 | skb_put(dataskb, urb->actual_length); | 932 | skb_put(dataskb, urb->actual_length); |
848 | skb_pull(dataskb, USB_IRDA_HEADER); | 933 | skb_pull(dataskb, self->header_length); |
849 | 934 | ||
850 | /* Ask the networking layer to queue the packet for the IrDA stack */ | 935 | /* Ask the networking layer to queue the packet for the IrDA stack */ |
851 | dataskb->dev = self->netdev; | 936 | dataskb->dev = self->netdev; |
@@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self) | |||
937 | return 0; /* For now */ | 1022 | return 0; /* For now */ |
938 | } | 1023 | } |
939 | 1024 | ||
1025 | |||
1026 | #define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: " | ||
1027 | #define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: " | ||
1028 | #define STIR421X_PATCH_DATA_TAG_STR "STMP" | ||
1029 | #define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */ | ||
1030 | #define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */ | ||
1031 | #define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */ | ||
1032 | |||
1033 | /* | ||
1034 | * Known firmware patches for STIR421x dongles | ||
1035 | */ | ||
1036 | static char * stir421x_patches[] = { | ||
1037 | "42101001.sb", | ||
1038 | "42101002.sb", | ||
1039 | }; | ||
1040 | |||
1041 | static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len) | ||
1042 | { | ||
1043 | unsigned int version_offset; | ||
1044 | unsigned long version_major, version_minor, version_build; | ||
1045 | unsigned char * version_start; | ||
1046 | int version_found = 0; | ||
1047 | |||
1048 | for (version_offset = 0; | ||
1049 | version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG; | ||
1050 | version_offset++) { | ||
1051 | if (!memcmp(patch + version_offset, | ||
1052 | STIR421X_PATCH_PRODUCT_VERSION_STR, | ||
1053 | sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) { | ||
1054 | version_found = 1; | ||
1055 | version_start = patch + | ||
1056 | version_offset + | ||
1057 | sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1; | ||
1058 | break; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | /* We couldn't find a product version on this patch */ | ||
1063 | if (!version_found) | ||
1064 | return -EINVAL; | ||
1065 | |||
1066 | /* Let's check if the product version is dotted */ | ||
1067 | if (version_start[3] != '.' || | ||
1068 | version_start[7] != '.') | ||
1069 | return -EINVAL; | ||
1070 | |||
1071 | version_major = simple_strtoul(version_start, NULL, 10); | ||
1072 | version_minor = simple_strtoul(version_start + 4, NULL, 10); | ||
1073 | version_build = simple_strtoul(version_start + 8, NULL, 10); | ||
1074 | |||
1075 | IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n", | ||
1076 | __FUNCTION__, | ||
1077 | version_major, version_minor, version_build); | ||
1078 | |||
1079 | return (((version_major) << 12) + | ||
1080 | ((version_minor) << 8) + | ||
1081 | ((version_build / 10) << 4) + | ||
1082 | (version_build % 10)); | ||
1083 | |||
1084 | } | ||
1085 | |||
1086 | |||
1087 | static int stir421x_upload_patch (struct irda_usb_cb *self, | ||
1088 | unsigned char * patch, | ||
1089 | const unsigned int patch_len) | ||
1090 | { | ||
1091 | int retval = 0; | ||
1092 | int actual_len; | ||
1093 | unsigned int i = 0, download_amount = 0; | ||
1094 | unsigned char * patch_chunk; | ||
1095 | |||
1096 | IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__); | ||
1097 | |||
1098 | patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL); | ||
1099 | if (patch_chunk == NULL) | ||
1100 | return -ENOMEM; | ||
1101 | |||
1102 | /* break up patch into 1023-byte sections */ | ||
1103 | for (i = 0; retval >= 0 && i < patch_len; i += download_amount) { | ||
1104 | download_amount = patch_len - i; | ||
1105 | if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE) | ||
1106 | download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE; | ||
1107 | |||
1108 | /* download the patch section */ | ||
1109 | memcpy(patch_chunk, patch + i, download_amount); | ||
1110 | |||
1111 | retval = usb_bulk_msg (self->usbdev, | ||
1112 | usb_sndbulkpipe (self->usbdev, | ||
1113 | self->bulk_out_ep), | ||
1114 | patch_chunk, download_amount, | ||
1115 | &actual_len, msecs_to_jiffies (500)); | ||
1116 | IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__, | ||
1117 | actual_len); | ||
1118 | if (retval == 0) | ||
1119 | mdelay(10); | ||
1120 | } | ||
1121 | |||
1122 | kfree(patch_chunk); | ||
1123 | |||
1124 | if (i != patch_len) { | ||
1125 | IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n", | ||
1126 | __FUNCTION__, i, patch_len); | ||
1127 | retval = -EIO; | ||
1128 | } | ||
1129 | |||
1130 | if (retval < 0) | ||
1131 | /* todo - mark device as not ready */ | ||
1132 | IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n", | ||
1133 | __FUNCTION__, retval); | ||
1134 | |||
1135 | return retval; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | static int stir421x_patch_device(struct irda_usb_cb *self) | ||
1140 | { | ||
1141 | unsigned int i, patch_found = 0, data_found = 0, data_offset; | ||
1142 | int patch_version, ret = 0; | ||
1143 | const struct firmware *fw_entry; | ||
1144 | |||
1145 | for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) { | ||
1146 | if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) { | ||
1147 | IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]); | ||
1148 | continue; | ||
1149 | } | ||
1150 | |||
1151 | /* We found a patch from userspace */ | ||
1152 | patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size); | ||
1153 | |||
1154 | if (patch_version < 0) { | ||
1155 | /* Couldn't fetch a version, let's move on to the next file */ | ||
1156 | IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__); | ||
1157 | ret = patch_version; | ||
1158 | release_firmware(fw_entry); | ||
1159 | continue; | ||
1160 | } | ||
1161 | |||
1162 | if (patch_version != self->usbdev->descriptor.bcdDevice) { | ||
1163 | /* Patch version and device don't match */ | ||
1164 | IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n", | ||
1165 | __FUNCTION__, | ||
1166 | patch_version, self->usbdev->descriptor.bcdDevice); | ||
1167 | ret = -EINVAL; | ||
1168 | release_firmware(fw_entry); | ||
1169 | continue; | ||
1170 | } | ||
1171 | |||
1172 | /* If we're here, we've found a correct patch */ | ||
1173 | patch_found = 1; | ||
1174 | break; | ||
1175 | |||
1176 | } | ||
1177 | |||
1178 | /* We couldn't find a valid firmware, let's leave */ | ||
1179 | if (!patch_found) | ||
1180 | return ret; | ||
1181 | |||
1182 | /* The actual image starts after the "STMP" keyword */ | ||
1183 | for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) { | ||
1184 | if (!memcmp(fw_entry->data + data_offset, | ||
1185 | STIR421X_PATCH_DATA_TAG_STR, | ||
1186 | sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) { | ||
1187 | IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n", | ||
1188 | __FUNCTION__, data_offset); | ||
1189 | data_found = 1; | ||
1190 | break; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | /* We couldn't find "STMP" from the header */ | ||
1195 | if (!data_found) | ||
1196 | return -EINVAL; | ||
1197 | |||
1198 | /* Let's upload the patch to the target */ | ||
1199 | ret = stir421x_upload_patch(self, | ||
1200 | &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)], | ||
1201 | fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))); | ||
1202 | |||
1203 | release_firmware(fw_entry); | ||
1204 | |||
1205 | return ret; | ||
1206 | |||
1207 | } | ||
1208 | |||
1209 | |||
940 | /********************** IRDA DEVICE CALLBACKS **********************/ | 1210 | /********************** IRDA DEVICE CALLBACKS **********************/ |
941 | /* | 1211 | /* |
942 | * Main calls from the IrDA/Network subsystem. | 1212 | * Main calls from the IrDA/Network subsystem. |
@@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev) | |||
972 | return -1; | 1242 | return -1; |
973 | } | 1243 | } |
974 | 1244 | ||
1245 | if(self->needspatch) { | ||
1246 | IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ; | ||
1247 | return -EIO ; | ||
1248 | } | ||
1249 | |||
975 | /* Initialise default speed and xbofs value | 1250 | /* Initialise default speed and xbofs value |
976 | * (IrLAP will change that soon) */ | 1251 | * (IrLAP will change that soon) */ |
977 | self->speed = -1; | 1252 | self->speed = -1; |
@@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev) | |||
1050 | del_timer(&self->rx_defer_timer); | 1325 | del_timer(&self->rx_defer_timer); |
1051 | 1326 | ||
1052 | /* Deallocate all the Rx path buffers (URBs and skb) */ | 1327 | /* Deallocate all the Rx path buffers (URBs and skb) */ |
1053 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1328 | for (i = 0; i < self->max_rx_urb; i++) { |
1054 | struct urb *urb = self->rx_urb[i]; | 1329 | struct urb *urb = self->rx_urb[i]; |
1055 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 1330 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
1056 | /* Cancel the receive command */ | 1331 | /* Cancel the receive command */ |
@@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1426 | spin_lock_init(&self->lock); | 1701 | spin_lock_init(&self->lock); |
1427 | init_timer(&self->rx_defer_timer); | 1702 | init_timer(&self->rx_defer_timer); |
1428 | 1703 | ||
1704 | self->capability = id->driver_info; | ||
1705 | self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ; | ||
1706 | |||
1429 | /* Create all of the needed urbs */ | 1707 | /* Create all of the needed urbs */ |
1430 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1708 | if (self->capability & IUC_STIR_4210) { |
1709 | self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; | ||
1710 | self->header_length = USB_IRDA_SIGMATEL_HEADER; | ||
1711 | } else { | ||
1712 | self->max_rx_urb = IU_MAX_RX_URBS; | ||
1713 | self->header_length = USB_IRDA_HEADER; | ||
1714 | } | ||
1715 | |||
1716 | self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), | ||
1717 | GFP_KERNEL); | ||
1718 | |||
1719 | for (i = 0; i < self->max_rx_urb; i++) { | ||
1431 | self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); | 1720 | self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); |
1432 | if (!self->rx_urb[i]) { | 1721 | if (!self->rx_urb[i]) { |
1433 | goto err_out_1; | 1722 | goto err_out_1; |
@@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1479 | goto err_out_3; | 1768 | goto err_out_3; |
1480 | } | 1769 | } |
1481 | 1770 | ||
1771 | self->usbdev = dev; | ||
1772 | |||
1482 | /* Find IrDA class descriptor */ | 1773 | /* Find IrDA class descriptor */ |
1483 | irda_desc = irda_usb_find_class_desc(intf); | 1774 | irda_desc = irda_usb_find_class_desc(intf); |
1484 | ret = -ENODEV; | 1775 | ret = -ENODEV; |
1485 | if (irda_desc == NULL) | 1776 | if (irda_desc == NULL) |
1486 | goto err_out_3; | 1777 | goto err_out_3; |
1487 | 1778 | ||
1779 | if (self->needspatch) { | ||
1780 | ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), | ||
1781 | 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500)); | ||
1782 | if (ret < 0) { | ||
1783 | IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); | ||
1784 | goto err_out_3; | ||
1785 | } else { | ||
1786 | mdelay(10); | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1488 | self->irda_desc = irda_desc; | 1790 | self->irda_desc = irda_desc; |
1489 | self->present = 1; | 1791 | self->present = 1; |
1490 | self->netopen = 0; | 1792 | self->netopen = 0; |
1491 | self->capability = id->driver_info; | ||
1492 | self->usbdev = dev; | ||
1493 | self->usbintf = intf; | 1793 | self->usbintf = intf; |
1494 | 1794 | ||
1495 | /* Allocate the buffer for speed changes */ | 1795 | /* Allocate the buffer for speed changes */ |
@@ -1508,6 +1808,28 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1508 | 1808 | ||
1509 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); | 1809 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); |
1510 | usb_set_intfdata(intf, self); | 1810 | usb_set_intfdata(intf, self); |
1811 | |||
1812 | if (self->needspatch) { | ||
1813 | /* Now we fetch and upload the firmware patch */ | ||
1814 | ret = stir421x_patch_device(self); | ||
1815 | self->needspatch = (ret < 0); | ||
1816 | if (ret < 0) { | ||
1817 | printk("patch_device failed\n"); | ||
1818 | goto err_out_4; | ||
1819 | } | ||
1820 | |||
1821 | /* replace IrDA class descriptor with what patched device is now reporting */ | ||
1822 | irda_desc = irda_usb_find_class_desc (self->usbintf); | ||
1823 | if (irda_desc == NULL) { | ||
1824 | ret = -ENODEV; | ||
1825 | goto err_out_4; | ||
1826 | } | ||
1827 | if (self->irda_desc) | ||
1828 | kfree (self->irda_desc); | ||
1829 | self->irda_desc = irda_desc; | ||
1830 | irda_usb_init_qos(self); | ||
1831 | } | ||
1832 | |||
1511 | return 0; | 1833 | return 0; |
1512 | 1834 | ||
1513 | err_out_4: | 1835 | err_out_4: |
@@ -1518,7 +1840,7 @@ err_out_3: | |||
1518 | err_out_2: | 1840 | err_out_2: |
1519 | usb_free_urb(self->tx_urb); | 1841 | usb_free_urb(self->tx_urb); |
1520 | err_out_1: | 1842 | err_out_1: |
1521 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1843 | for (i = 0; i < self->max_rx_urb; i++) { |
1522 | if (self->rx_urb[i]) | 1844 | if (self->rx_urb[i]) |
1523 | usb_free_urb(self->rx_urb[i]); | 1845 | usb_free_urb(self->rx_urb[i]); |
1524 | } | 1846 | } |
@@ -1571,7 +1893,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) | |||
1571 | /*netif_device_detach(self->netdev);*/ | 1893 | /*netif_device_detach(self->netdev);*/ |
1572 | netif_stop_queue(self->netdev); | 1894 | netif_stop_queue(self->netdev); |
1573 | /* Stop all the receive URBs. Must be synchronous. */ | 1895 | /* Stop all the receive URBs. Must be synchronous. */ |
1574 | for (i = 0; i < IU_MAX_RX_URBS; i++) | 1896 | for (i = 0; i < self->max_rx_urb; i++) |
1575 | usb_kill_urb(self->rx_urb[i]); | 1897 | usb_kill_urb(self->rx_urb[i]); |
1576 | /* Cancel Tx and speed URB. | 1898 | /* Cancel Tx and speed URB. |
1577 | * Make sure it's synchronous to avoid races. */ | 1899 | * Make sure it's synchronous to avoid races. */ |
@@ -1586,8 +1908,9 @@ static void irda_usb_disconnect(struct usb_interface *intf) | |||
1586 | self->usbintf = NULL; | 1908 | self->usbintf = NULL; |
1587 | 1909 | ||
1588 | /* Clean up our urbs */ | 1910 | /* Clean up our urbs */ |
1589 | for (i = 0; i < IU_MAX_RX_URBS; i++) | 1911 | for (i = 0; i < self->max_rx_urb; i++) |
1590 | usb_free_urb(self->rx_urb[i]); | 1912 | usb_free_urb(self->rx_urb[i]); |
1913 | kfree(self->rx_urb); | ||
1591 | /* Clean up Tx and speed URB */ | 1914 | /* Clean up Tx and speed URB */ |
1592 | usb_free_urb(self->tx_urb); | 1915 | usb_free_urb(self->tx_urb); |
1593 | usb_free_urb(self->speed_urb); | 1916 | usb_free_urb(self->speed_urb); |
@@ -1648,6 +1971,6 @@ module_exit(usb_irda_cleanup); | |||
1648 | */ | 1971 | */ |
1649 | module_param(qos_mtt_bits, int, 0); | 1972 | module_param(qos_mtt_bits, int, 0); |
1650 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); | 1973 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); |
1651 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>"); | 1974 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>"); |
1652 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); | 1975 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); |
1653 | MODULE_LICENSE("GPL"); | 1976 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index 4026af42dd47..d833db52cebf 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Filename: irda-usb.h | 3 | * Filename: irda-usb.h |
4 | * Version: 0.9b | 4 | * Version: 0.10 |
5 | * Description: IrDA-USB Driver | 5 | * Description: IrDA-USB Driver |
6 | * Status: Experimental | 6 | * Status: Experimental |
7 | * Author: Dag Brattli <dag@brattli.net> | 7 | * Author: Dag Brattli <dag@brattli.net> |
@@ -9,6 +9,9 @@ | |||
9 | * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> | 9 | * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> |
10 | * Copyright (C) 2000, Dag Brattli <dag@brattli.net> | 10 | * Copyright (C) 2000, Dag Brattli <dag@brattli.net> |
11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> | 11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> |
12 | * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> | ||
13 | * Copyright (C) 2005, Milan Beno <beno@pobox.sk> | ||
14 | * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua> | ||
12 | * | 15 | * |
13 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -31,6 +34,9 @@ | |||
31 | #include <net/irda/irda.h> | 34 | #include <net/irda/irda.h> |
32 | #include <net/irda/irda_device.h> /* struct irlap_cb */ | 35 | #include <net/irda/irda_device.h> /* struct irlap_cb */ |
33 | 36 | ||
37 | #define PATCH_FILE_SIZE_MAX 65536 | ||
38 | #define PATCH_FILE_SIZE_MIN 80 | ||
39 | |||
34 | #define RX_COPY_THRESHOLD 200 | 40 | #define RX_COPY_THRESHOLD 200 |
35 | #define IRDA_USB_MAX_MTU 2051 | 41 | #define IRDA_USB_MAX_MTU 2051 |
36 | #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ | 42 | #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ |
@@ -79,15 +85,16 @@ | |||
79 | /* Inbound header */ | 85 | /* Inbound header */ |
80 | #define MEDIA_BUSY 0x80 | 86 | #define MEDIA_BUSY 0x80 |
81 | 87 | ||
82 | #define SPEED_2400 0x01 | 88 | #define SPEED_2400 0x01 |
83 | #define SPEED_9600 0x02 | 89 | #define SPEED_9600 0x02 |
84 | #define SPEED_19200 0x03 | 90 | #define SPEED_19200 0x03 |
85 | #define SPEED_38400 0x04 | 91 | #define SPEED_38400 0x04 |
86 | #define SPEED_57600 0x05 | 92 | #define SPEED_57600 0x05 |
87 | #define SPEED_115200 0x06 | 93 | #define SPEED_115200 0x06 |
88 | #define SPEED_576000 0x07 | 94 | #define SPEED_576000 0x07 |
89 | #define SPEED_1152000 0x08 | 95 | #define SPEED_1152000 0x08 |
90 | #define SPEED_4000000 0x09 | 96 | #define SPEED_4000000 0x09 |
97 | #define SPEED_16000000 0x0a | ||
91 | 98 | ||
92 | /* Basic capabilities */ | 99 | /* Basic capabilities */ |
93 | #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ | 100 | #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ |
@@ -100,11 +107,14 @@ | |||
100 | #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ | 107 | #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ |
101 | #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ | 108 | #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ |
102 | #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ | 109 | #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ |
110 | #define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */ | ||
103 | 111 | ||
104 | /* USB class definitions */ | 112 | /* USB class definitions */ |
105 | #define USB_IRDA_HEADER 0x01 | 113 | #define USB_IRDA_HEADER 0x01 |
106 | #define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ | 114 | #define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ |
107 | #define USB_DT_IRDA 0x21 | 115 | #define USB_DT_IRDA 0x21 |
116 | #define USB_IRDA_SIGMATEL_HEADER 0x03 | ||
117 | #define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER) | ||
108 | 118 | ||
109 | struct irda_class_desc { | 119 | struct irda_class_desc { |
110 | __u8 bLength; | 120 | __u8 bLength; |
@@ -123,6 +133,7 @@ struct irda_class_desc { | |||
123 | * (6.2.5, USB-IrDA class spec 1.0) */ | 133 | * (6.2.5, USB-IrDA class spec 1.0) */ |
124 | 134 | ||
125 | #define IU_REQ_GET_CLASS_DESC 0x06 | 135 | #define IU_REQ_GET_CLASS_DESC 0x06 |
136 | #define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023 | ||
126 | 137 | ||
127 | struct irda_usb_cb { | 138 | struct irda_usb_cb { |
128 | struct irda_class_desc *irda_desc; | 139 | struct irda_class_desc *irda_desc; |
@@ -136,7 +147,8 @@ struct irda_usb_cb { | |||
136 | __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ | 147 | __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ |
137 | __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ | 148 | __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ |
138 | 149 | ||
139 | struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */ | 150 | __u8 max_rx_urb; |
151 | struct urb **rx_urb; /* URBs used to receive data frames */ | ||
140 | struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ | 152 | struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ |
141 | struct urb *tx_urb; /* URB used to send data frames */ | 153 | struct urb *tx_urb; /* URB used to send data frames */ |
142 | struct urb *speed_urb; /* URB used to send speed commands */ | 154 | struct urb *speed_urb; /* URB used to send speed commands */ |
@@ -157,6 +169,9 @@ struct irda_usb_cb { | |||
157 | __u32 speed; /* Current speed */ | 169 | __u32 speed; /* Current speed */ |
158 | __s32 new_speed; /* speed we need to set */ | 170 | __s32 new_speed; /* speed we need to set */ |
159 | 171 | ||
172 | __u8 header_length; /* USB-IrDA frame header size */ | ||
173 | int needspatch; /* device needs firmware patch */ | ||
174 | |||
160 | struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ | 175 | struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ |
161 | }; | 176 | }; |
162 | 177 | ||
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index ec94ecdb103d..bbcfc8ec35a1 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Copyright (c) 2002 Daniele Peri | 11 | * Copyright (c) 2002 Daniele Peri |
12 | * All Rights Reserved. | 12 | * All Rights Reserved. |
13 | * Copyright (c) 2002 Jean Tourrilhes | 13 | * Copyright (c) 2002 Jean Tourrilhes |
14 | * Copyright (c) 2006 Linus Walleij | ||
14 | * | 15 | * |
15 | * | 16 | * |
16 | * Based on smc-ircc.c: | 17 | * Based on smc-ircc.c: |
@@ -61,6 +62,9 @@ | |||
61 | 62 | ||
62 | #include <linux/spinlock.h> | 63 | #include <linux/spinlock.h> |
63 | #include <linux/pm.h> | 64 | #include <linux/pm.h> |
65 | #ifdef CONFIG_PCI | ||
66 | #include <linux/pci.h> | ||
67 | #endif | ||
64 | 68 | ||
65 | #include <net/irda/wrapper.h> | 69 | #include <net/irda/wrapper.h> |
66 | #include <net/irda/irda.h> | 70 | #include <net/irda/irda.h> |
@@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); | |||
100 | 104 | ||
101 | /* Types */ | 105 | /* Types */ |
102 | 106 | ||
107 | #ifdef CONFIG_PCI | ||
108 | struct smsc_ircc_subsystem_configuration { | ||
109 | unsigned short vendor; /* PCI vendor ID */ | ||
110 | unsigned short device; /* PCI vendor ID */ | ||
111 | unsigned short subvendor; /* PCI subsystem vendor ID */ | ||
112 | unsigned short subdevice; /* PCI sybsystem device ID */ | ||
113 | unsigned short sir_io; /* I/O port for SIR */ | ||
114 | unsigned short fir_io; /* I/O port for FIR */ | ||
115 | unsigned char fir_irq; /* FIR IRQ */ | ||
116 | unsigned char fir_dma; /* FIR DMA */ | ||
117 | unsigned short cfg_base; /* I/O port for chip configuration */ | ||
118 | int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */ | ||
119 | const char *name; /* name shown as info */ | ||
120 | }; | ||
121 | #endif | ||
122 | |||
103 | struct smsc_transceiver { | 123 | struct smsc_transceiver { |
104 | char *name; | 124 | char *name; |
105 | void (*set_for_speed)(int fir_base, u32 speed); | 125 | void (*set_for_speed)(int fir_base, u32 speed); |
@@ -202,6 +222,16 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor | |||
202 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); | 222 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); |
203 | static int __init smsc_superio_fdc(unsigned short cfg_base); | 223 | static int __init smsc_superio_fdc(unsigned short cfg_base); |
204 | static int __init smsc_superio_lpc(unsigned short cfg_base); | 224 | static int __init smsc_superio_lpc(unsigned short cfg_base); |
225 | #ifdef CONFIG_PCI | ||
226 | static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); | ||
227 | static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
228 | static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
229 | static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, | ||
230 | unsigned short ircc_fir, | ||
231 | unsigned short ircc_sir, | ||
232 | unsigned char ircc_dma, | ||
233 | unsigned char ircc_irq); | ||
234 | #endif | ||
205 | 235 | ||
206 | /* Transceivers specific functions */ | 236 | /* Transceivers specific functions */ |
207 | 237 | ||
@@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void) | |||
353 | return ret; | 383 | return ret; |
354 | } | 384 | } |
355 | 385 | ||
386 | #ifdef CONFIG_PCI | ||
387 | if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { | ||
388 | /* Ignore errors from preconfiguration */ | ||
389 | IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); | ||
390 | } | ||
391 | #endif | ||
392 | |||
356 | dev_count = 0; | 393 | dev_count = 0; |
357 | 394 | ||
358 | if (ircc_fir > 0 && ircc_sir > 0) { | 395 | if (ircc_fir > 0 && ircc_sir > 0) { |
@@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) | |||
2285 | return ret; | 2322 | return ret; |
2286 | } | 2323 | } |
2287 | 2324 | ||
2325 | /* | ||
2326 | * Look for some specific subsystem setups that need | ||
2327 | * pre-configuration not properly done by the BIOS (especially laptops) | ||
2328 | * This code is based in part on smcinit.c, tosh1800-smcinit.c | ||
2329 | * and tosh2450-smcinit.c. The table lists the device entries | ||
2330 | * for ISA bridges with an LPC (Local Peripheral Configurator) | ||
2331 | * that are in turn used to configure the SMSC device with default | ||
2332 | * SIR and FIR I/O ports, DMA and IRQ. | ||
2333 | */ | ||
2334 | #ifdef CONFIG_PCI | ||
2335 | #define PCIID_VENDOR_INTEL 0x8086 | ||
2336 | #define PCIID_VENDOR_ALI 0x10b9 | ||
2337 | static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = { | ||
2338 | { | ||
2339 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ | ||
2340 | .device = 0x24cc, | ||
2341 | .subvendor = 0x103c, | ||
2342 | .subdevice = 0x088c, | ||
2343 | .sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */ | ||
2344 | .fir_io = 0x0130, | ||
2345 | .fir_irq = 0x09, | ||
2346 | .fir_dma = 0x03, | ||
2347 | .cfg_base = 0x004e, | ||
2348 | .preconfigure = preconfigure_through_82801, | ||
2349 | .name = "HP nc8000", | ||
2350 | }, | ||
2351 | { | ||
2352 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ | ||
2353 | .device = 0x24cc, | ||
2354 | .subvendor = 0x103c, | ||
2355 | .subdevice = 0x0890, | ||
2356 | .sir_io = 0x02f8, | ||
2357 | .fir_io = 0x0130, | ||
2358 | .fir_irq = 0x09, | ||
2359 | .fir_dma = 0x03, | ||
2360 | .cfg_base = 0x004e, | ||
2361 | .preconfigure = preconfigure_through_82801, | ||
2362 | .name = "HP nc6000", | ||
2363 | }, | ||
2364 | { | ||
2365 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ | ||
2366 | .device = 0x24c0, | ||
2367 | .subvendor = 0x1179, | ||
2368 | .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ | ||
2369 | .sir_io = 0x03f8, | ||
2370 | .fir_io = 0x0130, | ||
2371 | .fir_irq = 0x07, | ||
2372 | .fir_dma = 0x01, | ||
2373 | .cfg_base = 0x002e, | ||
2374 | .preconfigure = preconfigure_through_82801, | ||
2375 | .name = "Toshiba Satellite 2450", | ||
2376 | }, | ||
2377 | { | ||
2378 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */ | ||
2379 | .device = 0x248c, /* Some use 24cc? */ | ||
2380 | .subvendor = 0x1179, | ||
2381 | .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ | ||
2382 | .sir_io = 0x03f8, | ||
2383 | .fir_io = 0x0130, | ||
2384 | .fir_irq = 0x03, | ||
2385 | .fir_dma = 0x03, | ||
2386 | .cfg_base = 0x002e, | ||
2387 | .preconfigure = preconfigure_through_82801, | ||
2388 | .name = "Toshiba Satellite 5100/5200, Tecra 9100", | ||
2389 | }, | ||
2390 | { | ||
2391 | .vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */ | ||
2392 | .device = 0x1533, | ||
2393 | .subvendor = 0x1179, | ||
2394 | .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ | ||
2395 | .sir_io = 0x02e8, | ||
2396 | .fir_io = 0x02f8, | ||
2397 | .fir_irq = 0x07, | ||
2398 | .fir_dma = 0x03, | ||
2399 | .cfg_base = 0x002e, | ||
2400 | .preconfigure = preconfigure_through_ali, | ||
2401 | .name = "Toshiba Satellite 1800", | ||
2402 | }, | ||
2403 | { } // Terminator | ||
2404 | }; | ||
2405 | |||
2406 | |||
2407 | /* | ||
2408 | * This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ) | ||
2409 | * through the chip configuration port. | ||
2410 | */ | ||
2411 | static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf) | ||
2412 | { | ||
2413 | unsigned short iobase = conf->cfg_base; | ||
2414 | unsigned char tmpbyte; | ||
2415 | |||
2416 | outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state | ||
2417 | outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID | ||
2418 | tmpbyte = inb(iobase +1); // Read device ID | ||
2419 | IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte); | ||
2420 | |||
2421 | /* Disable UART1 and set up SIR I/O port */ | ||
2422 | outb(0x24, iobase); // select CR24 - UART1 base addr | ||
2423 | outb(0x00, iobase + 1); // disable UART1 | ||
2424 | outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr | ||
2425 | outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8 | ||
2426 | tmpbyte = inb(iobase + 1); | ||
2427 | if (tmpbyte != (conf->sir_io >> 2) ) { | ||
2428 | IRDA_WARNING("ERROR: could not configure SIR ioport.\n"); | ||
2429 | return -ENXIO; | ||
2430 | } | ||
2431 | |||
2432 | /* Set up FIR IRQ channel for UART2 */ | ||
2433 | outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select | ||
2434 | tmpbyte = inb(iobase + 1); | ||
2435 | tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion | ||
2436 | tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK); | ||
2437 | outb(tmpbyte, iobase + 1); | ||
2438 | tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; | ||
2439 | if (tmpbyte != conf->fir_irq) { | ||
2440 | IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n"); | ||
2441 | return -ENXIO; | ||
2442 | } | ||
2443 | |||
2444 | /* Set up FIR I/O port */ | ||
2445 | outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr | ||
2446 | outb((conf->fir_io >> 3), iobase + 1); | ||
2447 | tmpbyte = inb(iobase + 1); | ||
2448 | if (tmpbyte != (conf->fir_io >> 3) ) { | ||
2449 | IRDA_WARNING("ERROR: could not configure FIR I/O port.\n"); | ||
2450 | return -ENXIO; | ||
2451 | } | ||
2452 | |||
2453 | /* Set up FIR DMA channel */ | ||
2454 | outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select | ||
2455 | outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA | ||
2456 | tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK; | ||
2457 | if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) { | ||
2458 | IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n"); | ||
2459 | return -ENXIO; | ||
2460 | } | ||
2461 | |||
2462 | outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode | ||
2463 | tmpbyte = inb(iobase + 1); | ||
2464 | tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA; | ||
2465 | outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed | ||
2466 | |||
2467 | outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel | ||
2468 | tmpbyte = inb(iobase + 1); | ||
2469 | outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down | ||
2470 | |||
2471 | /* This one was not part of tosh1800 */ | ||
2472 | outb(0x0a, iobase); // CR0a - ecp fifo / ir mux | ||
2473 | tmpbyte = inb(iobase + 1); | ||
2474 | outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port | ||
2475 | |||
2476 | outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power | ||
2477 | tmpbyte = inb(iobase + 1); | ||
2478 | outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down | ||
2479 | |||
2480 | outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle | ||
2481 | tmpbyte = inb(iobase + 1); | ||
2482 | outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done | ||
2483 | |||
2484 | outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration | ||
2485 | |||
2486 | return 0; | ||
2487 | } | ||
2488 | |||
2489 | /* 82801CAM registers */ | ||
2490 | #define VID 0x00 | ||
2491 | #define DID 0x02 | ||
2492 | #define PIRQA_ROUT 0x60 | ||
2493 | #define PCI_DMA_C 0x90 | ||
2494 | #define COM_DEC 0xe0 | ||
2495 | #define LPC_EN 0xe6 | ||
2496 | #define GEN2_DEC 0xec | ||
2497 | /* | ||
2498 | * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or | ||
2499 | * Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way! | ||
2500 | */ | ||
2501 | static int __init preconfigure_through_82801(struct pci_dev *dev, | ||
2502 | struct smsc_ircc_subsystem_configuration *conf) | ||
2503 | { | ||
2504 | unsigned short tmpword; | ||
2505 | int ret; | ||
2506 | |||
2507 | IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n"); | ||
2508 | pci_write_config_byte(dev, COM_DEC, 0x10); | ||
2509 | |||
2510 | /* Enable LPC */ | ||
2511 | pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ | ||
2512 | tmpword &= 0xfffd; /* mask bit 1 */ | ||
2513 | tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */ | ||
2514 | pci_write_config_word(dev, LPC_EN, tmpword); | ||
2515 | |||
2516 | /* Setup DMA */ | ||
2517 | pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */ | ||
2518 | pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */ | ||
2519 | |||
2520 | /* Pre-configure chip */ | ||
2521 | ret = preconfigure_smsc_chip(conf); | ||
2522 | |||
2523 | /* Disable LPC */ | ||
2524 | pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ | ||
2525 | tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */ | ||
2526 | pci_write_config_word(dev, LPC_EN, tmpword); | ||
2527 | return ret; | ||
2528 | } | ||
2529 | |||
2530 | static int __init preconfigure_through_ali(struct pci_dev *dev, | ||
2531 | struct smsc_ircc_subsystem_configuration *conf) | ||
2532 | { | ||
2533 | /* TODO: put in ALi 1533 configuration here. */ | ||
2534 | IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name); | ||
2535 | return -ENODEV; | ||
2536 | } | ||
2537 | |||
2538 | static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, | ||
2539 | unsigned short ircc_fir, | ||
2540 | unsigned short ircc_sir, | ||
2541 | unsigned char ircc_dma, | ||
2542 | unsigned char ircc_irq) | ||
2543 | { | ||
2544 | struct pci_dev *dev = NULL; | ||
2545 | unsigned short ss_vendor = 0x0000; | ||
2546 | unsigned short ss_device = 0x0000; | ||
2547 | int ret = 0; | ||
2548 | |||
2549 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
2550 | |||
2551 | while (dev != NULL) { | ||
2552 | struct smsc_ircc_subsystem_configuration *conf; | ||
2553 | |||
2554 | /* | ||
2555 | * Cache the subsystem vendor/device: some manufacturers fail to set | ||
2556 | * this for all components, so we save it in case there is just | ||
2557 | * 0x0000 0x0000 on the device we want to check. | ||
2558 | */ | ||
2559 | if (dev->subsystem_vendor != 0x0000U) { | ||
2560 | ss_vendor = dev->subsystem_vendor; | ||
2561 | ss_device = dev->subsystem_device; | ||
2562 | } | ||
2563 | conf = subsystem_configurations; | ||
2564 | for( ; conf->subvendor; conf++) { | ||
2565 | if(conf->vendor == dev->vendor && | ||
2566 | conf->device == dev->device && | ||
2567 | conf->subvendor == ss_vendor && /* Sometimes these are cached values */ | ||
2568 | (conf->subdevice == ss_device || conf->subdevice == 0xffff)) { | ||
2569 | struct smsc_ircc_subsystem_configuration tmpconf; | ||
2570 | |||
2571 | memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration)); | ||
2572 | |||
2573 | /* Override the default values with anything passed in as parameter */ | ||
2574 | if (ircc_cfg != 0) | ||
2575 | tmpconf.cfg_base = ircc_cfg; | ||
2576 | if (ircc_fir != 0) | ||
2577 | tmpconf.fir_io = ircc_fir; | ||
2578 | if (ircc_sir != 0) | ||
2579 | tmpconf.sir_io = ircc_sir; | ||
2580 | if (ircc_dma != 0xff) | ||
2581 | tmpconf.fir_dma = ircc_dma; | ||
2582 | if (ircc_irq != 0xff) | ||
2583 | tmpconf.fir_irq = ircc_irq; | ||
2584 | |||
2585 | IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); | ||
2586 | if (conf->preconfigure) | ||
2587 | ret = conf->preconfigure(dev, &tmpconf); | ||
2588 | else | ||
2589 | ret = -ENODEV; | ||
2590 | } | ||
2591 | } | ||
2592 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
2593 | } | ||
2594 | |||
2595 | return ret; | ||
2596 | } | ||
2597 | #endif // CONFIG_PCI | ||
2598 | |||
2288 | /************************************************ | 2599 | /************************************************ |
2289 | * | 2600 | * |
2290 | * Transceivers specific functions | 2601 | * Transceivers specific functions |
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 75b35ad760de..66e74f740261 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len) | |||
87 | } | 87 | } |
88 | 88 | ||
89 | static struct console netconsole = { | 89 | static struct console netconsole = { |
90 | .name = "netcon", | ||
90 | .flags = CON_ENABLED | CON_PRINTBUFFER, | 91 | .flags = CON_ENABLED | CON_PRINTBUFFER, |
91 | .write = write_msg | 92 | .write = write_msg |
92 | }; | 93 | }; |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0b5358072172..73e271e59c6a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) | |||
497 | unsigned long flags; | 497 | unsigned long flags; |
498 | 498 | ||
499 | spin_lock_irqsave(&tp->indirect_lock, flags); | 499 | spin_lock_irqsave(&tp->indirect_lock, flags); |
500 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 500 | if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { |
501 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 501 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
502 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | ||
502 | 503 | ||
503 | /* Always leave this as zero. */ | 504 | /* Always leave this as zero. */ |
504 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 505 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
505 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | 506 | } else { |
506 | } | 507 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); |
508 | tw32_f(TG3PCI_MEM_WIN_DATA, val); | ||
507 | 509 | ||
508 | static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) | 510 | /* Always leave this as zero. */ |
509 | { | 511 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); |
510 | /* If no workaround is needed, write to mem space directly */ | 512 | } |
511 | if (tp->write32 != tg3_write_indirect_reg32) | 513 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
512 | tw32(NIC_SRAM_WIN_BASE + off, val); | ||
513 | else | ||
514 | tg3_write_mem(tp, off, val); | ||
515 | } | 514 | } |
516 | 515 | ||
517 | static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | 516 | static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) |
@@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | |||
519 | unsigned long flags; | 518 | unsigned long flags; |
520 | 519 | ||
521 | spin_lock_irqsave(&tp->indirect_lock, flags); | 520 | spin_lock_irqsave(&tp->indirect_lock, flags); |
522 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 521 | if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { |
523 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 522 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
523 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | ||
524 | 524 | ||
525 | /* Always leave this as zero. */ | 525 | /* Always leave this as zero. */ |
526 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 526 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
527 | } else { | ||
528 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); | ||
529 | *val = tr32(TG3PCI_MEM_WIN_DATA); | ||
530 | |||
531 | /* Always leave this as zero. */ | ||
532 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); | ||
533 | } | ||
527 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | 534 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
528 | } | 535 | } |
529 | 536 | ||
@@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
1367 | } | 1374 | } |
1368 | } | 1375 | } |
1369 | 1376 | ||
1377 | tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); | ||
1378 | |||
1370 | /* Finally, set the new power state. */ | 1379 | /* Finally, set the new power state. */ |
1371 | pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); | 1380 | pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); |
1372 | udelay(100); /* Delay after power state change */ | 1381 | udelay(100); /* Delay after power state change */ |
1373 | 1382 | ||
1374 | tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); | ||
1375 | |||
1376 | return 0; | 1383 | return 0; |
1377 | } | 1384 | } |
1378 | 1385 | ||
@@ -5828,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp) | |||
5828 | GRC_MODE_NO_TX_PHDR_CSUM | | 5835 | GRC_MODE_NO_TX_PHDR_CSUM | |
5829 | GRC_MODE_NO_RX_PHDR_CSUM); | 5836 | GRC_MODE_NO_RX_PHDR_CSUM); |
5830 | tp->grc_mode |= GRC_MODE_HOST_SENDBDS; | 5837 | tp->grc_mode |= GRC_MODE_HOST_SENDBDS; |
5831 | if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) | 5838 | |
5832 | tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; | 5839 | /* Pseudo-header checksum is done by hardware logic and not |
5833 | if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) | 5840 | * the offload processers, so make the chip do the pseudo- |
5834 | tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; | 5841 | * header checksums on receive. For transmit it is more |
5842 | * convenient to do the pseudo-header checksum in software | ||
5843 | * as Linux does that on transmit for us in all cases. | ||
5844 | */ | ||
5845 | tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; | ||
5835 | 5846 | ||
5836 | tw32(GRC_MODE, | 5847 | tw32(GRC_MODE, |
5837 | tp->grc_mode | | 5848 | tp->grc_mode | |
@@ -6535,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque) | |||
6535 | if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { | 6546 | if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { |
6536 | u32 val; | 6547 | u32 val; |
6537 | 6548 | ||
6538 | tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, | 6549 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, |
6539 | FWCMD_NICDRV_ALIVE2); | 6550 | FWCMD_NICDRV_ALIVE2); |
6540 | tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); | 6551 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); |
6541 | /* 5 seconds timeout */ | 6552 | /* 5 seconds timeout */ |
6542 | tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); | 6553 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); |
6543 | val = tr32(GRC_RX_CPU_EVENT); | 6554 | val = tr32(GRC_RX_CPU_EVENT); |
6544 | val |= (1 << 14); | 6555 | val |= (1 << 14); |
6545 | tw32(GRC_RX_CPU_EVENT, val); | 6556 | tw32(GRC_RX_CPU_EVENT, val); |
@@ -8034,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp) | |||
8034 | for (i = 0; i < size; i++) | 8045 | for (i = 0; i < size; i++) |
8035 | csum8 += buf8[i]; | 8046 | csum8 += buf8[i]; |
8036 | 8047 | ||
8037 | if (csum8 == 0) | 8048 | if (csum8 == 0) { |
8038 | return 0; | 8049 | err = 0; |
8039 | return -EIO; | 8050 | goto out; |
8051 | } | ||
8052 | |||
8053 | err = -EIO; | ||
8054 | goto out; | ||
8040 | } | 8055 | } |
8041 | 8056 | ||
8042 | /* Bootstrap checksum at offset 0x10 */ | 8057 | /* Bootstrap checksum at offset 0x10 */ |
@@ -9531,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) | |||
9531 | tp->led_ctrl = LED_CTRL_MODE_PHY_1; | 9546 | tp->led_ctrl = LED_CTRL_MODE_PHY_1; |
9532 | 9547 | ||
9533 | /* Do not even try poking around in here on Sun parts. */ | 9548 | /* Do not even try poking around in here on Sun parts. */ |
9534 | if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) | 9549 | if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { |
9550 | /* All SUN chips are built-in LOMs. */ | ||
9551 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; | ||
9535 | return; | 9552 | return; |
9553 | } | ||
9536 | 9554 | ||
9537 | tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); | 9555 | tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); |
9538 | if (val == NIC_SRAM_DATA_SIG_MAGIC) { | 9556 | if (val == NIC_SRAM_DATA_SIG_MAGIC) { |
@@ -9630,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) | |||
9630 | tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) | 9648 | tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) |
9631 | tp->led_ctrl = LED_CTRL_MODE_PHY_2; | 9649 | tp->led_ctrl = LED_CTRL_MODE_PHY_2; |
9632 | 9650 | ||
9633 | if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && | 9651 | if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) |
9634 | (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && | ||
9635 | (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) | ||
9636 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; | 9652 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; |
9637 | 9653 | ||
9638 | if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { | 9654 | if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { |
@@ -10257,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10257 | pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); | 10273 | pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); |
10258 | } | 10274 | } |
10259 | 10275 | ||
10276 | if (tp->write32 == tg3_write_indirect_reg32 || | ||
10277 | ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && | ||
10278 | (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || | ||
10279 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) || | ||
10280 | (tp->tg3_flags2 & TG3_FLG2_SUN_570X)) | ||
10281 | tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; | ||
10282 | |||
10260 | /* Get eeprom hw config before calling tg3_set_power_state(). | 10283 | /* Get eeprom hw config before calling tg3_set_power_state(). |
10261 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be | 10284 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be |
10262 | * determined before calling tg3_set_power_state() so that | 10285 | * determined before calling tg3_set_power_state() so that |
@@ -10299,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10299 | if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) | 10322 | if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) |
10300 | tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; | 10323 | tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; |
10301 | 10324 | ||
10302 | /* Pseudo-header checksum is done by hardware logic and not | ||
10303 | * the offload processers, so make the chip do the pseudo- | ||
10304 | * header checksums on receive. For transmit it is more | ||
10305 | * convenient to do the pseudo-header checksum in software | ||
10306 | * as Linux does that on transmit for us in all cases. | ||
10307 | */ | ||
10308 | tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM; | ||
10309 | tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM; | ||
10310 | |||
10311 | /* Derive initial jumbo mode from MTU assigned in | 10325 | /* Derive initial jumbo mode from MTU assigned in |
10312 | * ether_setup() via the alloc_etherdev() call | 10326 | * ether_setup() via the alloc_etherdev() call |
10313 | */ | 10327 | */ |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c43cc3264202..8c8b987d1250 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2171,8 +2171,7 @@ struct tg3 { | |||
2171 | #define TG3_FLAG_PCIX_MODE 0x00020000 | 2171 | #define TG3_FLAG_PCIX_MODE 0x00020000 |
2172 | #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 | 2172 | #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 |
2173 | #define TG3_FLAG_PCI_32BIT 0x00080000 | 2173 | #define TG3_FLAG_PCI_32BIT 0x00080000 |
2174 | #define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 | 2174 | #define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 |
2175 | #define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 | ||
2176 | #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 | 2175 | #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 |
2177 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 | 2176 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 |
2178 | #define TG3_FLAG_10_100_ONLY 0x01000000 | 2177 | #define TG3_FLAG_10_100_ONLY 0x01000000 |
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1bd82c4e52a0..b4f8fb1d628b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
@@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = { | |||
207 | .name = DRV_NAME, | 207 | .name = DRV_NAME, |
208 | .ioctl = ata_scsi_ioctl, | 208 | .ioctl = ata_scsi_ioctl, |
209 | .queuecommand = ata_scsi_queuecmd, | 209 | .queuecommand = ata_scsi_queuecmd, |
210 | .eh_strategy_handler = ata_scsi_error, | ||
211 | .can_queue = ATA_DEF_QUEUE, | 210 | .can_queue = ATA_DEF_QUEUE, |
212 | .this_id = ATA_SHT_THIS_ID, | 211 | .this_id = ATA_SHT_THIS_ID, |
213 | .sg_tablesize = AHCI_MAX_SG, | 212 | .sg_tablesize = AHCI_MAX_SG, |
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 24e71b555172..6dc88149f9f1 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = { | |||
209 | .name = DRV_NAME, | 209 | .name = DRV_NAME, |
210 | .ioctl = ata_scsi_ioctl, | 210 | .ioctl = ata_scsi_ioctl, |
211 | .queuecommand = ata_scsi_queuecmd, | 211 | .queuecommand = ata_scsi_queuecmd, |
212 | .eh_strategy_handler = ata_scsi_error, | ||
213 | .can_queue = ATA_DEF_QUEUE, | 212 | .can_queue = ATA_DEF_QUEUE, |
214 | .this_id = ATA_SHT_THIS_ID, | 213 | .this_id = ATA_SHT_THIS_ID, |
215 | .sg_tablesize = LIBATA_MAX_PRD, | 214 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index ef57f253031c..dfcb96f3e60c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -294,18 +294,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
294 | if (sht->unchecked_isa_dma && privsize) | 294 | if (sht->unchecked_isa_dma && privsize) |
295 | gfp_mask |= __GFP_DMA; | 295 | gfp_mask |= __GFP_DMA; |
296 | 296 | ||
297 | /* Check to see if this host has any error handling facilities */ | ||
298 | if (!sht->eh_strategy_handler && !sht->eh_abort_handler && | ||
299 | !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler && | ||
300 | !sht->eh_host_reset_handler) { | ||
301 | printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n" | ||
302 | "ERROR: This is not a safe way to run your " | ||
303 | "SCSI host\n" | ||
304 | "ERROR: The error handling must be added to " | ||
305 | "this driver\n", sht->proc_name); | ||
306 | dump_stack(); | ||
307 | } | ||
308 | |||
309 | shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); | 297 | shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); |
310 | if (!shost) | 298 | if (!shost) |
311 | return NULL; | 299 | return NULL; |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e63c1ff1e102..bd147207f25d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -4938,7 +4938,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); | |||
4938 | EXPORT_SYMBOL_GPL(ata_port_queue_task); | 4938 | EXPORT_SYMBOL_GPL(ata_port_queue_task); |
4939 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); | 4939 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); |
4940 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); | 4940 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); |
4941 | EXPORT_SYMBOL_GPL(ata_scsi_error); | ||
4942 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); | 4941 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); |
4943 | EXPORT_SYMBOL_GPL(ata_scsi_release); | 4942 | EXPORT_SYMBOL_GPL(ata_scsi_release); |
4944 | EXPORT_SYMBOL_GPL(ata_host_intr); | 4943 | EXPORT_SYMBOL_GPL(ata_host_intr); |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 53f5b0d9161c..a0289ec3e283 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -53,6 +53,7 @@ | |||
53 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); | 53 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); |
54 | static struct ata_device * | 54 | static struct ata_device * |
55 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); | 55 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); |
56 | static void ata_scsi_error(struct Scsi_Host *host); | ||
56 | enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | 57 | enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); |
57 | 58 | ||
58 | #define RW_RECOVERY_MPAGE 0x1 | 59 | #define RW_RECOVERY_MPAGE 0x1 |
@@ -99,6 +100,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { | |||
99 | * It just needs the eh_timed_out hook. | 100 | * It just needs the eh_timed_out hook. |
100 | */ | 101 | */ |
101 | struct scsi_transport_template ata_scsi_transport_template = { | 102 | struct scsi_transport_template ata_scsi_transport_template = { |
103 | .eh_strategy_handler = ata_scsi_error, | ||
102 | .eh_timed_out = ata_scsi_timed_out, | 104 | .eh_timed_out = ata_scsi_timed_out, |
103 | }; | 105 | }; |
104 | 106 | ||
@@ -772,12 +774,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) | |||
772 | * | 774 | * |
773 | * LOCKING: | 775 | * LOCKING: |
774 | * Inherited from SCSI layer (none, can sleep) | 776 | * Inherited from SCSI layer (none, can sleep) |
775 | * | ||
776 | * RETURNS: | ||
777 | * Zero. | ||
778 | */ | 777 | */ |
779 | 778 | ||
780 | int ata_scsi_error(struct Scsi_Host *host) | 779 | static void ata_scsi_error(struct Scsi_Host *host) |
781 | { | 780 | { |
782 | struct ata_port *ap; | 781 | struct ata_port *ap; |
783 | unsigned long flags; | 782 | unsigned long flags; |
@@ -805,7 +804,6 @@ int ata_scsi_error(struct Scsi_Host *host) | |||
805 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | 804 | spin_unlock_irqrestore(&ap->host_set->lock, flags); |
806 | 805 | ||
807 | DPRINTK("EXIT\n"); | 806 | DPRINTK("EXIT\n"); |
808 | return 0; | ||
809 | } | 807 | } |
810 | 808 | ||
811 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) | 809 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) |
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1c755b14521a..bac8cbae06fe 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
@@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); | |||
60 | extern struct scsi_transport_template ata_scsi_transport_template; | 60 | extern struct scsi_transport_template ata_scsi_transport_template; |
61 | 61 | ||
62 | extern void ata_scsi_scan_host(struct ata_port *ap); | 62 | extern void ata_scsi_scan_host(struct ata_port *ap); |
63 | extern int ata_scsi_error(struct Scsi_Host *host); | ||
64 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, | 63 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, |
65 | unsigned int buflen); | 64 | unsigned int buflen); |
66 | 65 | ||
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 3c85c4b66e19..5cda16cfacb0 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c | |||
@@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = { | |||
143 | .name = DRV_NAME, | 143 | .name = DRV_NAME, |
144 | .ioctl = ata_scsi_ioctl, | 144 | .ioctl = ata_scsi_ioctl, |
145 | .queuecommand = ata_scsi_queuecmd, | 145 | .queuecommand = ata_scsi_queuecmd, |
146 | .eh_strategy_handler = ata_scsi_error, | ||
147 | .can_queue = ATA_DEF_QUEUE, | 146 | .can_queue = ATA_DEF_QUEUE, |
148 | .this_id = ATA_SHT_THIS_ID, | 147 | .this_id = ATA_SHT_THIS_ID, |
149 | .sg_tablesize = LIBATA_MAX_PRD, | 148 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index fa901fd65085..b64b077573c2 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = { | |||
378 | .name = DRV_NAME, | 378 | .name = DRV_NAME, |
379 | .ioctl = ata_scsi_ioctl, | 379 | .ioctl = ata_scsi_ioctl, |
380 | .queuecommand = ata_scsi_queuecmd, | 380 | .queuecommand = ata_scsi_queuecmd, |
381 | .eh_strategy_handler = ata_scsi_error, | ||
382 | .can_queue = MV_USE_Q_DEPTH, | 381 | .can_queue = MV_USE_Q_DEPTH, |
383 | .this_id = ATA_SHT_THIS_ID, | 382 | .this_id = ATA_SHT_THIS_ID, |
384 | .sg_tablesize = MV_MAX_SG_CT / 2, | 383 | .sg_tablesize = MV_MAX_SG_CT / 2, |
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index f77bf183dfab..9f553081b5e8 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c | |||
@@ -201,7 +201,6 @@ static struct scsi_host_template nv_sht = { | |||
201 | .name = DRV_NAME, | 201 | .name = DRV_NAME, |
202 | .ioctl = ata_scsi_ioctl, | 202 | .ioctl = ata_scsi_ioctl, |
203 | .queuecommand = ata_scsi_queuecmd, | 203 | .queuecommand = ata_scsi_queuecmd, |
204 | .eh_strategy_handler = ata_scsi_error, | ||
205 | .can_queue = ATA_DEF_QUEUE, | 204 | .can_queue = ATA_DEF_QUEUE, |
206 | .this_id = ATA_SHT_THIS_ID, | 205 | .this_id = ATA_SHT_THIS_ID, |
207 | .sg_tablesize = LIBATA_MAX_PRD, | 206 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index cc928c68a479..7eb67a6bdc64 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c | |||
@@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = { | |||
111 | .name = DRV_NAME, | 111 | .name = DRV_NAME, |
112 | .ioctl = ata_scsi_ioctl, | 112 | .ioctl = ata_scsi_ioctl, |
113 | .queuecommand = ata_scsi_queuecmd, | 113 | .queuecommand = ata_scsi_queuecmd, |
114 | .eh_strategy_handler = ata_scsi_error, | ||
115 | .can_queue = ATA_DEF_QUEUE, | 114 | .can_queue = ATA_DEF_QUEUE, |
116 | .this_id = ATA_SHT_THIS_ID, | 115 | .this_id = ATA_SHT_THIS_ID, |
117 | .sg_tablesize = LIBATA_MAX_PRD, | 116 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9ffe1ef0d205..886f3447dd48 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c | |||
@@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = { | |||
132 | .name = DRV_NAME, | 132 | .name = DRV_NAME, |
133 | .ioctl = ata_scsi_ioctl, | 133 | .ioctl = ata_scsi_ioctl, |
134 | .queuecommand = ata_scsi_queuecmd, | 134 | .queuecommand = ata_scsi_queuecmd, |
135 | .eh_strategy_handler = ata_scsi_error, | ||
136 | .can_queue = ATA_DEF_QUEUE, | 135 | .can_queue = ATA_DEF_QUEUE, |
137 | .this_id = ATA_SHT_THIS_ID, | 136 | .this_id = ATA_SHT_THIS_ID, |
138 | .sg_tablesize = QS_MAX_PRD, | 137 | .sg_tablesize = QS_MAX_PRD, |
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 18c296c56899..106627299d55 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c | |||
@@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = { | |||
146 | .name = DRV_NAME, | 146 | .name = DRV_NAME, |
147 | .ioctl = ata_scsi_ioctl, | 147 | .ioctl = ata_scsi_ioctl, |
148 | .queuecommand = ata_scsi_queuecmd, | 148 | .queuecommand = ata_scsi_queuecmd, |
149 | .eh_strategy_handler = ata_scsi_error, | ||
150 | .can_queue = ATA_DEF_QUEUE, | 149 | .can_queue = ATA_DEF_QUEUE, |
151 | .this_id = ATA_SHT_THIS_ID, | 150 | .this_id = ATA_SHT_THIS_ID, |
152 | .sg_tablesize = LIBATA_MAX_PRD, | 151 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 068c98a4111b..f7264fd611c2 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = { | |||
281 | .name = DRV_NAME, | 281 | .name = DRV_NAME, |
282 | .ioctl = ata_scsi_ioctl, | 282 | .ioctl = ata_scsi_ioctl, |
283 | .queuecommand = ata_scsi_queuecmd, | 283 | .queuecommand = ata_scsi_queuecmd, |
284 | .eh_strategy_handler = ata_scsi_error, | ||
285 | .can_queue = ATA_DEF_QUEUE, | 284 | .can_queue = ATA_DEF_QUEUE, |
286 | .this_id = ATA_SHT_THIS_ID, | 285 | .this_id = ATA_SHT_THIS_ID, |
287 | .sg_tablesize = LIBATA_MAX_PRD, | 286 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index acc8439dea23..728530df2e07 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c | |||
@@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = { | |||
87 | .name = DRV_NAME, | 87 | .name = DRV_NAME, |
88 | .ioctl = ata_scsi_ioctl, | 88 | .ioctl = ata_scsi_ioctl, |
89 | .queuecommand = ata_scsi_queuecmd, | 89 | .queuecommand = ata_scsi_queuecmd, |
90 | .eh_strategy_handler = ata_scsi_error, | ||
91 | .can_queue = ATA_DEF_QUEUE, | 90 | .can_queue = ATA_DEF_QUEUE, |
92 | .this_id = ATA_SHT_THIS_ID, | 91 | .this_id = ATA_SHT_THIS_ID, |
93 | .sg_tablesize = ATA_MAX_PRD, | 92 | .sg_tablesize = ATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 724f0ed6a52d..53b0d5c0a61f 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c | |||
@@ -290,7 +290,6 @@ static struct scsi_host_template k2_sata_sht = { | |||
290 | .name = DRV_NAME, | 290 | .name = DRV_NAME, |
291 | .ioctl = ata_scsi_ioctl, | 291 | .ioctl = ata_scsi_ioctl, |
292 | .queuecommand = ata_scsi_queuecmd, | 292 | .queuecommand = ata_scsi_queuecmd, |
293 | .eh_strategy_handler = ata_scsi_error, | ||
294 | .can_queue = ATA_DEF_QUEUE, | 293 | .can_queue = ATA_DEF_QUEUE, |
295 | .this_id = ATA_SHT_THIS_ID, | 294 | .this_id = ATA_SHT_THIS_ID, |
296 | .sg_tablesize = LIBATA_MAX_PRD, | 295 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index ae70f60c7c0d..4139ad4b1df0 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c | |||
@@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = { | |||
182 | .name = DRV_NAME, | 182 | .name = DRV_NAME, |
183 | .ioctl = ata_scsi_ioctl, | 183 | .ioctl = ata_scsi_ioctl, |
184 | .queuecommand = ata_scsi_queuecmd, | 184 | .queuecommand = ata_scsi_queuecmd, |
185 | .eh_strategy_handler = ata_scsi_error, | ||
186 | .can_queue = ATA_DEF_QUEUE, | 185 | .can_queue = ATA_DEF_QUEUE, |
187 | .this_id = ATA_SHT_THIS_ID, | 186 | .this_id = ATA_SHT_THIS_ID, |
188 | .sg_tablesize = LIBATA_MAX_PRD, | 187 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 7ac5a5f5a905..38b52bd3fa3f 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c | |||
@@ -81,7 +81,6 @@ static struct scsi_host_template uli_sht = { | |||
81 | .name = DRV_NAME, | 81 | .name = DRV_NAME, |
82 | .ioctl = ata_scsi_ioctl, | 82 | .ioctl = ata_scsi_ioctl, |
83 | .queuecommand = ata_scsi_queuecmd, | 83 | .queuecommand = ata_scsi_queuecmd, |
84 | .eh_strategy_handler = ata_scsi_error, | ||
85 | .can_queue = ATA_DEF_QUEUE, | 84 | .can_queue = ATA_DEF_QUEUE, |
86 | .this_id = ATA_SHT_THIS_ID, | 85 | .this_id = ATA_SHT_THIS_ID, |
87 | .sg_tablesize = LIBATA_MAX_PRD, | 86 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 791bf652ba63..9e7ae4e0db32 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c | |||
@@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = { | |||
94 | .name = DRV_NAME, | 94 | .name = DRV_NAME, |
95 | .ioctl = ata_scsi_ioctl, | 95 | .ioctl = ata_scsi_ioctl, |
96 | .queuecommand = ata_scsi_queuecmd, | 96 | .queuecommand = ata_scsi_queuecmd, |
97 | .eh_strategy_handler = ata_scsi_error, | ||
98 | .can_queue = ATA_DEF_QUEUE, | 97 | .can_queue = ATA_DEF_QUEUE, |
99 | .this_id = ATA_SHT_THIS_ID, | 98 | .this_id = ATA_SHT_THIS_ID, |
100 | .sg_tablesize = LIBATA_MAX_PRD, | 99 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 836bbbb26ff2..8a29ce340b47 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c | |||
@@ -263,7 +263,6 @@ static struct scsi_host_template vsc_sata_sht = { | |||
263 | .name = DRV_NAME, | 263 | .name = DRV_NAME, |
264 | .ioctl = ata_scsi_ioctl, | 264 | .ioctl = ata_scsi_ioctl, |
265 | .queuecommand = ata_scsi_queuecmd, | 265 | .queuecommand = ata_scsi_queuecmd, |
266 | .eh_strategy_handler = ata_scsi_error, | ||
267 | .can_queue = ATA_DEF_QUEUE, | 266 | .can_queue = ATA_DEF_QUEUE, |
268 | .this_id = ATA_SHT_THIS_ID, | 267 | .this_id = ATA_SHT_THIS_ID, |
269 | .sg_tablesize = LIBATA_MAX_PRD, | 268 | .sg_tablesize = LIBATA_MAX_PRD, |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5f0fdfb2618c..1c75646f9689 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1537,8 +1537,8 @@ int scsi_error_handler(void *data) | |||
1537 | * what we need to do to get it up and online again (if we can). | 1537 | * what we need to do to get it up and online again (if we can). |
1538 | * If we fail, we end up taking the thing offline. | 1538 | * If we fail, we end up taking the thing offline. |
1539 | */ | 1539 | */ |
1540 | if (shost->hostt->eh_strategy_handler) | 1540 | if (shost->transportt->eh_strategy_handler) |
1541 | shost->hostt->eh_strategy_handler(shost); | 1541 | shost->transportt->eh_strategy_handler(shost); |
1542 | else | 1542 | else |
1543 | scsi_unjam_host(shost); | 1543 | scsi_unjam_host(shost); |
1544 | 1544 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index e207be68d4ca..97f317413122 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -861,7 +861,7 @@ config RAMFS | |||
861 | 861 | ||
862 | config CONFIGFS_FS | 862 | config CONFIGFS_FS |
863 | tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" | 863 | tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" |
864 | depends on EXPERIMENTAL | 864 | depends on SYSFS && EXPERIMENTAL |
865 | help | 865 | help |
866 | configfs is a ram-based filesystem that provides the converse | 866 | configfs is a ram-based filesystem that provides the converse |
867 | of sysfs's functionality. Where sysfs is a filesystem-based | 867 | of sysfs's functionality. Where sysfs is a filesystem-based |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8ed9b06a9828..5638c8f9362f 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -504,7 +504,7 @@ static int populate_groups(struct config_group *group) | |||
504 | int ret = 0; | 504 | int ret = 0; |
505 | int i; | 505 | int i; |
506 | 506 | ||
507 | if (group && group->default_groups) { | 507 | if (group->default_groups) { |
508 | /* FYI, we're faking mkdir here | 508 | /* FYI, we're faking mkdir here |
509 | * I'm not sure we need this semaphore, as we're called | 509 | * I'm not sure we need this semaphore, as we're called |
510 | * from our parent's mkdir. That holds our parent's | 510 | * from our parent's mkdir. That holds our parent's |
@@ -723,7 +723,12 @@ static int de_thread(struct task_struct *tsk) | |||
723 | current->parent = current->real_parent = leader->real_parent; | 723 | current->parent = current->real_parent = leader->real_parent; |
724 | leader->parent = leader->real_parent = child_reaper; | 724 | leader->parent = leader->real_parent = child_reaper; |
725 | current->group_leader = current; | 725 | current->group_leader = current; |
726 | leader->group_leader = leader; | 726 | leader->group_leader = current; |
727 | |||
728 | /* Reduce leader to a thread */ | ||
729 | detach_pid(leader, PIDTYPE_PGID); | ||
730 | detach_pid(leader, PIDTYPE_SID); | ||
731 | list_del_init(&leader->tasks); | ||
727 | 732 | ||
728 | add_parent(current); | 733 | add_parent(current); |
729 | add_parent(leader); | 734 | add_parent(leader); |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index bff0f0d06867..21f38accd039 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -153,6 +153,7 @@ struct o2hb_region { | |||
153 | struct o2hb_bio_wait_ctxt { | 153 | struct o2hb_bio_wait_ctxt { |
154 | atomic_t wc_num_reqs; | 154 | atomic_t wc_num_reqs; |
155 | struct completion wc_io_complete; | 155 | struct completion wc_io_complete; |
156 | int wc_error; | ||
156 | }; | 157 | }; |
157 | 158 | ||
158 | static void o2hb_write_timeout(void *arg) | 159 | static void o2hb_write_timeout(void *arg) |
@@ -186,6 +187,7 @@ static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc, | |||
186 | { | 187 | { |
187 | atomic_set(&wc->wc_num_reqs, num_ios); | 188 | atomic_set(&wc->wc_num_reqs, num_ios); |
188 | init_completion(&wc->wc_io_complete); | 189 | init_completion(&wc->wc_io_complete); |
190 | wc->wc_error = 0; | ||
189 | } | 191 | } |
190 | 192 | ||
191 | /* Used in error paths too */ | 193 | /* Used in error paths too */ |
@@ -218,8 +220,10 @@ static int o2hb_bio_end_io(struct bio *bio, | |||
218 | { | 220 | { |
219 | struct o2hb_bio_wait_ctxt *wc = bio->bi_private; | 221 | struct o2hb_bio_wait_ctxt *wc = bio->bi_private; |
220 | 222 | ||
221 | if (error) | 223 | if (error) { |
222 | mlog(ML_ERROR, "IO Error %d\n", error); | 224 | mlog(ML_ERROR, "IO Error %d\n", error); |
225 | wc->wc_error = error; | ||
226 | } | ||
223 | 227 | ||
224 | if (bio->bi_size) | 228 | if (bio->bi_size) |
225 | return 1; | 229 | return 1; |
@@ -390,6 +394,8 @@ static int o2hb_read_slots(struct o2hb_region *reg, | |||
390 | 394 | ||
391 | bail_and_wait: | 395 | bail_and_wait: |
392 | o2hb_wait_on_io(reg, &wc); | 396 | o2hb_wait_on_io(reg, &wc); |
397 | if (wc.wc_error && !status) | ||
398 | status = wc.wc_error; | ||
393 | 399 | ||
394 | if (bios) { | 400 | if (bios) { |
395 | for(i = 0; i < num_bios; i++) | 401 | for(i = 0; i < num_bios; i++) |
@@ -790,20 +796,24 @@ static int o2hb_highest_node(unsigned long *nodes, | |||
790 | return highest; | 796 | return highest; |
791 | } | 797 | } |
792 | 798 | ||
793 | static void o2hb_do_disk_heartbeat(struct o2hb_region *reg) | 799 | static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) |
794 | { | 800 | { |
795 | int i, ret, highest_node, change = 0; | 801 | int i, ret, highest_node, change = 0; |
796 | unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)]; | 802 | unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)]; |
797 | struct bio *write_bio; | 803 | struct bio *write_bio; |
798 | struct o2hb_bio_wait_ctxt write_wc; | 804 | struct o2hb_bio_wait_ctxt write_wc; |
799 | 805 | ||
800 | if (o2nm_configured_node_map(configured_nodes, sizeof(configured_nodes))) | 806 | ret = o2nm_configured_node_map(configured_nodes, |
801 | return; | 807 | sizeof(configured_nodes)); |
808 | if (ret) { | ||
809 | mlog_errno(ret); | ||
810 | return ret; | ||
811 | } | ||
802 | 812 | ||
803 | highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES); | 813 | highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES); |
804 | if (highest_node >= O2NM_MAX_NODES) { | 814 | if (highest_node >= O2NM_MAX_NODES) { |
805 | mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n"); | 815 | mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n"); |
806 | return; | 816 | return -EINVAL; |
807 | } | 817 | } |
808 | 818 | ||
809 | /* No sense in reading the slots of nodes that don't exist | 819 | /* No sense in reading the slots of nodes that don't exist |
@@ -813,7 +823,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
813 | ret = o2hb_read_slots(reg, highest_node + 1); | 823 | ret = o2hb_read_slots(reg, highest_node + 1); |
814 | if (ret < 0) { | 824 | if (ret < 0) { |
815 | mlog_errno(ret); | 825 | mlog_errno(ret); |
816 | return; | 826 | return ret; |
817 | } | 827 | } |
818 | 828 | ||
819 | /* With an up to date view of the slots, we can check that no | 829 | /* With an up to date view of the slots, we can check that no |
@@ -831,7 +841,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
831 | ret = o2hb_issue_node_write(reg, &write_bio, &write_wc); | 841 | ret = o2hb_issue_node_write(reg, &write_bio, &write_wc); |
832 | if (ret < 0) { | 842 | if (ret < 0) { |
833 | mlog_errno(ret); | 843 | mlog_errno(ret); |
834 | return; | 844 | return ret; |
835 | } | 845 | } |
836 | 846 | ||
837 | i = -1; | 847 | i = -1; |
@@ -847,6 +857,15 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
847 | */ | 857 | */ |
848 | o2hb_wait_on_io(reg, &write_wc); | 858 | o2hb_wait_on_io(reg, &write_wc); |
849 | bio_put(write_bio); | 859 | bio_put(write_bio); |
860 | if (write_wc.wc_error) { | ||
861 | /* Do not re-arm the write timeout on I/O error - we | ||
862 | * can't be sure that the new block ever made it to | ||
863 | * disk */ | ||
864 | mlog(ML_ERROR, "Write error %d on device \"%s\"\n", | ||
865 | write_wc.wc_error, reg->hr_dev_name); | ||
866 | return write_wc.wc_error; | ||
867 | } | ||
868 | |||
850 | o2hb_arm_write_timeout(reg); | 869 | o2hb_arm_write_timeout(reg); |
851 | 870 | ||
852 | /* let the person who launched us know when things are steady */ | 871 | /* let the person who launched us know when things are steady */ |
@@ -854,6 +873,8 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
854 | if (atomic_dec_and_test(®->hr_steady_iterations)) | 873 | if (atomic_dec_and_test(®->hr_steady_iterations)) |
855 | wake_up(&o2hb_steady_queue); | 874 | wake_up(&o2hb_steady_queue); |
856 | } | 875 | } |
876 | |||
877 | return 0; | ||
857 | } | 878 | } |
858 | 879 | ||
859 | /* Subtract b from a, storing the result in a. a *must* have a larger | 880 | /* Subtract b from a, storing the result in a. a *must* have a larger |
@@ -913,7 +934,10 @@ static int o2hb_thread(void *data) | |||
913 | * likely to time itself out. */ | 934 | * likely to time itself out. */ |
914 | do_gettimeofday(&before_hb); | 935 | do_gettimeofday(&before_hb); |
915 | 936 | ||
916 | o2hb_do_disk_heartbeat(reg); | 937 | i = 0; |
938 | do { | ||
939 | ret = o2hb_do_disk_heartbeat(reg); | ||
940 | } while (ret && ++i < 2); | ||
917 | 941 | ||
918 | do_gettimeofday(&after_hb); | 942 | do_gettimeofday(&after_hb); |
919 | elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); | 943 | elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); |
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c index c3764f4744ee..74ca4e5f9765 100644 --- a/fs/ocfs2/dlm/userdlm.c +++ b/fs/ocfs2/dlm/userdlm.c | |||
@@ -139,6 +139,10 @@ static void user_ast(void *opaque) | |||
139 | return; | 139 | return; |
140 | } | 140 | } |
141 | 141 | ||
142 | mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE, | ||
143 | "Lockres %s, requested ivmode. flags 0x%x\n", | ||
144 | lockres->l_name, lockres->l_flags); | ||
145 | |||
142 | /* we're downconverting. */ | 146 | /* we're downconverting. */ |
143 | if (lockres->l_requested < lockres->l_level) { | 147 | if (lockres->l_requested < lockres->l_level) { |
144 | if (lockres->l_requested <= | 148 | if (lockres->l_requested <= |
@@ -229,23 +233,42 @@ static void user_unlock_ast(void *opaque, enum dlm_status status) | |||
229 | 233 | ||
230 | mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name); | 234 | mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name); |
231 | 235 | ||
232 | if (status != DLM_NORMAL) | 236 | if (status != DLM_NORMAL && status != DLM_CANCELGRANT) |
233 | mlog(ML_ERROR, "Dlm returns status %d\n", status); | 237 | mlog(ML_ERROR, "Dlm returns status %d\n", status); |
234 | 238 | ||
235 | spin_lock(&lockres->l_lock); | 239 | spin_lock(&lockres->l_lock); |
236 | if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) | 240 | /* The teardown flag gets set early during the unlock process, |
241 | * so test the cancel flag to make sure that this ast isn't | ||
242 | * for a concurrent cancel. */ | ||
243 | if (lockres->l_flags & USER_LOCK_IN_TEARDOWN | ||
244 | && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) { | ||
237 | lockres->l_level = LKM_IVMODE; | 245 | lockres->l_level = LKM_IVMODE; |
238 | else { | 246 | } else if (status == DLM_CANCELGRANT) { |
247 | mlog(0, "Lock %s, cancel fails, flags 0x%x\n", | ||
248 | lockres->l_name, lockres->l_flags); | ||
249 | /* We tried to cancel a convert request, but it was | ||
250 | * already granted. Don't clear the busy flag - the | ||
251 | * ast should've done this already. */ | ||
252 | BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); | ||
253 | lockres->l_flags &= ~USER_LOCK_IN_CANCEL; | ||
254 | goto out_noclear; | ||
255 | } else { | ||
256 | BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); | ||
257 | /* Cancel succeeded, we want to re-queue */ | ||
258 | mlog(0, "Lock %s, cancel succeeds, flags 0x%x\n", | ||
259 | lockres->l_name, lockres->l_flags); | ||
239 | lockres->l_requested = LKM_IVMODE; /* cancel an | 260 | lockres->l_requested = LKM_IVMODE; /* cancel an |
240 | * upconvert | 261 | * upconvert |
241 | * request. */ | 262 | * request. */ |
242 | lockres->l_flags &= ~USER_LOCK_IN_CANCEL; | 263 | lockres->l_flags &= ~USER_LOCK_IN_CANCEL; |
243 | /* we want the unblock thread to look at it again | 264 | /* we want the unblock thread to look at it again |
244 | * now. */ | 265 | * now. */ |
245 | __user_dlm_queue_lockres(lockres); | 266 | if (lockres->l_flags & USER_LOCK_BLOCKED) |
267 | __user_dlm_queue_lockres(lockres); | ||
246 | } | 268 | } |
247 | 269 | ||
248 | lockres->l_flags &= ~USER_LOCK_BUSY; | 270 | lockres->l_flags &= ~USER_LOCK_BUSY; |
271 | out_noclear: | ||
249 | spin_unlock(&lockres->l_lock); | 272 | spin_unlock(&lockres->l_lock); |
250 | 273 | ||
251 | wake_up(&lockres->l_event); | 274 | wake_up(&lockres->l_event); |
@@ -268,13 +291,26 @@ static void user_dlm_unblock_lock(void *opaque) | |||
268 | 291 | ||
269 | spin_lock(&lockres->l_lock); | 292 | spin_lock(&lockres->l_lock); |
270 | 293 | ||
271 | BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED)); | 294 | mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED), |
272 | BUG_ON(!(lockres->l_flags & USER_LOCK_QUEUED)); | 295 | "Lockres %s, flags 0x%x\n", |
296 | lockres->l_name, lockres->l_flags); | ||
273 | 297 | ||
274 | /* notice that we don't clear USER_LOCK_BLOCKED here. That's | 298 | /* notice that we don't clear USER_LOCK_BLOCKED here. If it's |
275 | * for user_ast to do. */ | 299 | * set, we want user_ast clear it. */ |
276 | lockres->l_flags &= ~USER_LOCK_QUEUED; | 300 | lockres->l_flags &= ~USER_LOCK_QUEUED; |
277 | 301 | ||
302 | /* It's valid to get here and no longer be blocked - if we get | ||
303 | * several basts in a row, we might be queued by the first | ||
304 | * one, the unblock thread might run and clear the queued | ||
305 | * flag, and finally we might get another bast which re-queues | ||
306 | * us before our ast for the downconvert is called. */ | ||
307 | if (!(lockres->l_flags & USER_LOCK_BLOCKED)) { | ||
308 | mlog(0, "Lockres %s, flags 0x%x: queued but not blocking\n", | ||
309 | lockres->l_name, lockres->l_flags); | ||
310 | spin_unlock(&lockres->l_lock); | ||
311 | goto drop_ref; | ||
312 | } | ||
313 | |||
278 | if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { | 314 | if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { |
279 | mlog(0, "lock is in teardown so we do nothing\n"); | 315 | mlog(0, "lock is in teardown so we do nothing\n"); |
280 | spin_unlock(&lockres->l_lock); | 316 | spin_unlock(&lockres->l_lock); |
@@ -282,7 +318,9 @@ static void user_dlm_unblock_lock(void *opaque) | |||
282 | } | 318 | } |
283 | 319 | ||
284 | if (lockres->l_flags & USER_LOCK_BUSY) { | 320 | if (lockres->l_flags & USER_LOCK_BUSY) { |
285 | mlog(0, "BUSY flag detected...\n"); | 321 | mlog(0, "Cancel lock %s, flags 0x%x\n", |
322 | lockres->l_name, lockres->l_flags); | ||
323 | |||
286 | if (lockres->l_flags & USER_LOCK_IN_CANCEL) { | 324 | if (lockres->l_flags & USER_LOCK_IN_CANCEL) { |
287 | spin_unlock(&lockres->l_lock); | 325 | spin_unlock(&lockres->l_lock); |
288 | goto drop_ref; | 326 | goto drop_ref; |
@@ -296,14 +334,7 @@ static void user_dlm_unblock_lock(void *opaque) | |||
296 | LKM_CANCEL, | 334 | LKM_CANCEL, |
297 | user_unlock_ast, | 335 | user_unlock_ast, |
298 | lockres); | 336 | lockres); |
299 | if (status == DLM_CANCELGRANT) { | 337 | if (status != DLM_NORMAL) |
300 | /* If we got this, then the ast was fired | ||
301 | * before we could cancel. We cleanup our | ||
302 | * state, and restart the function. */ | ||
303 | spin_lock(&lockres->l_lock); | ||
304 | lockres->l_flags &= ~USER_LOCK_IN_CANCEL; | ||
305 | spin_unlock(&lockres->l_lock); | ||
306 | } else if (status != DLM_NORMAL) | ||
307 | user_log_dlm_error("dlmunlock", status, lockres); | 338 | user_log_dlm_error("dlmunlock", status, lockres); |
308 | goto drop_ref; | 339 | goto drop_ref; |
309 | } | 340 | } |
@@ -581,6 +612,14 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres) | |||
581 | mlog(0, "asked to destroy %s\n", lockres->l_name); | 612 | mlog(0, "asked to destroy %s\n", lockres->l_name); |
582 | 613 | ||
583 | spin_lock(&lockres->l_lock); | 614 | spin_lock(&lockres->l_lock); |
615 | if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { | ||
616 | mlog(0, "Lock is already torn down\n"); | ||
617 | spin_unlock(&lockres->l_lock); | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | lockres->l_flags |= USER_LOCK_IN_TEARDOWN; | ||
622 | |||
584 | while (lockres->l_flags & USER_LOCK_BUSY) { | 623 | while (lockres->l_flags & USER_LOCK_BUSY) { |
585 | spin_unlock(&lockres->l_lock); | 624 | spin_unlock(&lockres->l_lock); |
586 | 625 | ||
@@ -606,7 +645,6 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres) | |||
606 | 645 | ||
607 | lockres->l_flags &= ~USER_LOCK_ATTACHED; | 646 | lockres->l_flags &= ~USER_LOCK_ATTACHED; |
608 | lockres->l_flags |= USER_LOCK_BUSY; | 647 | lockres->l_flags |= USER_LOCK_BUSY; |
609 | lockres->l_flags |= USER_LOCK_IN_TEARDOWN; | ||
610 | spin_unlock(&lockres->l_lock); | 648 | spin_unlock(&lockres->l_lock); |
611 | 649 | ||
612 | mlog(0, "unlocking lockres %s\n", lockres->l_name); | 650 | mlog(0, "unlocking lockres %s\n", lockres->l_name); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 34e903a6a46b..581eb451a41a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -260,6 +260,17 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
260 | if (new_i_size == le64_to_cpu(fe->i_size)) | 260 | if (new_i_size == le64_to_cpu(fe->i_size)) |
261 | goto bail; | 261 | goto bail; |
262 | 262 | ||
263 | /* This forces other nodes to sync and drop their pages. Do | ||
264 | * this even if we have a truncate without allocation change - | ||
265 | * ocfs2 cluster sizes can be much greater than page size, so | ||
266 | * we have to truncate them anyway. */ | ||
267 | status = ocfs2_data_lock(inode, 1); | ||
268 | if (status < 0) { | ||
269 | mlog_errno(status); | ||
270 | goto bail; | ||
271 | } | ||
272 | ocfs2_data_unlock(inode, 1); | ||
273 | |||
263 | if (le32_to_cpu(fe->i_clusters) == | 274 | if (le32_to_cpu(fe->i_clusters) == |
264 | ocfs2_clusters_for_bytes(osb->sb, new_i_size)) { | 275 | ocfs2_clusters_for_bytes(osb->sb, new_i_size)) { |
265 | mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n", | 276 | mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n", |
@@ -272,14 +283,6 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
272 | goto bail; | 283 | goto bail; |
273 | } | 284 | } |
274 | 285 | ||
275 | /* This forces other nodes to sync and drop their pages */ | ||
276 | status = ocfs2_data_lock(inode, 1); | ||
277 | if (status < 0) { | ||
278 | mlog_errno(status); | ||
279 | goto bail; | ||
280 | } | ||
281 | ocfs2_data_unlock(inode, 1); | ||
282 | |||
283 | /* alright, we're going to need to do a full blown alloc size | 286 | /* alright, we're going to need to do a full blown alloc size |
284 | * change. Orphan the inode so that recovery can complete the | 287 | * change. Orphan the inode so that recovery can complete the |
285 | * truncate if necessary. This does the task of marking | 288 | * truncate if necessary. This does the task of marking |
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index ff9ac8d19eb2..288233fd77d7 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h | |||
@@ -139,6 +139,8 @@ void switch_ipi_to_APIC_timer(void *cpumask); | |||
139 | 139 | ||
140 | extern int timer_over_8254; | 140 | extern int timer_over_8254; |
141 | 141 | ||
142 | extern int modern_apic(void); | ||
143 | |||
142 | #else /* !CONFIG_X86_LOCAL_APIC */ | 144 | #else /* !CONFIG_X86_LOCAL_APIC */ |
143 | static inline void lapic_shutdown(void) { } | 145 | static inline void lapic_shutdown(void) { } |
144 | 146 | ||
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h index edf65be21a92..ca82acb8cb1f 100644 --- a/include/asm-i386/e820.h +++ b/include/asm-i386/e820.h | |||
@@ -35,6 +35,10 @@ struct e820map { | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | extern struct e820map e820; | 37 | extern struct e820map e820; |
38 | |||
39 | extern int e820_all_mapped(unsigned long start, unsigned long end, | ||
40 | unsigned type); | ||
41 | |||
38 | #endif/*!__ASSEMBLY__*/ | 42 | #endif/*!__ASSEMBLY__*/ |
39 | 43 | ||
40 | #endif/*__E820_HEADER*/ | 44 | #endif/*__E820_HEADER*/ |
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h index 16ef9f996e3f..7f1a8a6ee32f 100644 --- a/include/asm-i386/hpet.h +++ b/include/asm-i386/hpet.h | |||
@@ -89,6 +89,7 @@ | |||
89 | * then 32 bit HPET counter wrapsaround in less than 0.5 sec. | 89 | * then 32 bit HPET counter wrapsaround in less than 0.5 sec. |
90 | */ | 90 | */ |
91 | #define HPET_MIN_PERIOD (100000UL) | 91 | #define HPET_MIN_PERIOD (100000UL) |
92 | #define HPET_TICK_RATE (HZ * 100000UL) | ||
92 | 93 | ||
93 | extern unsigned long hpet_tick; /* hpet clks count per tick */ | 94 | extern unsigned long hpet_tick; /* hpet clks count per tick */ |
94 | extern unsigned long hpet_address; /* hpet memory map physical address */ | 95 | extern unsigned long hpet_address; /* hpet memory map physical address */ |
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h index 8dcc32665240..93b51df51687 100644 --- a/include/asm-x86_64/e820.h +++ b/include/asm-x86_64/e820.h | |||
@@ -47,7 +47,8 @@ extern void contig_e820_setup(void); | |||
47 | extern unsigned long e820_end_of_ram(void); | 47 | extern unsigned long e820_end_of_ram(void); |
48 | extern void e820_reserve_resources(void); | 48 | extern void e820_reserve_resources(void); |
49 | extern void e820_print_map(char *who); | 49 | extern void e820_print_map(char *who); |
50 | extern int e820_mapped(unsigned long start, unsigned long end, unsigned type); | 50 | extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type); |
51 | extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type); | ||
51 | 52 | ||
52 | extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end); | 53 | extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end); |
53 | extern void e820_setup_gap(void); | 54 | extern void e820_setup_gap(void); |
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h index 08b75c15269a..18ff7ee9e774 100644 --- a/include/asm-x86_64/hpet.h +++ b/include/asm-x86_64/hpet.h | |||
@@ -51,6 +51,8 @@ | |||
51 | 51 | ||
52 | #define HPET_TN_ROUTE_SHIFT 9 | 52 | #define HPET_TN_ROUTE_SHIFT 9 |
53 | 53 | ||
54 | #define HPET_TICK_RATE (HZ * 100000UL) | ||
55 | |||
54 | extern int is_hpet_enabled(void); | 56 | extern int is_hpet_enabled(void); |
55 | extern int hpet_rtc_timer_init(void); | 57 | extern int hpet_rtc_timer_init(void); |
56 | extern int oem_force_hpet_timer(void); | 58 | extern int oem_force_hpet_timer(void); |
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h index eeb2bcd635de..b4f4b172b15a 100644 --- a/include/asm-x86_64/ia32_unistd.h +++ b/include/asm-x86_64/ia32_unistd.h | |||
@@ -317,6 +317,4 @@ | |||
317 | #define __NR_ia32_ppoll 309 | 317 | #define __NR_ia32_ppoll 309 |
318 | #define __NR_ia32_unshare 310 | 318 | #define __NR_ia32_unshare 310 |
319 | 319 | ||
320 | #define IA32_NR_syscalls 315 /* must be > than biggest syscall! */ | ||
321 | |||
322 | #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ | 320 | #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ |
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h index 5d298b799a9f..7229785094e3 100644 --- a/include/asm-x86_64/mce.h +++ b/include/asm-x86_64/mce.h | |||
@@ -70,6 +70,9 @@ struct mce_log { | |||
70 | #define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */ | 70 | #define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */ |
71 | #define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4 | 71 | #define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4 |
72 | 72 | ||
73 | #ifdef __KERNEL__ | ||
74 | #include <asm/atomic.h> | ||
75 | |||
73 | void mce_log(struct mce *m); | 76 | void mce_log(struct mce *m); |
74 | #ifdef CONFIG_X86_MCE_INTEL | 77 | #ifdef CONFIG_X86_MCE_INTEL |
75 | void mce_intel_feature_init(struct cpuinfo_x86 *c); | 78 | void mce_intel_feature_init(struct cpuinfo_x86 *c); |
@@ -87,4 +90,8 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
87 | } | 90 | } |
88 | #endif | 91 | #endif |
89 | 92 | ||
93 | extern atomic_t mce_entry; | ||
94 | |||
95 | #endif | ||
96 | |||
90 | #endif | 97 | #endif |
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index f6cbb4cbb5a3..f0ba4d984bdf 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h | |||
@@ -18,6 +18,8 @@ extern void numa_init_array(void); | |||
18 | extern int numa_off; | 18 | extern int numa_off; |
19 | 19 | ||
20 | extern void numa_set_node(int cpu, int node); | 20 | extern void numa_set_node(int cpu, int node); |
21 | extern void srat_reserve_add_area(int nodeid); | ||
22 | extern int hotadd_percent; | ||
21 | 23 | ||
22 | extern unsigned char apicid_to_node[256]; | 24 | extern unsigned char apicid_to_node[256]; |
23 | #ifdef CONFIG_NUMA | 25 | #ifdef CONFIG_NUMA |
diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h index 32be16b8ae96..5a1d506b8299 100644 --- a/include/asm-x86_64/numnodes.h +++ b/include/asm-x86_64/numnodes.h | |||
@@ -5,8 +5,6 @@ | |||
5 | 5 | ||
6 | #ifdef CONFIG_NUMA | 6 | #ifdef CONFIG_NUMA |
7 | #define NODES_SHIFT 6 | 7 | #define NODES_SHIFT 6 |
8 | #else | ||
9 | #define NODES_SHIFT 0 | ||
10 | #endif | 8 | #endif |
11 | 9 | ||
12 | #endif | 10 | #endif |
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index de3eb8d8ae26..da2d107fe2cf 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
@@ -45,6 +45,7 @@ extern unsigned long __init bootmem_bootmap_pages (unsigned long); | |||
45 | extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend); | 45 | extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend); |
46 | extern void __init free_bootmem (unsigned long addr, unsigned long size); | 46 | extern void __init free_bootmem (unsigned long addr, unsigned long size); |
47 | extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal); | 47 | extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal); |
48 | extern void * __init __alloc_bootmem_nopanic (unsigned long size, unsigned long align, unsigned long goal); | ||
48 | extern void * __init __alloc_bootmem_low(unsigned long size, | 49 | extern void * __init __alloc_bootmem_low(unsigned long size, |
49 | unsigned long align, | 50 | unsigned long align, |
50 | unsigned long goal); | 51 | unsigned long goal); |
diff --git a/include/linux/init.h b/include/linux/init.h index ed0ac7c39fdc..93dcbe1abb4c 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -245,7 +245,8 @@ void __init parse_early_param(void); | |||
245 | #define __cpuexitdata __exitdata | 245 | #define __cpuexitdata __exitdata |
246 | #endif | 246 | #endif |
247 | 247 | ||
248 | #ifdef CONFIG_MEMORY_HOTPLUG | 248 | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ |
249 | || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||
249 | #define __meminit | 250 | #define __meminit |
250 | #define __meminitdata | 251 | #define __meminitdata |
251 | #define __memexit | 252 | #define __memexit |
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 99905e180532..043376920f51 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
@@ -36,6 +36,8 @@ | |||
36 | /* LATCH is used in the interval timer and ftape setup. */ | 36 | /* LATCH is used in the interval timer and ftape setup. */ |
37 | #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ | 37 | #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ |
38 | 38 | ||
39 | #define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ) | ||
40 | |||
39 | /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can | 41 | /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can |
40 | * improve accuracy by shifting LSH bits, hence calculating: | 42 | * improve accuracy by shifting LSH bits, hence calculating: |
41 | * (NOM << LSH) / DEN | 43 | * (NOM << LSH) / DEN |
@@ -51,9 +53,13 @@ | |||
51 | /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ | 53 | /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ |
52 | #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) | 54 | #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) |
53 | 55 | ||
56 | #define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8)) | ||
57 | |||
54 | /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ | 58 | /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ |
55 | #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) | 59 | #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) |
56 | 60 | ||
61 | #define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8)) | ||
62 | |||
57 | /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ | 63 | /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ |
58 | #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) | 64 | #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) |
59 | 65 | ||
diff --git a/include/linux/libata.h b/include/linux/libata.h index 0d61357604d5..b80d2e7fa6d2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -523,7 +523,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); | |||
523 | extern int ata_scsi_detect(struct scsi_host_template *sht); | 523 | extern int ata_scsi_detect(struct scsi_host_template *sht); |
524 | extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); | 524 | extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); |
525 | extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); | 525 | extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); |
526 | extern int ata_scsi_error(struct Scsi_Host *host); | ||
527 | extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); | 526 | extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); |
528 | extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); | 527 | extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); |
529 | extern int ata_scsi_release(struct Scsi_Host *host); | 528 | extern int ata_scsi_release(struct Scsi_Host *host); |
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 968b1aa3732c..4ca3e6ad03ec 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); | |||
58 | /* need some defines for these for archs that don't support it */ | 58 | /* need some defines for these for archs that don't support it */ |
59 | extern void online_page(struct page *page); | 59 | extern void online_page(struct page *page); |
60 | /* VM interface that may be used by firmware interface */ | 60 | /* VM interface that may be used by firmware interface */ |
61 | extern int add_memory(u64 start, u64 size); | ||
62 | extern int remove_memory(u64 start, u64 size); | ||
63 | extern int online_pages(unsigned long, unsigned long); | 61 | extern int online_pages(unsigned long, unsigned long); |
64 | 62 | ||
65 | /* reasonably generic interface to expand the physical pages in a zone */ | 63 | /* reasonably generic interface to expand the physical pages in a zone */ |
@@ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func) | |||
92 | return -ENOSYS; | 90 | return -ENOSYS; |
93 | } | 91 | } |
94 | 92 | ||
95 | static inline int __add_pages(struct zone *zone, unsigned long start_pfn, | ||
96 | unsigned long nr_pages) | ||
97 | { | ||
98 | return mhp_notimplemented(__FUNCTION__); | ||
99 | } | ||
100 | #endif /* ! CONFIG_MEMORY_HOTPLUG */ | 93 | #endif /* ! CONFIG_MEMORY_HOTPLUG */ |
101 | static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, | 94 | static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, |
102 | unsigned long nr_pages) | 95 | unsigned long nr_pages) |
@@ -105,4 +98,11 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, | |||
105 | dump_stack(); | 98 | dump_stack(); |
106 | return -ENOSYS; | 99 | return -ENOSYS; |
107 | } | 100 | } |
101 | |||
102 | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ | ||
103 | || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||
104 | extern int add_memory(u64 start, u64 size); | ||
105 | extern int remove_memory(u64 start, u64 size); | ||
106 | #endif | ||
107 | |||
108 | #endif /* __LINUX_MEMORY_HOTPLUG_H */ | 108 | #endif /* __LINUX_MEMORY_HOTPLUG_H */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 6aa016f1d3ae..1154684209a4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -229,10 +229,9 @@ struct page { | |||
229 | unsigned long private; /* Mapping-private opaque data: | 229 | unsigned long private; /* Mapping-private opaque data: |
230 | * usually used for buffer_heads | 230 | * usually used for buffer_heads |
231 | * if PagePrivate set; used for | 231 | * if PagePrivate set; used for |
232 | * swp_entry_t if PageSwapCache. | 232 | * swp_entry_t if PageSwapCache; |
233 | * When page is free, this | ||
234 | * indicates order in the buddy | 233 | * indicates order in the buddy |
235 | * system. | 234 | * system if PG_buddy is set. |
236 | */ | 235 | */ |
237 | struct address_space *mapping; /* If low bit clear, points to | 236 | struct address_space *mapping; /* If low bit clear, points to |
238 | * inode address_space, or NULL. | 237 | * inode address_space, or NULL. |
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 412e52ca9720..b31a9bca9361 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -110,6 +110,8 @@ struct nf_info | |||
110 | /* Function to register/unregister hook points. */ | 110 | /* Function to register/unregister hook points. */ |
111 | int nf_register_hook(struct nf_hook_ops *reg); | 111 | int nf_register_hook(struct nf_hook_ops *reg); |
112 | void nf_unregister_hook(struct nf_hook_ops *reg); | 112 | void nf_unregister_hook(struct nf_hook_ops *reg); |
113 | int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); | ||
114 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); | ||
113 | 115 | ||
114 | /* Functions to register get/setsockopt ranges (non-inclusive). You | 116 | /* Functions to register get/setsockopt ranges (non-inclusive). You |
115 | need to check permissions yourself! */ | 117 | need to check permissions yourself! */ |
@@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf); | |||
281 | Returns true or false. */ | 283 | Returns true or false. */ |
282 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); | 284 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); |
283 | 285 | ||
284 | struct nf_queue_rerouter { | 286 | struct nf_afinfo { |
285 | void (*save)(const struct sk_buff *skb, struct nf_info *info); | 287 | unsigned short family; |
286 | int (*reroute)(struct sk_buff **skb, const struct nf_info *info); | 288 | unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, |
287 | int rer_size; | 289 | unsigned int dataoff, u_int8_t protocol); |
290 | void (*saveroute)(const struct sk_buff *skb, | ||
291 | struct nf_info *info); | ||
292 | int (*reroute)(struct sk_buff **skb, | ||
293 | const struct nf_info *info); | ||
294 | int route_key_size; | ||
288 | }; | 295 | }; |
289 | 296 | ||
290 | #define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) | 297 | extern struct nf_afinfo *nf_afinfo[]; |
298 | static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) | ||
299 | { | ||
300 | return rcu_dereference(nf_afinfo[family]); | ||
301 | } | ||
302 | |||
303 | static inline unsigned int | ||
304 | nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, | ||
305 | u_int8_t protocol, unsigned short family) | ||
306 | { | ||
307 | struct nf_afinfo *afinfo; | ||
308 | unsigned int csum = 0; | ||
309 | |||
310 | rcu_read_lock(); | ||
311 | afinfo = nf_get_afinfo(family); | ||
312 | if (afinfo) | ||
313 | csum = afinfo->checksum(skb, hook, dataoff, protocol); | ||
314 | rcu_read_unlock(); | ||
315 | return csum; | ||
316 | } | ||
291 | 317 | ||
292 | extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); | 318 | extern int nf_register_afinfo(struct nf_afinfo *afinfo); |
293 | extern int nf_unregister_queue_rerouter(int pf); | 319 | extern void nf_unregister_afinfo(struct nf_afinfo *afinfo); |
320 | |||
321 | #define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) | ||
294 | 322 | ||
295 | #include <net/flow.h> | 323 | #include <net/flow.h> |
296 | extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | 324 | extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); |
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 43c09d790b83..85301c5e8d24 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h | |||
@@ -80,6 +80,8 @@ enum nf_ip_hook_priorities { | |||
80 | #ifdef __KERNEL__ | 80 | #ifdef __KERNEL__ |
81 | extern int ip_route_me_harder(struct sk_buff **pskb); | 81 | extern int ip_route_me_harder(struct sk_buff **pskb); |
82 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); | 82 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); |
83 | extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, | ||
84 | unsigned int dataoff, u_int8_t protocol); | ||
83 | #endif /*__KERNEL__*/ | 85 | #endif /*__KERNEL__*/ |
84 | 86 | ||
85 | #endif /*__LINUX_IP_NETFILTER_H*/ | 87 | #endif /*__LINUX_IP_NETFILTER_H*/ |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h index 0987cea53840..eace86bd2adb 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> | ||
7 | |||
6 | #define RAS_PORT 1719 | 8 | #define RAS_PORT 1719 |
7 | #define Q931_PORT 1720 | 9 | #define Q931_PORT 1720 |
8 | #define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ | 10 | #define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ |
@@ -25,6 +27,56 @@ struct ip_ct_h323_master { | |||
25 | }; | 27 | }; |
26 | }; | 28 | }; |
27 | 29 | ||
30 | struct ip_conntrack_expect; | ||
31 | |||
32 | extern int get_h225_addr(unsigned char *data, TransportAddress * addr, | ||
33 | u_int32_t * ip, u_int16_t * port); | ||
34 | extern void ip_conntrack_h245_expect(struct ip_conntrack *new, | ||
35 | struct ip_conntrack_expect *this); | ||
36 | extern void ip_conntrack_q931_expect(struct ip_conntrack *new, | ||
37 | struct ip_conntrack_expect *this); | ||
38 | extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, | ||
39 | unsigned char **data, int dataoff, | ||
40 | H245_TransportAddress * addr, | ||
41 | u_int32_t ip, u_int16_t port); | ||
42 | extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, | ||
43 | unsigned char **data, int dataoff, | ||
44 | TransportAddress * addr, | ||
45 | u_int32_t ip, u_int16_t port); | ||
46 | extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, | ||
47 | struct ip_conntrack * ct, | ||
48 | enum ip_conntrack_info ctinfo, | ||
49 | unsigned char **data, | ||
50 | TransportAddress * addr, int count); | ||
51 | extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, | ||
52 | struct ip_conntrack * ct, | ||
53 | enum ip_conntrack_info ctinfo, | ||
54 | unsigned char **data, | ||
55 | TransportAddress * addr, int count); | ||
56 | extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, | ||
57 | struct ip_conntrack * ct, | ||
58 | enum ip_conntrack_info ctinfo, | ||
59 | unsigned char **data, int dataoff, | ||
60 | H245_TransportAddress * addr, | ||
61 | u_int16_t port, u_int16_t rtp_port, | ||
62 | struct ip_conntrack_expect * rtp_exp, | ||
63 | struct ip_conntrack_expect * rtcp_exp); | ||
64 | extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
65 | enum ip_conntrack_info ctinfo, | ||
66 | unsigned char **data, int dataoff, | ||
67 | H245_TransportAddress * addr, u_int16_t port, | ||
68 | struct ip_conntrack_expect * exp); | ||
69 | extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
70 | enum ip_conntrack_info ctinfo, | ||
71 | unsigned char **data, int dataoff, | ||
72 | TransportAddress * addr, u_int16_t port, | ||
73 | struct ip_conntrack_expect * exp); | ||
74 | extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
75 | enum ip_conntrack_info ctinfo, | ||
76 | unsigned char **data, TransportAddress * addr, | ||
77 | int idx, u_int16_t port, | ||
78 | struct ip_conntrack_expect * exp); | ||
79 | |||
28 | #endif | 80 | #endif |
29 | 81 | ||
30 | #endif | 82 | #endif |
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h index 0bd828081c0c..0bd828081c0c 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h | |||
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h index cc98f7aa5abe..cc98f7aa5abe 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h | |||
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index 14f2bd010884..52a7b9e76428 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h | |||
@@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities { | |||
73 | }; | 73 | }; |
74 | 74 | ||
75 | #ifdef CONFIG_NETFILTER | 75 | #ifdef CONFIG_NETFILTER |
76 | extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | ||
77 | unsigned int dataoff, u_int8_t protocol); | ||
78 | |||
76 | extern int ipv6_netfilter_init(void); | 79 | extern int ipv6_netfilter_init(void); |
77 | extern void ipv6_netfilter_fini(void); | 80 | extern void ipv6_netfilter_fini(void); |
78 | #else /* CONFIG_NETFILTER */ | 81 | #else /* CONFIG_NETFILTER */ |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 9ea629c02a4b..547aac7696cd 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -74,7 +74,9 @@ | |||
74 | #define PG_mappedtodisk 16 /* Has blocks allocated on-disk */ | 74 | #define PG_mappedtodisk 16 /* Has blocks allocated on-disk */ |
75 | #define PG_reclaim 17 /* To be reclaimed asap */ | 75 | #define PG_reclaim 17 /* To be reclaimed asap */ |
76 | #define PG_nosave_free 18 /* Free, should not be written */ | 76 | #define PG_nosave_free 18 /* Free, should not be written */ |
77 | #define PG_uncached 19 /* Page has been mapped as uncached */ | 77 | #define PG_buddy 19 /* Page is free, on buddy lists */ |
78 | |||
79 | #define PG_uncached 20 /* Page has been mapped as uncached */ | ||
78 | 80 | ||
79 | /* | 81 | /* |
80 | * Global page accounting. One instance per CPU. Only unsigned longs are | 82 | * Global page accounting. One instance per CPU. Only unsigned longs are |
@@ -317,6 +319,10 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); | |||
317 | #define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags) | 319 | #define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags) |
318 | #define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags) | 320 | #define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags) |
319 | 321 | ||
322 | #define PageBuddy(page) test_bit(PG_buddy, &(page)->flags) | ||
323 | #define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags) | ||
324 | #define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags) | ||
325 | |||
320 | #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) | 326 | #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) |
321 | #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) | 327 | #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) |
322 | #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) | 328 | #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 541f4828f5e7..a3e4f6b503a3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1203,7 +1203,8 @@ extern void wait_task_inactive(task_t * p); | |||
1203 | #define while_each_thread(g, t) \ | 1203 | #define while_each_thread(g, t) \ |
1204 | while ((t = next_thread(t)) != g) | 1204 | while ((t = next_thread(t)) != g) |
1205 | 1205 | ||
1206 | #define thread_group_leader(p) (p->pid == p->tgid) | 1206 | /* de_thread depends on thread_group_leader not being a pid based check */ |
1207 | #define thread_group_leader(p) (p == p->group_leader) | ||
1207 | 1208 | ||
1208 | static inline task_t *next_thread(task_t *p) | 1209 | static inline task_t *next_thread(task_t *p) |
1209 | { | 1210 | { |
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 25f708ff020e..59f0c83d55a2 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h | |||
@@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk) | |||
48 | return inet6_ehashfn(laddr, lport, faddr, fport); | 48 | return inet6_ehashfn(laddr, lport, faddr, fport); |
49 | } | 49 | } |
50 | 50 | ||
51 | static inline void __inet6_hash(struct inet_hashinfo *hashinfo, | 51 | extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk); |
52 | struct sock *sk) | ||
53 | { | ||
54 | struct hlist_head *list; | ||
55 | rwlock_t *lock; | ||
56 | |||
57 | BUG_TRAP(sk_unhashed(sk)); | ||
58 | |||
59 | if (sk->sk_state == TCP_LISTEN) { | ||
60 | list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)]; | ||
61 | lock = &hashinfo->lhash_lock; | ||
62 | inet_listen_wlock(hashinfo); | ||
63 | } else { | ||
64 | unsigned int hash; | ||
65 | sk->sk_hash = hash = inet6_sk_ehashfn(sk); | ||
66 | hash &= (hashinfo->ehash_size - 1); | ||
67 | list = &hashinfo->ehash[hash].chain; | ||
68 | lock = &hashinfo->ehash[hash].lock; | ||
69 | write_lock(lock); | ||
70 | } | ||
71 | |||
72 | __sk_add_node(sk, list); | ||
73 | sock_prot_inc_use(sk->sk_prot); | ||
74 | write_unlock(lock); | ||
75 | } | ||
76 | 52 | ||
77 | /* | 53 | /* |
78 | * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so | 54 | * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so |
@@ -80,52 +56,12 @@ static inline void __inet6_hash(struct inet_hashinfo *hashinfo, | |||
80 | * | 56 | * |
81 | * The sockhash lock must be held as a reader here. | 57 | * The sockhash lock must be held as a reader here. |
82 | */ | 58 | */ |
83 | static inline struct sock * | 59 | extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, |
84 | __inet6_lookup_established(struct inet_hashinfo *hashinfo, | ||
85 | const struct in6_addr *saddr, | 60 | const struct in6_addr *saddr, |
86 | const u16 sport, | 61 | const u16 sport, |
87 | const struct in6_addr *daddr, | 62 | const struct in6_addr *daddr, |
88 | const u16 hnum, | 63 | const u16 hnum, |
89 | const int dif) | 64 | const int dif); |
90 | { | ||
91 | struct sock *sk; | ||
92 | const struct hlist_node *node; | ||
93 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | ||
94 | /* Optimize here for direct hit, only listening connections can | ||
95 | * have wildcards anyways. | ||
96 | */ | ||
97 | unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport); | ||
98 | struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); | ||
99 | |||
100 | prefetch(head->chain.first); | ||
101 | read_lock(&head->lock); | ||
102 | sk_for_each(sk, node, &head->chain) { | ||
103 | /* For IPV6 do the cheaper port and family tests first. */ | ||
104 | if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) | ||
105 | goto hit; /* You sunk my battleship! */ | ||
106 | } | ||
107 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | ||
108 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { | ||
109 | const struct inet_timewait_sock *tw = inet_twsk(sk); | ||
110 | |||
111 | if(*((__u32 *)&(tw->tw_dport)) == ports && | ||
112 | sk->sk_family == PF_INET6) { | ||
113 | const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); | ||
114 | |||
115 | if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && | ||
116 | ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && | ||
117 | (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)) | ||
118 | goto hit; | ||
119 | } | ||
120 | } | ||
121 | read_unlock(&head->lock); | ||
122 | return NULL; | ||
123 | |||
124 | hit: | ||
125 | sock_hold(sk); | ||
126 | read_unlock(&head->lock); | ||
127 | return sk; | ||
128 | } | ||
129 | 65 | ||
130 | extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | 66 | extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, |
131 | const struct in6_addr *daddr, | 67 | const struct in6_addr *daddr, |
diff --git a/include/net/ip.h b/include/net/ip.h index 8fe6156ca9b0..3d2e5ca62a5a 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb); | |||
95 | extern int ip_mr_input(struct sk_buff *skb); | 95 | extern int ip_mr_input(struct sk_buff *skb); |
96 | extern int ip_output(struct sk_buff *skb); | 96 | extern int ip_output(struct sk_buff *skb); |
97 | extern int ip_mc_output(struct sk_buff *skb); | 97 | extern int ip_mc_output(struct sk_buff *skb); |
98 | extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | ||
98 | extern int ip_do_nat(struct sk_buff *skb); | 99 | extern int ip_do_nat(struct sk_buff *skb); |
99 | extern void ip_send_check(struct iphdr *ip); | 100 | extern void ip_send_check(struct iphdr *ip); |
100 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); | 101 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); |
diff --git a/include/net/x25device.h b/include/net/x25device.h index 1a318374faef..1d10c879f7e2 100644 --- a/include/net/x25device.h +++ b/include/net/x25device.h | |||
@@ -8,6 +8,7 @@ | |||
8 | static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev) | 8 | static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev) |
9 | { | 9 | { |
10 | skb->mac.raw = skb->data; | 10 | skb->mac.raw = skb->data; |
11 | skb->dev = dev; | ||
11 | skb->pkt_type = PACKET_HOST; | 12 | skb->pkt_type = PACKET_HOST; |
12 | 13 | ||
13 | return htons(ETH_P_X25); | 14 | return htons(ETH_P_X25); |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index dc6862d09e53..de6ce541a046 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -140,7 +140,6 @@ struct scsi_host_template { | |||
140 | * | 140 | * |
141 | * Status: REQUIRED (at least one of them) | 141 | * Status: REQUIRED (at least one of them) |
142 | */ | 142 | */ |
143 | int (* eh_strategy_handler)(struct Scsi_Host *); | ||
144 | int (* eh_abort_handler)(struct scsi_cmnd *); | 143 | int (* eh_abort_handler)(struct scsi_cmnd *); |
145 | int (* eh_device_reset_handler)(struct scsi_cmnd *); | 144 | int (* eh_device_reset_handler)(struct scsi_cmnd *); |
146 | int (* eh_bus_reset_handler)(struct scsi_cmnd *); | 145 | int (* eh_bus_reset_handler)(struct scsi_cmnd *); |
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index b3657f111937..cca1d4926d2a 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h | |||
@@ -50,6 +50,11 @@ struct scsi_transport_template { | |||
50 | unsigned int create_work_queue : 1; | 50 | unsigned int create_work_queue : 1; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Allows a transport to override the default error handler. | ||
54 | */ | ||
55 | void (* eh_strategy_handler)(struct Scsi_Host *); | ||
56 | |||
57 | /* | ||
53 | * This is an optional routine that allows the transport to become | 58 | * This is an optional routine that allows the transport to become |
54 | * involved when a scsi io timer fires. The return value tells the | 59 | * involved when a scsi io timer fires. The return value tells the |
55 | * timer routine how to finish the io timeout handling: | 60 | * timer routine how to finish the io timeout handling: |
diff --git a/kernel/timer.c b/kernel/timer.c index c3a874f1393c..471ab8710b8f 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1455,7 +1455,7 @@ static void time_interpolator_update(long delta_nsec) | |||
1455 | */ | 1455 | */ |
1456 | if (jiffies % INTERPOLATOR_ADJUST == 0) | 1456 | if (jiffies % INTERPOLATOR_ADJUST == 0) |
1457 | { | 1457 | { |
1458 | if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC) | 1458 | if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec) |
1459 | time_interpolator->nsec_per_cyc--; | 1459 | time_interpolator->nsec_per_cyc--; |
1460 | if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0) | 1460 | if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0) |
1461 | time_interpolator->nsec_per_cyc++; | 1461 | time_interpolator->nsec_per_cyc++; |
diff --git a/mm/bootmem.c b/mm/bootmem.c index d3e3bd2ffcea..d213feded10d 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -401,7 +401,7 @@ unsigned long __init free_all_bootmem (void) | |||
401 | return(free_all_bootmem_core(NODE_DATA(0))); | 401 | return(free_all_bootmem_core(NODE_DATA(0))); |
402 | } | 402 | } |
403 | 403 | ||
404 | void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) | 404 | void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal) |
405 | { | 405 | { |
406 | bootmem_data_t *bdata; | 406 | bootmem_data_t *bdata; |
407 | void *ptr; | 407 | void *ptr; |
@@ -409,7 +409,14 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned | |||
409 | list_for_each_entry(bdata, &bdata_list, list) | 409 | list_for_each_entry(bdata, &bdata_list, list) |
410 | if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0))) | 410 | if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0))) |
411 | return(ptr); | 411 | return(ptr); |
412 | return NULL; | ||
413 | } | ||
412 | 414 | ||
415 | void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) | ||
416 | { | ||
417 | void *mem = __alloc_bootmem_nopanic(size,align,goal); | ||
418 | if (mem) | ||
419 | return mem; | ||
413 | /* | 420 | /* |
414 | * Whoops, we cannot satisfy the allocation request. | 421 | * Whoops, we cannot satisfy the allocation request. |
415 | */ | 422 | */ |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index dc523a1f270d..b8165e037dee 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -151,7 +151,8 @@ static void bad_page(struct page *page) | |||
151 | 1 << PG_reclaim | | 151 | 1 << PG_reclaim | |
152 | 1 << PG_slab | | 152 | 1 << PG_slab | |
153 | 1 << PG_swapcache | | 153 | 1 << PG_swapcache | |
154 | 1 << PG_writeback ); | 154 | 1 << PG_writeback | |
155 | 1 << PG_buddy ); | ||
155 | set_page_count(page, 0); | 156 | set_page_count(page, 0); |
156 | reset_page_mapcount(page); | 157 | reset_page_mapcount(page); |
157 | page->mapping = NULL; | 158 | page->mapping = NULL; |
@@ -236,12 +237,12 @@ static inline unsigned long page_order(struct page *page) { | |||
236 | 237 | ||
237 | static inline void set_page_order(struct page *page, int order) { | 238 | static inline void set_page_order(struct page *page, int order) { |
238 | set_page_private(page, order); | 239 | set_page_private(page, order); |
239 | __SetPagePrivate(page); | 240 | __SetPageBuddy(page); |
240 | } | 241 | } |
241 | 242 | ||
242 | static inline void rmv_page_order(struct page *page) | 243 | static inline void rmv_page_order(struct page *page) |
243 | { | 244 | { |
244 | __ClearPagePrivate(page); | 245 | __ClearPageBuddy(page); |
245 | set_page_private(page, 0); | 246 | set_page_private(page, 0); |
246 | } | 247 | } |
247 | 248 | ||
@@ -280,11 +281,13 @@ __find_combined_index(unsigned long page_idx, unsigned int order) | |||
280 | * This function checks whether a page is free && is the buddy | 281 | * This function checks whether a page is free && is the buddy |
281 | * we can do coalesce a page and its buddy if | 282 | * we can do coalesce a page and its buddy if |
282 | * (a) the buddy is not in a hole && | 283 | * (a) the buddy is not in a hole && |
283 | * (b) the buddy is free && | 284 | * (b) the buddy is in the buddy system && |
284 | * (c) the buddy is on the buddy system && | 285 | * (c) a page and its buddy have the same order. |
285 | * (d) a page and its buddy have the same order. | 286 | * |
286 | * for recording page's order, we use page_private(page) and PG_private. | 287 | * For recording whether a page is in the buddy system, we use PG_buddy. |
288 | * Setting, clearing, and testing PG_buddy is serialized by zone->lock. | ||
287 | * | 289 | * |
290 | * For recording page's order, we use page_private(page). | ||
288 | */ | 291 | */ |
289 | static inline int page_is_buddy(struct page *page, int order) | 292 | static inline int page_is_buddy(struct page *page, int order) |
290 | { | 293 | { |
@@ -293,10 +296,10 @@ static inline int page_is_buddy(struct page *page, int order) | |||
293 | return 0; | 296 | return 0; |
294 | #endif | 297 | #endif |
295 | 298 | ||
296 | if (PagePrivate(page) && | 299 | if (PageBuddy(page) && page_order(page) == order) { |
297 | (page_order(page) == order) && | 300 | BUG_ON(page_count(page) != 0); |
298 | page_count(page) == 0) | ||
299 | return 1; | 301 | return 1; |
302 | } | ||
300 | return 0; | 303 | return 0; |
301 | } | 304 | } |
302 | 305 | ||
@@ -313,7 +316,7 @@ static inline int page_is_buddy(struct page *page, int order) | |||
313 | * as necessary, plus some accounting needed to play nicely with other | 316 | * as necessary, plus some accounting needed to play nicely with other |
314 | * parts of the VM system. | 317 | * parts of the VM system. |
315 | * At each level, we keep a list of pages, which are heads of continuous | 318 | * At each level, we keep a list of pages, which are heads of continuous |
316 | * free pages of length of (1 << order) and marked with PG_Private.Page's | 319 | * free pages of length of (1 << order) and marked with PG_buddy. Page's |
317 | * order is recorded in page_private(page) field. | 320 | * order is recorded in page_private(page) field. |
318 | * So when we are allocating or freeing one, we can derive the state of the | 321 | * So when we are allocating or freeing one, we can derive the state of the |
319 | * other. That is, if we allocate a small block, and both were | 322 | * other. That is, if we allocate a small block, and both were |
@@ -376,7 +379,8 @@ static inline int free_pages_check(struct page *page) | |||
376 | 1 << PG_slab | | 379 | 1 << PG_slab | |
377 | 1 << PG_swapcache | | 380 | 1 << PG_swapcache | |
378 | 1 << PG_writeback | | 381 | 1 << PG_writeback | |
379 | 1 << PG_reserved )))) | 382 | 1 << PG_reserved | |
383 | 1 << PG_buddy )))) | ||
380 | bad_page(page); | 384 | bad_page(page); |
381 | if (PageDirty(page)) | 385 | if (PageDirty(page)) |
382 | __ClearPageDirty(page); | 386 | __ClearPageDirty(page); |
@@ -524,7 +528,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) | |||
524 | 1 << PG_slab | | 528 | 1 << PG_slab | |
525 | 1 << PG_swapcache | | 529 | 1 << PG_swapcache | |
526 | 1 << PG_writeback | | 530 | 1 << PG_writeback | |
527 | 1 << PG_reserved )))) | 531 | 1 << PG_reserved | |
532 | 1 << PG_buddy )))) | ||
528 | bad_page(page); | 533 | bad_page(page); |
529 | 534 | ||
530 | /* | 535 | /* |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 6b61323ce23c..0c2d13ad69bb 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | if ((err = hci_send_sco(conn->hcon, skb)) < 0) | 257 | if ((err = hci_send_sco(conn->hcon, skb)) < 0) |
258 | goto fail; | 258 | return err; |
259 | 259 | ||
260 | return count; | 260 | return count; |
261 | 261 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index f29450b788be..3da9264449f7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -765,6 +765,15 @@ out: | |||
765 | return NF_STOLEN; | 765 | return NF_STOLEN; |
766 | } | 766 | } |
767 | 767 | ||
768 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | ||
769 | { | ||
770 | if (skb->protocol == htons(ETH_P_IP) && | ||
771 | skb->len > skb->dev->mtu && | ||
772 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | ||
773 | return ip_fragment(skb, br_dev_queue_push_xmit); | ||
774 | else | ||
775 | return br_dev_queue_push_xmit(skb); | ||
776 | } | ||
768 | 777 | ||
769 | /* PF_BRIDGE/POST_ROUTING ********************************************/ | 778 | /* PF_BRIDGE/POST_ROUTING ********************************************/ |
770 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | 779 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, |
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
824 | realoutdev = nf_bridge->netoutdev; | 833 | realoutdev = nf_bridge->netoutdev; |
825 | #endif | 834 | #endif |
826 | NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, | 835 | NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, |
827 | br_dev_queue_push_xmit); | 836 | br_nf_dev_queue_xmit); |
828 | 837 | ||
829 | return NF_STOLEN; | 838 | return NF_STOLEN; |
830 | 839 | ||
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, | |||
869 | 878 | ||
870 | if ((out->hard_start_xmit == br_dev_xmit && | 879 | if ((out->hard_start_xmit == br_dev_xmit && |
871 | okfn != br_nf_forward_finish && | 880 | okfn != br_nf_forward_finish && |
872 | okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) | 881 | okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit) |
873 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 882 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
874 | || ((out->priv_flags & IFF_802_1Q_VLAN) && | 883 | || ((out->priv_flags & IFF_802_1Q_VLAN) && |
875 | VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) | 884 | VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) |
diff --git a/net/core/dev.c b/net/core/dev.c index 434220d093aa..2731570eba5b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3042,11 +3042,11 @@ void netdev_run_todo(void) | |||
3042 | 3042 | ||
3043 | switch(dev->reg_state) { | 3043 | switch(dev->reg_state) { |
3044 | case NETREG_REGISTERING: | 3044 | case NETREG_REGISTERING: |
3045 | dev->reg_state = NETREG_REGISTERED; | ||
3045 | err = netdev_register_sysfs(dev); | 3046 | err = netdev_register_sysfs(dev); |
3046 | if (err) | 3047 | if (err) |
3047 | printk(KERN_ERR "%s: failed sysfs registration (%d)\n", | 3048 | printk(KERN_ERR "%s: failed sysfs registration (%d)\n", |
3048 | dev->name, err); | 3049 | dev->name, err); |
3049 | dev->reg_state = NETREG_REGISTERED; | ||
3050 | break; | 3050 | break; |
3051 | 3051 | ||
3052 | case NETREG_UNREGISTERING: | 3052 | case NETREG_UNREGISTERING: |
@@ -3100,12 +3100,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
3100 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; | 3100 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; |
3101 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; | 3101 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; |
3102 | 3102 | ||
3103 | p = kmalloc(alloc_size, GFP_KERNEL); | 3103 | p = kzalloc(alloc_size, GFP_KERNEL); |
3104 | if (!p) { | 3104 | if (!p) { |
3105 | printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); | 3105 | printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); |
3106 | return NULL; | 3106 | return NULL; |
3107 | } | 3107 | } |
3108 | memset(p, 0, alloc_size); | ||
3109 | 3108 | ||
3110 | dev = (struct net_device *) | 3109 | dev = (struct net_device *) |
3111 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 3110 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
diff --git a/net/core/dv.c b/net/core/dv.c index cf581407538c..29ee77f15932 100644 --- a/net/core/dv.c +++ b/net/core/dv.c | |||
@@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev) | |||
55 | 55 | ||
56 | dev->divert = NULL; | 56 | dev->divert = NULL; |
57 | if (dev->type == ARPHRD_ETHER) { | 57 | if (dev->type == ARPHRD_ETHER) { |
58 | dev->divert = (struct divert_blk *) | 58 | dev->divert = kzalloc(alloc_size, GFP_KERNEL); |
59 | kmalloc(alloc_size, GFP_KERNEL); | ||
60 | if (dev->divert == NULL) { | 59 | if (dev->divert == NULL) { |
61 | printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", | 60 | printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", |
62 | dev->name); | 61 | dev->name); |
63 | return -ENOMEM; | 62 | return -ENOMEM; |
64 | } | 63 | } |
65 | |||
66 | memset(dev->divert, 0, sizeof(struct divert_blk)); | ||
67 | dev_hold(dev); | 64 | dev_hold(dev); |
68 | } | 65 | } |
69 | 66 | ||
diff --git a/net/core/flow.c b/net/core/flow.c index 55789f832eda..885a2f655db0 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu) | |||
318 | /* NOTHING */; | 318 | /* NOTHING */; |
319 | 319 | ||
320 | flow_table(cpu) = (struct flow_cache_entry **) | 320 | flow_table(cpu) = (struct flow_cache_entry **) |
321 | __get_free_pages(GFP_KERNEL, order); | 321 | __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); |
322 | if (!flow_table(cpu)) | 322 | if (!flow_table(cpu)) |
323 | panic("NET: failed to allocate flow cache order %lu\n", order); | 323 | panic("NET: failed to allocate flow cache order %lu\n", order); |
324 | 324 | ||
325 | memset(flow_table(cpu), 0, PAGE_SIZE << order); | ||
326 | |||
327 | flow_hash_rnd_recalc(cpu) = 1; | 325 | flow_hash_rnd_recalc(cpu) = 1; |
328 | flow_count(cpu) = 0; | 326 | flow_count(cpu) = 0; |
329 | 327 | ||
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index b07c029e8219..3cad026764f0 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, | |||
159 | if (parm->interval < -2 || parm->interval > 3) | 159 | if (parm->interval < -2 || parm->interval > 3) |
160 | return -EINVAL; | 160 | return -EINVAL; |
161 | 161 | ||
162 | est = kmalloc(sizeof(*est), GFP_KERNEL); | 162 | est = kzalloc(sizeof(*est), GFP_KERNEL); |
163 | if (est == NULL) | 163 | if (est == NULL) |
164 | return -ENOBUFS; | 164 | return -ENOBUFS; |
165 | 165 | ||
166 | memset(est, 0, sizeof(*est)); | ||
167 | est->interval = parm->interval + 2; | 166 | est->interval = parm->interval + 2; |
168 | est->bstats = bstats; | 167 | est->bstats = bstats; |
169 | est->rate_est = rate_est; | 168 | est->rate_est = rate_est; |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0c8666872d10..2ec8693fb778 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries) | |||
284 | struct neighbour **ret; | 284 | struct neighbour **ret; |
285 | 285 | ||
286 | if (size <= PAGE_SIZE) { | 286 | if (size <= PAGE_SIZE) { |
287 | ret = kmalloc(size, GFP_ATOMIC); | 287 | ret = kzalloc(size, GFP_ATOMIC); |
288 | } else { | 288 | } else { |
289 | ret = (struct neighbour **) | 289 | ret = (struct neighbour **) |
290 | __get_free_pages(GFP_ATOMIC, get_order(size)); | 290 | __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size)); |
291 | } | 291 | } |
292 | if (ret) | ||
293 | memset(ret, 0, size); | ||
294 | |||
295 | return ret; | 292 | return ret; |
296 | } | 293 | } |
297 | 294 | ||
@@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | |||
1089 | if (hh->hh_type == protocol) | 1086 | if (hh->hh_type == protocol) |
1090 | break; | 1087 | break; |
1091 | 1088 | ||
1092 | if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { | 1089 | if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { |
1093 | memset(hh, 0, sizeof(struct hh_cache)); | ||
1094 | rwlock_init(&hh->hh_lock); | 1090 | rwlock_init(&hh->hh_lock); |
1095 | hh->hh_type = protocol; | 1091 | hh->hh_type = protocol; |
1096 | atomic_set(&hh->hh_refcnt, 0); | 1092 | atomic_set(&hh->hh_refcnt, 0); |
@@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl) | |||
1366 | tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); | 1362 | tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); |
1367 | 1363 | ||
1368 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); | 1364 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); |
1369 | tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL); | 1365 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); |
1370 | 1366 | ||
1371 | if (!tbl->hash_buckets || !tbl->phash_buckets) | 1367 | if (!tbl->hash_buckets || !tbl->phash_buckets) |
1372 | panic("cannot allocate neighbour cache hashes"); | 1368 | panic("cannot allocate neighbour cache hashes"); |
1373 | 1369 | ||
1374 | memset(tbl->phash_buckets, 0, phsize); | ||
1375 | |||
1376 | get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); | 1370 | get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); |
1377 | 1371 | ||
1378 | rwlock_init(&tbl->lock); | 1372 | rwlock_init(&tbl->lock); |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 21b68464cabb..c12990c9c603 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf) | |||
165 | operstate = IF_OPER_DOWN; | 165 | operstate = IF_OPER_DOWN; |
166 | read_unlock(&dev_base_lock); | 166 | read_unlock(&dev_base_lock); |
167 | 167 | ||
168 | if (operstate >= sizeof(operstates)) | 168 | if (operstate >= ARRAY_SIZE(operstates)) |
169 | return -EINVAL; /* should not happen */ | 169 | return -EINVAL; /* should not happen */ |
170 | 170 | ||
171 | return sprintf(buf, "%s\n", operstates[operstate]); | 171 | return sprintf(buf, "%s\n", operstates[operstate]); |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 1e44eda1fda9..79ebd75fbe4d 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
@@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
38 | { | 38 | { |
39 | const int lopt_size = sizeof(struct listen_sock) + | 39 | const int lopt_size = sizeof(struct listen_sock) + |
40 | nr_table_entries * sizeof(struct request_sock *); | 40 | nr_table_entries * sizeof(struct request_sock *); |
41 | struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL); | 41 | struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL); |
42 | 42 | ||
43 | if (lopt == NULL) | 43 | if (lopt == NULL) |
44 | return -ENOMEM; | 44 | return -ENOMEM; |
45 | 45 | ||
46 | memset(lopt, 0, lopt_size); | ||
47 | |||
48 | for (lopt->max_qlen_log = 6; | 46 | for (lopt->max_qlen_log = 6; |
49 | (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; | 47 | (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; |
50 | lopt->max_qlen_log++); | 48 | lopt->max_qlen_log++); |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index ccd3efc6a173..95a639f2e3db 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -50,7 +50,7 @@ | |||
50 | * Patrick McHardy <kaber@trash.net> | 50 | * Patrick McHardy <kaber@trash.net> |
51 | */ | 51 | */ |
52 | 52 | ||
53 | #define VERSION "0.406" | 53 | #define VERSION "0.407" |
54 | 54 | ||
55 | #include <linux/config.h> | 55 | #include <linux/config.h> |
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
@@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head) | |||
314 | kfree(container_of(head, struct leaf, rcu)); | 314 | kfree(container_of(head, struct leaf, rcu)); |
315 | } | 315 | } |
316 | 316 | ||
317 | static inline void free_leaf(struct leaf *leaf) | ||
318 | { | ||
319 | call_rcu(&leaf->rcu, __leaf_free_rcu); | ||
320 | } | ||
321 | |||
322 | static void __leaf_info_free_rcu(struct rcu_head *head) | 317 | static void __leaf_info_free_rcu(struct rcu_head *head) |
323 | { | 318 | { |
324 | kfree(container_of(head, struct leaf_info, rcu)); | 319 | kfree(container_of(head, struct leaf_info, rcu)); |
@@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head) | |||
357 | 352 | ||
358 | static inline void tnode_free(struct tnode *tn) | 353 | static inline void tnode_free(struct tnode *tn) |
359 | { | 354 | { |
360 | call_rcu(&tn->rcu, __tnode_free_rcu); | 355 | if(IS_LEAF(tn)) { |
356 | struct leaf *l = (struct leaf *) tn; | ||
357 | call_rcu_bh(&l->rcu, __leaf_free_rcu); | ||
358 | } | ||
359 | else | ||
360 | call_rcu(&tn->rcu, __tnode_free_rcu); | ||
361 | } | 361 | } |
362 | 362 | ||
363 | static struct leaf *leaf_new(void) | 363 | static struct leaf *leaf_new(void) |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 2a8adda15e11..da734c439179 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -304,13 +304,17 @@ out: | |||
304 | 304 | ||
305 | /* Creation primitives. */ | 305 | /* Creation primitives. */ |
306 | 306 | ||
307 | static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) | 307 | static struct ipq *ip_frag_intern(struct ipq *qp_in) |
308 | { | 308 | { |
309 | struct ipq *qp; | 309 | struct ipq *qp; |
310 | #ifdef CONFIG_SMP | 310 | #ifdef CONFIG_SMP |
311 | struct hlist_node *n; | 311 | struct hlist_node *n; |
312 | #endif | 312 | #endif |
313 | unsigned int hash; | ||
314 | |||
313 | write_lock(&ipfrag_lock); | 315 | write_lock(&ipfrag_lock); |
316 | hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr, | ||
317 | qp_in->protocol); | ||
314 | #ifdef CONFIG_SMP | 318 | #ifdef CONFIG_SMP |
315 | /* With SMP race we have to recheck hash table, because | 319 | /* With SMP race we have to recheck hash table, because |
316 | * such entry could be created on other cpu, while we | 320 | * such entry could be created on other cpu, while we |
@@ -345,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) | |||
345 | } | 349 | } |
346 | 350 | ||
347 | /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ | 351 | /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ |
348 | static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) | 352 | static struct ipq *ip_frag_create(struct iphdr *iph, u32 user) |
349 | { | 353 | { |
350 | struct ipq *qp; | 354 | struct ipq *qp; |
351 | 355 | ||
@@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) | |||
371 | spin_lock_init(&qp->lock); | 375 | spin_lock_init(&qp->lock); |
372 | atomic_set(&qp->refcnt, 1); | 376 | atomic_set(&qp->refcnt, 1); |
373 | 377 | ||
374 | return ip_frag_intern(hash, qp); | 378 | return ip_frag_intern(qp); |
375 | 379 | ||
376 | out_nomem: | 380 | out_nomem: |
377 | LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); | 381 | LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); |
@@ -387,11 +391,12 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
387 | __u32 saddr = iph->saddr; | 391 | __u32 saddr = iph->saddr; |
388 | __u32 daddr = iph->daddr; | 392 | __u32 daddr = iph->daddr; |
389 | __u8 protocol = iph->protocol; | 393 | __u8 protocol = iph->protocol; |
390 | unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); | 394 | unsigned int hash; |
391 | struct ipq *qp; | 395 | struct ipq *qp; |
392 | struct hlist_node *n; | 396 | struct hlist_node *n; |
393 | 397 | ||
394 | read_lock(&ipfrag_lock); | 398 | read_lock(&ipfrag_lock); |
399 | hash = ipqhashfn(id, saddr, daddr, protocol); | ||
395 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | 400 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { |
396 | if(qp->id == id && | 401 | if(qp->id == id && |
397 | qp->saddr == saddr && | 402 | qp->saddr == saddr && |
@@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
405 | } | 410 | } |
406 | read_unlock(&ipfrag_lock); | 411 | read_unlock(&ipfrag_lock); |
407 | 412 | ||
408 | return ip_frag_create(hash, iph, user); | 413 | return ip_frag_create(iph, user); |
409 | } | 414 | } |
410 | 415 | ||
411 | /* Is the fragment too far ahead to be part of ipq? */ | 416 | /* Is the fragment too far ahead to be part of ipq? */ |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 9981dcd68f11..ab99bebdcdc8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
656 | read_unlock(&ipgre_lock); | 656 | read_unlock(&ipgre_lock); |
657 | return(0); | 657 | return(0); |
658 | } | 658 | } |
659 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); | 659 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
660 | 660 | ||
661 | drop: | 661 | drop: |
662 | read_unlock(&ipgre_lock); | 662 | read_unlock(&ipgre_lock); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index f75ff1d96551..8dcba3887f04 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -86,8 +86,6 @@ | |||
86 | 86 | ||
87 | int sysctl_ip_default_ttl = IPDEFTTL; | 87 | int sysctl_ip_default_ttl = IPDEFTTL; |
88 | 88 | ||
89 | static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)); | ||
90 | |||
91 | /* Generate a checksum for an outgoing IP datagram. */ | 89 | /* Generate a checksum for an outgoing IP datagram. */ |
92 | __inline__ void ip_send_check(struct iphdr *iph) | 90 | __inline__ void ip_send_check(struct iphdr *iph) |
93 | { | 91 | { |
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
421 | * single device frame, and queue such a frame for sending. | 419 | * single device frame, and queue such a frame for sending. |
422 | */ | 420 | */ |
423 | 421 | ||
424 | static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) | 422 | int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) |
425 | { | 423 | { |
426 | struct iphdr *iph; | 424 | struct iphdr *iph; |
427 | int raw = 0; | 425 | int raw = 0; |
@@ -673,6 +671,8 @@ fail: | |||
673 | return err; | 671 | return err; |
674 | } | 672 | } |
675 | 673 | ||
674 | EXPORT_SYMBOL(ip_fragment); | ||
675 | |||
676 | int | 676 | int |
677 | ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) | 677 | ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) |
678 | { | 678 | { |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index eef07b0916a3..ea398ee43f28 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb) | |||
474 | struct iphdr *iph; | 474 | struct iphdr *iph; |
475 | struct ip_tunnel *tunnel; | 475 | struct ip_tunnel *tunnel; |
476 | 476 | ||
477 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
478 | goto out; | ||
479 | |||
480 | iph = skb->nh.iph; | 477 | iph = skb->nh.iph; |
481 | 478 | ||
482 | read_lock(&ipip_lock); | 479 | read_lock(&ipip_lock); |
@@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb) | |||
508 | } | 505 | } |
509 | read_unlock(&ipip_lock); | 506 | read_unlock(&ipip_lock); |
510 | 507 | ||
511 | out: | ||
512 | return -1; | 508 | return -1; |
513 | } | 509 | } |
514 | 510 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b5ad9ac2fbcc..6a9e34b794bc 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -133,7 +133,7 @@ struct ip_rt_info { | |||
133 | u_int8_t tos; | 133 | u_int8_t tos; |
134 | }; | 134 | }; |
135 | 135 | ||
136 | static void queue_save(const struct sk_buff *skb, struct nf_info *info) | 136 | static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) |
137 | { | 137 | { |
138 | struct ip_rt_info *rt_info = nf_info_reroute(info); | 138 | struct ip_rt_info *rt_info = nf_info_reroute(info); |
139 | 139 | ||
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info) | |||
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
149 | static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) | 149 | static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) |
150 | { | 150 | { |
151 | const struct ip_rt_info *rt_info = nf_info_reroute(info); | 151 | const struct ip_rt_info *rt_info = nf_info_reroute(info); |
152 | 152 | ||
@@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | static struct nf_queue_rerouter ip_reroute = { | 164 | unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, |
165 | .rer_size = sizeof(struct ip_rt_info), | 165 | unsigned int dataoff, u_int8_t protocol) |
166 | .save = queue_save, | 166 | { |
167 | .reroute = queue_reroute, | 167 | struct iphdr *iph = skb->nh.iph; |
168 | unsigned int csum = 0; | ||
169 | |||
170 | switch (skb->ip_summed) { | ||
171 | case CHECKSUM_HW: | ||
172 | if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) | ||
173 | break; | ||
174 | if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || | ||
175 | !csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
176 | skb->len - dataoff, protocol, | ||
177 | skb->csum)) { | ||
178 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
179 | break; | ||
180 | } | ||
181 | /* fall through */ | ||
182 | case CHECKSUM_NONE: | ||
183 | if (protocol == 0) | ||
184 | skb->csum = 0; | ||
185 | else | ||
186 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
187 | skb->len - dataoff, | ||
188 | protocol, 0); | ||
189 | csum = __skb_checksum_complete(skb); | ||
190 | } | ||
191 | return csum; | ||
192 | } | ||
193 | |||
194 | EXPORT_SYMBOL(nf_ip_checksum); | ||
195 | |||
196 | static struct nf_afinfo nf_ip_afinfo = { | ||
197 | .family = AF_INET, | ||
198 | .checksum = nf_ip_checksum, | ||
199 | .saveroute = nf_ip_saveroute, | ||
200 | .reroute = nf_ip_reroute, | ||
201 | .route_key_size = sizeof(struct ip_rt_info), | ||
168 | }; | 202 | }; |
169 | 203 | ||
170 | static int ipv4_netfilter_init(void) | 204 | static int ipv4_netfilter_init(void) |
171 | { | 205 | { |
172 | return nf_register_queue_rerouter(PF_INET, &ip_reroute); | 206 | return nf_register_afinfo(&nf_ip_afinfo); |
173 | } | 207 | } |
174 | 208 | ||
175 | static void ipv4_netfilter_fini(void) | 209 | static void ipv4_netfilter_fini(void) |
176 | { | 210 | { |
177 | nf_unregister_queue_rerouter(PF_INET); | 211 | nf_unregister_afinfo(&nf_ip_afinfo); |
178 | } | 212 | } |
179 | 213 | ||
180 | module_init(ipv4_netfilter_init); | 214 | module_init(ipv4_netfilter_init); |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 77855ccd6b43..c60fd5c4ea1e 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK | |||
69 | tristate 'Connection tracking netlink interface (EXPERIMENTAL)' | 69 | tristate 'Connection tracking netlink interface (EXPERIMENTAL)' |
70 | depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK | 70 | depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK |
71 | depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m | 71 | depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m |
72 | depends on IP_NF_NAT=n || IP_NF_NAT | ||
72 | help | 73 | help |
73 | This option enables support for a netlink-based userspace interface | 74 | This option enables support for a netlink-based userspace interface |
74 | 75 | ||
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index d0d379c7df9a..d7c472faa53b 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = { | |||
181 | 181 | ||
182 | static int __init arptable_filter_init(void) | 182 | static int __init arptable_filter_init(void) |
183 | { | 183 | { |
184 | int ret, i; | 184 | int ret; |
185 | 185 | ||
186 | /* Register table */ | 186 | /* Register table */ |
187 | ret = arpt_register_table(&packet_filter, &initial_table.repl); | 187 | ret = arpt_register_table(&packet_filter, &initial_table.repl); |
188 | if (ret < 0) | 188 | if (ret < 0) |
189 | return ret; | 189 | return ret; |
190 | 190 | ||
191 | for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) | 191 | ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); |
192 | if ((ret = nf_register_hook(&arpt_ops[i])) < 0) | 192 | if (ret < 0) |
193 | goto cleanup_hooks; | 193 | goto cleanup_table; |
194 | return ret; | 194 | return ret; |
195 | 195 | ||
196 | cleanup_hooks: | 196 | cleanup_table: |
197 | while (--i >= 0) | ||
198 | nf_unregister_hook(&arpt_ops[i]); | ||
199 | |||
200 | arpt_unregister_table(&packet_filter); | 197 | arpt_unregister_table(&packet_filter); |
201 | return ret; | 198 | return ret; |
202 | } | 199 | } |
203 | 200 | ||
204 | static void __exit arptable_filter_fini(void) | 201 | static void __exit arptable_filter_fini(void) |
205 | { | 202 | { |
206 | unsigned int i; | 203 | nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); |
207 | |||
208 | for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) | ||
209 | nf_unregister_hook(&arpt_ops[i]); | ||
210 | |||
211 | arpt_unregister_table(&packet_filter); | 204 | arpt_unregister_table(&packet_filter); |
212 | } | 205 | } |
213 | 206 | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index daeb1395faa4..2c2fb700d835 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c | |||
@@ -9,37 +9,6 @@ | |||
9 | * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 9 | * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> |
10 | * | 10 | * |
11 | * For more information, please see http://nath323.sourceforge.net/ | 11 | * For more information, please see http://nath323.sourceforge.net/ |
12 | * | ||
13 | * Changes: | ||
14 | * 2006-02-01 - initial version 0.1 | ||
15 | * | ||
16 | * 2006-02-20 - version 0.2 | ||
17 | * 1. Changed source format to follow kernel conventions | ||
18 | * 2. Deleted some unnecessary structures | ||
19 | * 3. Minor fixes | ||
20 | * | ||
21 | * 2006-03-10 - version 0.3 | ||
22 | * 1. Added support for multiple TPKTs in one packet (suggested by | ||
23 | * Patrick McHardy) | ||
24 | * 2. Avoid excessive stack usage (based on Patrick McHardy's patch) | ||
25 | * 3. Added support for non-linear skb (based on Patrick McHardy's patch) | ||
26 | * 4. Fixed missing H.245 module owner (Patrick McHardy) | ||
27 | * 5. Avoid long RAS expectation chains (Patrick McHardy) | ||
28 | * 6. Fixed incorrect __exit attribute (Patrick McHardy) | ||
29 | * 7. Eliminated unnecessary return code | ||
30 | * 8. Fixed incorrect use of NAT data from conntrack code (suggested by | ||
31 | * Patrick McHardy) | ||
32 | * 9. Fixed TTL calculation error in RCF | ||
33 | * 10. Added TTL support in RRQ | ||
34 | * 11. Better support for separate TPKT header and data | ||
35 | * | ||
36 | * 2006-03-15 - version 0.4 | ||
37 | * 1. Added support for T.120 channels | ||
38 | * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) | ||
39 | * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy) | ||
40 | * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by | ||
41 | * Patrick McHardy) | ||
42 | * 5. Reset next TPKT data length in get_tpkt_data() | ||
43 | */ | 12 | */ |
44 | 13 | ||
45 | #include <linux/config.h> | 14 | #include <linux/config.h> |
@@ -54,8 +23,6 @@ | |||
54 | #include <linux/netfilter_ipv4/ip_conntrack_h323.h> | 23 | #include <linux/netfilter_ipv4/ip_conntrack_h323.h> |
55 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
56 | 25 | ||
57 | #include "ip_conntrack_helper_h323_asn1.h" | ||
58 | |||
59 | #if 0 | 26 | #if 0 |
60 | #define DEBUGP printk | 27 | #define DEBUGP printk |
61 | #else | 28 | #else |
@@ -63,6 +30,10 @@ | |||
63 | #endif | 30 | #endif |
64 | 31 | ||
65 | /* Parameters */ | 32 | /* Parameters */ |
33 | static unsigned int default_rrq_ttl = 300; | ||
34 | module_param(default_rrq_ttl, uint, 0600); | ||
35 | MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ"); | ||
36 | |||
66 | static int gkrouted_only = 1; | 37 | static int gkrouted_only = 1; |
67 | module_param(gkrouted_only, int, 0600); | 38 | module_param(gkrouted_only, int, 0600); |
68 | MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); | 39 | MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); |
@@ -222,8 +193,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
222 | } | 193 | } |
223 | 194 | ||
224 | /****************************************************************************/ | 195 | /****************************************************************************/ |
225 | int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, | 196 | static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, |
226 | u_int32_t * ip, u_int16_t * port) | 197 | u_int32_t * ip, u_int16_t * port) |
227 | { | 198 | { |
228 | unsigned char *p; | 199 | unsigned char *p; |
229 | 200 | ||
@@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1302 | DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); | 1273 | DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); |
1303 | info->timeout = rrq->timeToLive; | 1274 | info->timeout = rrq->timeToLive; |
1304 | } else | 1275 | } else |
1305 | info->timeout = 0; | 1276 | info->timeout = default_rrq_ttl; |
1306 | 1277 | ||
1307 | return 0; | 1278 | return 0; |
1308 | } | 1279 | } |
@@ -1713,18 +1684,17 @@ static int __init init(void) | |||
1713 | module_init(init); | 1684 | module_init(init); |
1714 | module_exit(fini); | 1685 | module_exit(fini); |
1715 | 1686 | ||
1716 | EXPORT_SYMBOL(get_h245_addr); | 1687 | EXPORT_SYMBOL_GPL(get_h225_addr); |
1717 | EXPORT_SYMBOL(get_h225_addr); | 1688 | EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect); |
1718 | EXPORT_SYMBOL(ip_conntrack_h245_expect); | 1689 | EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect); |
1719 | EXPORT_SYMBOL(ip_conntrack_q931_expect); | 1690 | EXPORT_SYMBOL_GPL(set_h245_addr_hook); |
1720 | EXPORT_SYMBOL(set_h245_addr_hook); | 1691 | EXPORT_SYMBOL_GPL(set_h225_addr_hook); |
1721 | EXPORT_SYMBOL(set_h225_addr_hook); | 1692 | EXPORT_SYMBOL_GPL(set_sig_addr_hook); |
1722 | EXPORT_SYMBOL(set_sig_addr_hook); | 1693 | EXPORT_SYMBOL_GPL(set_ras_addr_hook); |
1723 | EXPORT_SYMBOL(set_ras_addr_hook); | 1694 | EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); |
1724 | EXPORT_SYMBOL(nat_rtp_rtcp_hook); | 1695 | EXPORT_SYMBOL_GPL(nat_t120_hook); |
1725 | EXPORT_SYMBOL(nat_t120_hook); | 1696 | EXPORT_SYMBOL_GPL(nat_h245_hook); |
1726 | EXPORT_SYMBOL(nat_h245_hook); | 1697 | EXPORT_SYMBOL_GPL(nat_q931_hook); |
1727 | EXPORT_SYMBOL(nat_q931_hook); | ||
1728 | 1698 | ||
1729 | MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); | 1699 | MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); |
1730 | MODULE_DESCRIPTION("H.323 connection tracking helper"); | 1700 | MODULE_DESCRIPTION("H.323 connection tracking helper"); |
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index afa525129b51..48078002e450 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #else | 15 | #else |
16 | #include <stdio.h> | 16 | #include <stdio.h> |
17 | #endif | 17 | #endif |
18 | #include "ip_conntrack_helper_h323_asn1.h" | 18 | #include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> |
19 | 19 | ||
20 | /* Trace Flag */ | 20 | /* Trace Flag */ |
21 | #ifndef H323_TRACE | 21 | #ifndef H323_TRACE |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 3021af0910f1..d8b14a9010a6 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c | |||
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, | |||
224 | } | 224 | } |
225 | 225 | ||
226 | /* See ip_conntrack_proto_tcp.c */ | 226 | /* See ip_conntrack_proto_tcp.c */ |
227 | if (hooknum != NF_IP_PRE_ROUTING) | 227 | if (hooknum == NF_IP_PRE_ROUTING && |
228 | goto checksum_skipped; | 228 | nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) { |
229 | 229 | if (LOG_INVALID(IPPROTO_ICMP)) | |
230 | switch (skb->ip_summed) { | 230 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
231 | case CHECKSUM_HW: | 231 | "ip_ct_icmp: bad ICMP checksum "); |
232 | if (!(u16)csum_fold(skb->csum)) | 232 | return -NF_ACCEPT; |
233 | break; | ||
234 | /* fall through */ | ||
235 | case CHECKSUM_NONE: | ||
236 | skb->csum = 0; | ||
237 | if (__skb_checksum_complete(skb)) { | ||
238 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
239 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | ||
240 | "ip_ct_icmp: bad ICMP checksum "); | ||
241 | return -NF_ACCEPT; | ||
242 | } | ||
243 | } | 233 | } |
244 | 234 | ||
245 | checksum_skipped: | ||
246 | /* | 235 | /* |
247 | * 18 is the highest 'known' ICMP type. Anything else is a mystery | 236 | * 18 is the highest 'known' ICMP type. Anything else is a mystery |
248 | * | 237 | * |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index e0dc37063545..062b252b58ad 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c | |||
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb, | |||
870 | * and moreover root might send raw packets. | 870 | * and moreover root might send raw packets. |
871 | */ | 871 | */ |
872 | /* FIXME: Source route IP option packets --RR */ | 872 | /* FIXME: Source route IP option packets --RR */ |
873 | if (hooknum == NF_IP_PRE_ROUTING | 873 | if (hooknum == NF_IP_PRE_ROUTING && |
874 | && skb->ip_summed != CHECKSUM_UNNECESSARY | 874 | nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) { |
875 | && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, | ||
876 | skb->ip_summed == CHECKSUM_HW ? skb->csum | ||
877 | : skb_checksum(skb, iph->ihl*4, tcplen, 0))) { | ||
878 | if (LOG_INVALID(IPPROTO_TCP)) | 875 | if (LOG_INVALID(IPPROTO_TCP)) |
879 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | 876 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
880 | "ip_ct_tcp: bad TCP checksum "); | 877 | "ip_ct_tcp: bad TCP checksum "); |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 55b7d3210adf..70899868783b 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c | |||
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, | |||
120 | * because the semantic of CHECKSUM_HW is different there | 120 | * because the semantic of CHECKSUM_HW is different there |
121 | * and moreover root might send raw packets. | 121 | * and moreover root might send raw packets. |
122 | * FIXME: Source route IP option packets --RR */ | 122 | * FIXME: Source route IP option packets --RR */ |
123 | if (hooknum == NF_IP_PRE_ROUTING | 123 | if (hooknum == NF_IP_PRE_ROUTING && |
124 | && skb->ip_summed != CHECKSUM_UNNECESSARY | 124 | nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) { |
125 | && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP, | ||
126 | skb->ip_summed == CHECKSUM_HW ? skb->csum | ||
127 | : skb_checksum(skb, iph->ihl*4, udplen, 0))) { | ||
128 | if (LOG_INVALID(IPPROTO_UDP)) | 125 | if (LOG_INVALID(IPPROTO_UDP)) |
129 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | 126 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
130 | "ip_ct_udp: bad UDP checksum "); | 127 | "ip_ct_udp: bad UDP checksum "); |
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 52076026db36..929d61f7be91 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c | |||
@@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum, | |||
469 | 469 | ||
470 | /* Connection tracking may drop packets, but never alters them, so | 470 | /* Connection tracking may drop packets, but never alters them, so |
471 | make it the first hook. */ | 471 | make it the first hook. */ |
472 | static struct nf_hook_ops ip_conntrack_defrag_ops = { | 472 | static struct nf_hook_ops ip_conntrack_ops[] = { |
473 | .hook = ip_conntrack_defrag, | 473 | { |
474 | .owner = THIS_MODULE, | 474 | .hook = ip_conntrack_defrag, |
475 | .pf = PF_INET, | 475 | .owner = THIS_MODULE, |
476 | .hooknum = NF_IP_PRE_ROUTING, | 476 | .pf = PF_INET, |
477 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | 477 | .hooknum = NF_IP_PRE_ROUTING, |
478 | }; | 478 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, |
479 | 479 | }, | |
480 | static struct nf_hook_ops ip_conntrack_in_ops = { | 480 | { |
481 | .hook = ip_conntrack_in, | 481 | .hook = ip_conntrack_in, |
482 | .owner = THIS_MODULE, | 482 | .owner = THIS_MODULE, |
483 | .pf = PF_INET, | 483 | .pf = PF_INET, |
484 | .hooknum = NF_IP_PRE_ROUTING, | 484 | .hooknum = NF_IP_PRE_ROUTING, |
485 | .priority = NF_IP_PRI_CONNTRACK, | 485 | .priority = NF_IP_PRI_CONNTRACK, |
486 | }; | 486 | }, |
487 | 487 | { | |
488 | static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = { | 488 | .hook = ip_conntrack_defrag, |
489 | .hook = ip_conntrack_defrag, | 489 | .owner = THIS_MODULE, |
490 | .owner = THIS_MODULE, | 490 | .pf = PF_INET, |
491 | .pf = PF_INET, | 491 | .hooknum = NF_IP_LOCAL_OUT, |
492 | .hooknum = NF_IP_LOCAL_OUT, | 492 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, |
493 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | 493 | }, |
494 | }; | 494 | { |
495 | 495 | .hook = ip_conntrack_local, | |
496 | static struct nf_hook_ops ip_conntrack_local_out_ops = { | 496 | .owner = THIS_MODULE, |
497 | .hook = ip_conntrack_local, | 497 | .pf = PF_INET, |
498 | .owner = THIS_MODULE, | 498 | .hooknum = NF_IP_LOCAL_OUT, |
499 | .pf = PF_INET, | 499 | .priority = NF_IP_PRI_CONNTRACK, |
500 | .hooknum = NF_IP_LOCAL_OUT, | 500 | }, |
501 | .priority = NF_IP_PRI_CONNTRACK, | 501 | { |
502 | }; | 502 | .hook = ip_conntrack_help, |
503 | 503 | .owner = THIS_MODULE, | |
504 | /* helpers */ | 504 | .pf = PF_INET, |
505 | static struct nf_hook_ops ip_conntrack_helper_out_ops = { | 505 | .hooknum = NF_IP_POST_ROUTING, |
506 | .hook = ip_conntrack_help, | 506 | .priority = NF_IP_PRI_CONNTRACK_HELPER, |
507 | .owner = THIS_MODULE, | 507 | }, |
508 | .pf = PF_INET, | 508 | { |
509 | .hooknum = NF_IP_POST_ROUTING, | 509 | .hook = ip_conntrack_help, |
510 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | 510 | .owner = THIS_MODULE, |
511 | }; | 511 | .pf = PF_INET, |
512 | 512 | .hooknum = NF_IP_LOCAL_IN, | |
513 | static struct nf_hook_ops ip_conntrack_helper_in_ops = { | 513 | .priority = NF_IP_PRI_CONNTRACK_HELPER, |
514 | .hook = ip_conntrack_help, | 514 | }, |
515 | .owner = THIS_MODULE, | 515 | { |
516 | .pf = PF_INET, | 516 | .hook = ip_confirm, |
517 | .hooknum = NF_IP_LOCAL_IN, | 517 | .owner = THIS_MODULE, |
518 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | 518 | .pf = PF_INET, |
519 | }; | 519 | .hooknum = NF_IP_POST_ROUTING, |
520 | 520 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | |
521 | /* Refragmenter; last chance. */ | 521 | }, |
522 | static struct nf_hook_ops ip_conntrack_out_ops = { | 522 | { |
523 | .hook = ip_confirm, | 523 | .hook = ip_confirm, |
524 | .owner = THIS_MODULE, | 524 | .owner = THIS_MODULE, |
525 | .pf = PF_INET, | 525 | .pf = PF_INET, |
526 | .hooknum = NF_IP_POST_ROUTING, | 526 | .hooknum = NF_IP_LOCAL_IN, |
527 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | 527 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, |
528 | }; | 528 | }, |
529 | |||
530 | static struct nf_hook_ops ip_conntrack_local_in_ops = { | ||
531 | .hook = ip_confirm, | ||
532 | .owner = THIS_MODULE, | ||
533 | .pf = PF_INET, | ||
534 | .hooknum = NF_IP_LOCAL_IN, | ||
535 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | ||
536 | }; | 529 | }; |
537 | 530 | ||
538 | /* Sysctl support */ | 531 | /* Sysctl support */ |
@@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = { | |||
783 | EXPORT_SYMBOL(ip_ct_log_invalid); | 776 | EXPORT_SYMBOL(ip_ct_log_invalid); |
784 | #endif /* CONFIG_SYSCTL */ | 777 | #endif /* CONFIG_SYSCTL */ |
785 | 778 | ||
786 | static int init_or_cleanup(int init) | 779 | /* FIXME: Allow NULL functions and sub in pointers to generic for |
780 | them. --RR */ | ||
781 | int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) | ||
782 | { | ||
783 | int ret = 0; | ||
784 | |||
785 | write_lock_bh(&ip_conntrack_lock); | ||
786 | if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { | ||
787 | ret = -EBUSY; | ||
788 | goto out; | ||
789 | } | ||
790 | ip_ct_protos[proto->proto] = proto; | ||
791 | out: | ||
792 | write_unlock_bh(&ip_conntrack_lock); | ||
793 | return ret; | ||
794 | } | ||
795 | |||
796 | void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) | ||
797 | { | ||
798 | write_lock_bh(&ip_conntrack_lock); | ||
799 | ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; | ||
800 | write_unlock_bh(&ip_conntrack_lock); | ||
801 | |||
802 | /* Somebody could be still looking at the proto in bh. */ | ||
803 | synchronize_net(); | ||
804 | |||
805 | /* Remove all contrack entries for this protocol */ | ||
806 | ip_ct_iterate_cleanup(kill_proto, &proto->proto); | ||
807 | } | ||
808 | |||
809 | static int __init ip_conntrack_standalone_init(void) | ||
787 | { | 810 | { |
788 | #ifdef CONFIG_PROC_FS | 811 | #ifdef CONFIG_PROC_FS |
789 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; | 812 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; |
790 | #endif | 813 | #endif |
791 | int ret = 0; | 814 | int ret = 0; |
792 | 815 | ||
793 | if (!init) goto cleanup; | ||
794 | |||
795 | ret = ip_conntrack_init(); | 816 | ret = ip_conntrack_init(); |
796 | if (ret < 0) | 817 | if (ret < 0) |
797 | goto cleanup_nothing; | 818 | return ret; |
798 | 819 | ||
799 | #ifdef CONFIG_PROC_FS | 820 | #ifdef CONFIG_PROC_FS |
800 | ret = -ENOMEM; | 821 | ret = -ENOMEM; |
@@ -813,78 +834,25 @@ static int init_or_cleanup(int init) | |||
813 | proc_stat->owner = THIS_MODULE; | 834 | proc_stat->owner = THIS_MODULE; |
814 | #endif | 835 | #endif |
815 | 836 | ||
816 | ret = nf_register_hook(&ip_conntrack_defrag_ops); | 837 | ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); |
817 | if (ret < 0) { | 838 | if (ret < 0) { |
818 | printk("ip_conntrack: can't register pre-routing defrag hook.\n"); | 839 | printk("ip_conntrack: can't register hooks.\n"); |
819 | goto cleanup_proc_stat; | 840 | goto cleanup_proc_stat; |
820 | } | 841 | } |
821 | ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops); | ||
822 | if (ret < 0) { | ||
823 | printk("ip_conntrack: can't register local_out defrag hook.\n"); | ||
824 | goto cleanup_defragops; | ||
825 | } | ||
826 | ret = nf_register_hook(&ip_conntrack_in_ops); | ||
827 | if (ret < 0) { | ||
828 | printk("ip_conntrack: can't register pre-routing hook.\n"); | ||
829 | goto cleanup_defraglocalops; | ||
830 | } | ||
831 | ret = nf_register_hook(&ip_conntrack_local_out_ops); | ||
832 | if (ret < 0) { | ||
833 | printk("ip_conntrack: can't register local out hook.\n"); | ||
834 | goto cleanup_inops; | ||
835 | } | ||
836 | ret = nf_register_hook(&ip_conntrack_helper_in_ops); | ||
837 | if (ret < 0) { | ||
838 | printk("ip_conntrack: can't register local in helper hook.\n"); | ||
839 | goto cleanup_inandlocalops; | ||
840 | } | ||
841 | ret = nf_register_hook(&ip_conntrack_helper_out_ops); | ||
842 | if (ret < 0) { | ||
843 | printk("ip_conntrack: can't register postrouting helper hook.\n"); | ||
844 | goto cleanup_helperinops; | ||
845 | } | ||
846 | ret = nf_register_hook(&ip_conntrack_out_ops); | ||
847 | if (ret < 0) { | ||
848 | printk("ip_conntrack: can't register post-routing hook.\n"); | ||
849 | goto cleanup_helperoutops; | ||
850 | } | ||
851 | ret = nf_register_hook(&ip_conntrack_local_in_ops); | ||
852 | if (ret < 0) { | ||
853 | printk("ip_conntrack: can't register local in hook.\n"); | ||
854 | goto cleanup_inoutandlocalops; | ||
855 | } | ||
856 | #ifdef CONFIG_SYSCTL | 842 | #ifdef CONFIG_SYSCTL |
857 | ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); | 843 | ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); |
858 | if (ip_ct_sysctl_header == NULL) { | 844 | if (ip_ct_sysctl_header == NULL) { |
859 | printk("ip_conntrack: can't register to sysctl.\n"); | 845 | printk("ip_conntrack: can't register to sysctl.\n"); |
860 | ret = -ENOMEM; | 846 | ret = -ENOMEM; |
861 | goto cleanup_localinops; | 847 | goto cleanup_hooks; |
862 | } | 848 | } |
863 | #endif | 849 | #endif |
864 | |||
865 | return ret; | 850 | return ret; |
866 | 851 | ||
867 | cleanup: | ||
868 | synchronize_net(); | ||
869 | #ifdef CONFIG_SYSCTL | 852 | #ifdef CONFIG_SYSCTL |
870 | unregister_sysctl_table(ip_ct_sysctl_header); | 853 | cleanup_hooks: |
871 | cleanup_localinops: | 854 | nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); |
872 | #endif | 855 | #endif |
873 | nf_unregister_hook(&ip_conntrack_local_in_ops); | ||
874 | cleanup_inoutandlocalops: | ||
875 | nf_unregister_hook(&ip_conntrack_out_ops); | ||
876 | cleanup_helperoutops: | ||
877 | nf_unregister_hook(&ip_conntrack_helper_out_ops); | ||
878 | cleanup_helperinops: | ||
879 | nf_unregister_hook(&ip_conntrack_helper_in_ops); | ||
880 | cleanup_inandlocalops: | ||
881 | nf_unregister_hook(&ip_conntrack_local_out_ops); | ||
882 | cleanup_inops: | ||
883 | nf_unregister_hook(&ip_conntrack_in_ops); | ||
884 | cleanup_defraglocalops: | ||
885 | nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); | ||
886 | cleanup_defragops: | ||
887 | nf_unregister_hook(&ip_conntrack_defrag_ops); | ||
888 | cleanup_proc_stat: | 856 | cleanup_proc_stat: |
889 | #ifdef CONFIG_PROC_FS | 857 | #ifdef CONFIG_PROC_FS |
890 | remove_proc_entry("ip_conntrack", proc_net_stat); | 858 | remove_proc_entry("ip_conntrack", proc_net_stat); |
@@ -895,48 +863,22 @@ static int init_or_cleanup(int init) | |||
895 | cleanup_init: | 863 | cleanup_init: |
896 | #endif /* CONFIG_PROC_FS */ | 864 | #endif /* CONFIG_PROC_FS */ |
897 | ip_conntrack_cleanup(); | 865 | ip_conntrack_cleanup(); |
898 | cleanup_nothing: | ||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | /* FIXME: Allow NULL functions and sub in pointers to generic for | ||
903 | them. --RR */ | ||
904 | int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) | ||
905 | { | ||
906 | int ret = 0; | ||
907 | |||
908 | write_lock_bh(&ip_conntrack_lock); | ||
909 | if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { | ||
910 | ret = -EBUSY; | ||
911 | goto out; | ||
912 | } | ||
913 | ip_ct_protos[proto->proto] = proto; | ||
914 | out: | ||
915 | write_unlock_bh(&ip_conntrack_lock); | ||
916 | return ret; | 866 | return ret; |
917 | } | 867 | } |
918 | 868 | ||
919 | void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) | ||
920 | { | ||
921 | write_lock_bh(&ip_conntrack_lock); | ||
922 | ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; | ||
923 | write_unlock_bh(&ip_conntrack_lock); | ||
924 | |||
925 | /* Somebody could be still looking at the proto in bh. */ | ||
926 | synchronize_net(); | ||
927 | |||
928 | /* Remove all contrack entries for this protocol */ | ||
929 | ip_ct_iterate_cleanup(kill_proto, &proto->proto); | ||
930 | } | ||
931 | |||
932 | static int __init ip_conntrack_standalone_init(void) | ||
933 | { | ||
934 | return init_or_cleanup(1); | ||
935 | } | ||
936 | |||
937 | static void __exit ip_conntrack_standalone_fini(void) | 869 | static void __exit ip_conntrack_standalone_fini(void) |
938 | { | 870 | { |
939 | init_or_cleanup(0); | 871 | synchronize_net(); |
872 | #ifdef CONFIG_SYSCTL | ||
873 | unregister_sysctl_table(ip_ct_sysctl_header); | ||
874 | #endif | ||
875 | nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); | ||
876 | #ifdef CONFIG_PROC_FS | ||
877 | remove_proc_entry("ip_conntrack", proc_net_stat); | ||
878 | proc_net_remove("ip_conntrack_expect"); | ||
879 | proc_net_remove("ip_conntrack"); | ||
880 | #endif /* CONFIG_PROC_FS */ | ||
881 | ip_conntrack_cleanup(); | ||
940 | } | 882 | } |
941 | 883 | ||
942 | module_init(ip_conntrack_standalone_init); | 884 | module_init(ip_conntrack_standalone_init); |
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c index a0bc883928c0..d45663d137a7 100644 --- a/net/ipv4/netfilter/ip_nat_helper_h323.c +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c | |||
@@ -7,24 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Based on the 'brute force' H.323 NAT module by | 8 | * Based on the 'brute force' H.323 NAT module by |
9 | * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 9 | * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> |
10 | * | ||
11 | * Changes: | ||
12 | * 2006-02-01 - initial version 0.1 | ||
13 | * | ||
14 | * 2006-02-20 - version 0.2 | ||
15 | * 1. Changed source format to follow kernel conventions | ||
16 | * 2. Deleted some unnecessary structures | ||
17 | * 3. Minor fixes | ||
18 | * | ||
19 | * 2006-03-10 - version 0.3 | ||
20 | * 1. Added support for multiple TPKTs in one packet (suggested by | ||
21 | * Patrick McHardy) | ||
22 | * 2. Added support for non-linear skb (based on Patrick McHardy's patch) | ||
23 | * 3. Eliminated unnecessary return code | ||
24 | * | ||
25 | * 2006-03-15 - version 0.4 | ||
26 | * 1. Added support for T.120 channels | ||
27 | * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) | ||
28 | */ | 10 | */ |
29 | 11 | ||
30 | #include <linux/module.h> | 12 | #include <linux/module.h> |
@@ -41,65 +23,12 @@ | |||
41 | #include <linux/netfilter_ipv4/ip_conntrack_h323.h> | 23 | #include <linux/netfilter_ipv4/ip_conntrack_h323.h> |
42 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | 24 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> |
43 | 25 | ||
44 | #include "ip_conntrack_helper_h323_asn1.h" | ||
45 | |||
46 | #if 0 | 26 | #if 0 |
47 | #define DEBUGP printk | 27 | #define DEBUGP printk |
48 | #else | 28 | #else |
49 | #define DEBUGP(format, args...) | 29 | #define DEBUGP(format, args...) |
50 | #endif | 30 | #endif |
51 | 31 | ||
52 | extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, | ||
53 | u_int32_t * ip, u_int16_t * port); | ||
54 | extern int get_h225_addr(unsigned char *data, TransportAddress * addr, | ||
55 | u_int32_t * ip, u_int16_t * port); | ||
56 | extern void ip_conntrack_h245_expect(struct ip_conntrack *new, | ||
57 | struct ip_conntrack_expect *this); | ||
58 | extern void ip_conntrack_q931_expect(struct ip_conntrack *new, | ||
59 | struct ip_conntrack_expect *this); | ||
60 | extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, | ||
61 | unsigned char **data, int dataoff, | ||
62 | H245_TransportAddress * addr, | ||
63 | u_int32_t ip, u_int16_t port); | ||
64 | extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, | ||
65 | unsigned char **data, int dataoff, | ||
66 | TransportAddress * addr, | ||
67 | u_int32_t ip, u_int16_t port); | ||
68 | extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, | ||
69 | struct ip_conntrack * ct, | ||
70 | enum ip_conntrack_info ctinfo, | ||
71 | unsigned char **data, | ||
72 | TransportAddress * addr, int count); | ||
73 | extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, | ||
74 | struct ip_conntrack * ct, | ||
75 | enum ip_conntrack_info ctinfo, | ||
76 | unsigned char **data, | ||
77 | TransportAddress * addr, int count); | ||
78 | extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, | ||
79 | struct ip_conntrack * ct, | ||
80 | enum ip_conntrack_info ctinfo, | ||
81 | unsigned char **data, int dataoff, | ||
82 | H245_TransportAddress * addr, | ||
83 | u_int16_t port, u_int16_t rtp_port, | ||
84 | struct ip_conntrack_expect * rtp_exp, | ||
85 | struct ip_conntrack_expect * rtcp_exp); | ||
86 | extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
87 | enum ip_conntrack_info ctinfo, | ||
88 | unsigned char **data, int dataoff, | ||
89 | H245_TransportAddress * addr, u_int16_t port, | ||
90 | struct ip_conntrack_expect * exp); | ||
91 | extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
92 | enum ip_conntrack_info ctinfo, | ||
93 | unsigned char **data, int dataoff, | ||
94 | TransportAddress * addr, u_int16_t port, | ||
95 | struct ip_conntrack_expect * exp); | ||
96 | extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, | ||
97 | enum ip_conntrack_info ctinfo, | ||
98 | unsigned char **data, TransportAddress * addr, | ||
99 | int idx, u_int16_t port, | ||
100 | struct ip_conntrack_expect * exp); | ||
101 | |||
102 | |||
103 | /****************************************************************************/ | 32 | /****************************************************************************/ |
104 | static int set_addr(struct sk_buff **pskb, | 33 | static int set_addr(struct sk_buff **pskb, |
105 | unsigned char **data, int dataoff, | 34 | unsigned char **data, int dataoff, |
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index efba8c4e42e0..1aba926c1cb0 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c | |||
@@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = { | |||
279 | .target = ipt_dnat_target, | 279 | .target = ipt_dnat_target, |
280 | .targetsize = sizeof(struct ip_nat_multi_range_compat), | 280 | .targetsize = sizeof(struct ip_nat_multi_range_compat), |
281 | .table = "nat", | 281 | .table = "nat", |
282 | .hooks = 1 << NF_IP_PRE_ROUTING, | 282 | .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), |
283 | .checkentry = ipt_dnat_checkentry, | 283 | .checkentry = ipt_dnat_checkentry, |
284 | }; | 284 | }; |
285 | 285 | ||
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 3505b0de2e04..8f760b28617e 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum, | |||
299 | 299 | ||
300 | /* We must be after connection tracking and before packet filtering. */ | 300 | /* We must be after connection tracking and before packet filtering. */ |
301 | 301 | ||
302 | /* Before packet filtering, change destination */ | 302 | static struct nf_hook_ops ip_nat_ops[] = { |
303 | static struct nf_hook_ops ip_nat_in_ops = { | 303 | /* Before packet filtering, change destination */ |
304 | .hook = ip_nat_in, | 304 | { |
305 | .owner = THIS_MODULE, | 305 | .hook = ip_nat_in, |
306 | .pf = PF_INET, | 306 | .owner = THIS_MODULE, |
307 | .hooknum = NF_IP_PRE_ROUTING, | 307 | .pf = PF_INET, |
308 | .priority = NF_IP_PRI_NAT_DST, | 308 | .hooknum = NF_IP_PRE_ROUTING, |
309 | .priority = NF_IP_PRI_NAT_DST, | ||
310 | }, | ||
311 | /* After packet filtering, change source */ | ||
312 | { | ||
313 | .hook = ip_nat_out, | ||
314 | .owner = THIS_MODULE, | ||
315 | .pf = PF_INET, | ||
316 | .hooknum = NF_IP_POST_ROUTING, | ||
317 | .priority = NF_IP_PRI_NAT_SRC, | ||
318 | }, | ||
319 | /* After conntrack, adjust sequence number */ | ||
320 | { | ||
321 | .hook = ip_nat_adjust, | ||
322 | .owner = THIS_MODULE, | ||
323 | .pf = PF_INET, | ||
324 | .hooknum = NF_IP_POST_ROUTING, | ||
325 | .priority = NF_IP_PRI_NAT_SEQ_ADJUST, | ||
326 | }, | ||
327 | /* Before packet filtering, change destination */ | ||
328 | { | ||
329 | .hook = ip_nat_local_fn, | ||
330 | .owner = THIS_MODULE, | ||
331 | .pf = PF_INET, | ||
332 | .hooknum = NF_IP_LOCAL_OUT, | ||
333 | .priority = NF_IP_PRI_NAT_DST, | ||
334 | }, | ||
335 | /* After packet filtering, change source */ | ||
336 | { | ||
337 | .hook = ip_nat_fn, | ||
338 | .owner = THIS_MODULE, | ||
339 | .pf = PF_INET, | ||
340 | .hooknum = NF_IP_LOCAL_IN, | ||
341 | .priority = NF_IP_PRI_NAT_SRC, | ||
342 | }, | ||
343 | /* After conntrack, adjust sequence number */ | ||
344 | { | ||
345 | .hook = ip_nat_adjust, | ||
346 | .owner = THIS_MODULE, | ||
347 | .pf = PF_INET, | ||
348 | .hooknum = NF_IP_LOCAL_IN, | ||
349 | .priority = NF_IP_PRI_NAT_SEQ_ADJUST, | ||
350 | }, | ||
309 | }; | 351 | }; |
310 | 352 | ||
311 | /* After packet filtering, change source */ | 353 | static int __init ip_nat_standalone_init(void) |
312 | static struct nf_hook_ops ip_nat_out_ops = { | ||
313 | .hook = ip_nat_out, | ||
314 | .owner = THIS_MODULE, | ||
315 | .pf = PF_INET, | ||
316 | .hooknum = NF_IP_POST_ROUTING, | ||
317 | .priority = NF_IP_PRI_NAT_SRC, | ||
318 | }; | ||
319 | |||
320 | /* After conntrack, adjust sequence number */ | ||
321 | static struct nf_hook_ops ip_nat_adjust_out_ops = { | ||
322 | .hook = ip_nat_adjust, | ||
323 | .owner = THIS_MODULE, | ||
324 | .pf = PF_INET, | ||
325 | .hooknum = NF_IP_POST_ROUTING, | ||
326 | .priority = NF_IP_PRI_NAT_SEQ_ADJUST, | ||
327 | }; | ||
328 | |||
329 | /* Before packet filtering, change destination */ | ||
330 | static struct nf_hook_ops ip_nat_local_out_ops = { | ||
331 | .hook = ip_nat_local_fn, | ||
332 | .owner = THIS_MODULE, | ||
333 | .pf = PF_INET, | ||
334 | .hooknum = NF_IP_LOCAL_OUT, | ||
335 | .priority = NF_IP_PRI_NAT_DST, | ||
336 | }; | ||
337 | |||
338 | /* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */ | ||
339 | static struct nf_hook_ops ip_nat_local_in_ops = { | ||
340 | .hook = ip_nat_fn, | ||
341 | .owner = THIS_MODULE, | ||
342 | .pf = PF_INET, | ||
343 | .hooknum = NF_IP_LOCAL_IN, | ||
344 | .priority = NF_IP_PRI_NAT_SRC, | ||
345 | }; | ||
346 | |||
347 | /* After conntrack, adjust sequence number */ | ||
348 | static struct nf_hook_ops ip_nat_adjust_in_ops = { | ||
349 | .hook = ip_nat_adjust, | ||
350 | .owner = THIS_MODULE, | ||
351 | .pf = PF_INET, | ||
352 | .hooknum = NF_IP_LOCAL_IN, | ||
353 | .priority = NF_IP_PRI_NAT_SEQ_ADJUST, | ||
354 | }; | ||
355 | |||
356 | |||
357 | static int init_or_cleanup(int init) | ||
358 | { | 354 | { |
359 | int ret = 0; | 355 | int ret = 0; |
360 | 356 | ||
361 | need_conntrack(); | 357 | need_conntrack(); |
362 | 358 | ||
363 | if (!init) goto cleanup; | ||
364 | |||
365 | #ifdef CONFIG_XFRM | 359 | #ifdef CONFIG_XFRM |
366 | BUG_ON(ip_nat_decode_session != NULL); | 360 | BUG_ON(ip_nat_decode_session != NULL); |
367 | ip_nat_decode_session = nat_decode_session; | 361 | ip_nat_decode_session = nat_decode_session; |
@@ -371,50 +365,13 @@ static int init_or_cleanup(int init) | |||
371 | printk("ip_nat_init: can't setup rules.\n"); | 365 | printk("ip_nat_init: can't setup rules.\n"); |
372 | goto cleanup_decode_session; | 366 | goto cleanup_decode_session; |
373 | } | 367 | } |
374 | ret = nf_register_hook(&ip_nat_in_ops); | 368 | ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops)); |
375 | if (ret < 0) { | 369 | if (ret < 0) { |
376 | printk("ip_nat_init: can't register in hook.\n"); | 370 | printk("ip_nat_init: can't register hooks.\n"); |
377 | goto cleanup_rule_init; | 371 | goto cleanup_rule_init; |
378 | } | 372 | } |
379 | ret = nf_register_hook(&ip_nat_out_ops); | ||
380 | if (ret < 0) { | ||
381 | printk("ip_nat_init: can't register out hook.\n"); | ||
382 | goto cleanup_inops; | ||
383 | } | ||
384 | ret = nf_register_hook(&ip_nat_adjust_in_ops); | ||
385 | if (ret < 0) { | ||
386 | printk("ip_nat_init: can't register adjust in hook.\n"); | ||
387 | goto cleanup_outops; | ||
388 | } | ||
389 | ret = nf_register_hook(&ip_nat_adjust_out_ops); | ||
390 | if (ret < 0) { | ||
391 | printk("ip_nat_init: can't register adjust out hook.\n"); | ||
392 | goto cleanup_adjustin_ops; | ||
393 | } | ||
394 | ret = nf_register_hook(&ip_nat_local_out_ops); | ||
395 | if (ret < 0) { | ||
396 | printk("ip_nat_init: can't register local out hook.\n"); | ||
397 | goto cleanup_adjustout_ops; | ||
398 | } | ||
399 | ret = nf_register_hook(&ip_nat_local_in_ops); | ||
400 | if (ret < 0) { | ||
401 | printk("ip_nat_init: can't register local in hook.\n"); | ||
402 | goto cleanup_localoutops; | ||
403 | } | ||
404 | return ret; | 373 | return ret; |
405 | 374 | ||
406 | cleanup: | ||
407 | nf_unregister_hook(&ip_nat_local_in_ops); | ||
408 | cleanup_localoutops: | ||
409 | nf_unregister_hook(&ip_nat_local_out_ops); | ||
410 | cleanup_adjustout_ops: | ||
411 | nf_unregister_hook(&ip_nat_adjust_out_ops); | ||
412 | cleanup_adjustin_ops: | ||
413 | nf_unregister_hook(&ip_nat_adjust_in_ops); | ||
414 | cleanup_outops: | ||
415 | nf_unregister_hook(&ip_nat_out_ops); | ||
416 | cleanup_inops: | ||
417 | nf_unregister_hook(&ip_nat_in_ops); | ||
418 | cleanup_rule_init: | 375 | cleanup_rule_init: |
419 | ip_nat_rule_cleanup(); | 376 | ip_nat_rule_cleanup(); |
420 | cleanup_decode_session: | 377 | cleanup_decode_session: |
@@ -425,14 +382,14 @@ static int init_or_cleanup(int init) | |||
425 | return ret; | 382 | return ret; |
426 | } | 383 | } |
427 | 384 | ||
428 | static int __init ip_nat_standalone_init(void) | ||
429 | { | ||
430 | return init_or_cleanup(1); | ||
431 | } | ||
432 | |||
433 | static void __exit ip_nat_standalone_fini(void) | 385 | static void __exit ip_nat_standalone_fini(void) |
434 | { | 386 | { |
435 | init_or_cleanup(0); | 387 | nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops)); |
388 | ip_nat_rule_cleanup(); | ||
389 | #ifdef CONFIG_XFRM | ||
390 | ip_nat_decode_session = NULL; | ||
391 | synchronize_net(); | ||
392 | #endif | ||
436 | } | 393 | } |
437 | 394 | ||
438 | module_init(ip_nat_standalone_init); | 395 | module_init(ip_nat_standalone_init); |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 896a244f8f91..b93f0494362f 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = { | |||
662 | .outfn = &ipq_enqueue_packet, | 662 | .outfn = &ipq_enqueue_packet, |
663 | }; | 663 | }; |
664 | 664 | ||
665 | static int | 665 | static int __init ip_queue_init(void) |
666 | init_or_cleanup(int init) | ||
667 | { | 666 | { |
668 | int status = -ENOMEM; | 667 | int status = -ENOMEM; |
669 | struct proc_dir_entry *proc; | 668 | struct proc_dir_entry *proc; |
670 | 669 | ||
671 | if (!init) | ||
672 | goto cleanup; | ||
673 | |||
674 | netlink_register_notifier(&ipq_nl_notifier); | 670 | netlink_register_notifier(&ipq_nl_notifier); |
675 | ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, | 671 | ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, |
676 | THIS_MODULE); | 672 | THIS_MODULE); |
@@ -697,11 +693,6 @@ init_or_cleanup(int init) | |||
697 | } | 693 | } |
698 | return status; | 694 | return status; |
699 | 695 | ||
700 | cleanup: | ||
701 | nf_unregister_queue_handlers(&nfqh); | ||
702 | synchronize_net(); | ||
703 | ipq_flush(NF_DROP); | ||
704 | |||
705 | cleanup_sysctl: | 696 | cleanup_sysctl: |
706 | unregister_sysctl_table(ipq_sysctl_header); | 697 | unregister_sysctl_table(ipq_sysctl_header); |
707 | unregister_netdevice_notifier(&ipq_dev_notifier); | 698 | unregister_netdevice_notifier(&ipq_dev_notifier); |
@@ -717,15 +708,21 @@ cleanup_netlink_notifier: | |||
717 | return status; | 708 | return status; |
718 | } | 709 | } |
719 | 710 | ||
720 | static int __init ip_queue_init(void) | ||
721 | { | ||
722 | |||
723 | return init_or_cleanup(1); | ||
724 | } | ||
725 | |||
726 | static void __exit ip_queue_fini(void) | 711 | static void __exit ip_queue_fini(void) |
727 | { | 712 | { |
728 | init_or_cleanup(0); | 713 | nf_unregister_queue_handlers(&nfqh); |
714 | synchronize_net(); | ||
715 | ipq_flush(NF_DROP); | ||
716 | |||
717 | unregister_sysctl_table(ipq_sysctl_header); | ||
718 | unregister_netdevice_notifier(&ipq_dev_notifier); | ||
719 | proc_net_remove(IPQ_PROC_FS_NAME); | ||
720 | |||
721 | sock_release(ipqnl->sk_socket); | ||
722 | mutex_lock(&ipqnl_mutex); | ||
723 | mutex_unlock(&ipqnl_mutex); | ||
724 | |||
725 | netlink_unregister_notifier(&ipq_nl_notifier); | ||
729 | } | 726 | } |
730 | 727 | ||
731 | MODULE_DESCRIPTION("IPv4 packet queue handler"); | 728 | MODULE_DESCRIPTION("IPv4 packet queue handler"); |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index e4768a31718b..aad9d28c8d71 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = { | |||
725 | 725 | ||
726 | #endif /* CONFIG_PROC_FS */ | 726 | #endif /* CONFIG_PROC_FS */ |
727 | 727 | ||
728 | static int init_or_cleanup(int fini) | 728 | static int __init ipt_clusterip_init(void) |
729 | { | 729 | { |
730 | int ret; | 730 | int ret; |
731 | 731 | ||
732 | if (fini) | 732 | ret = ipt_register_target(&clusterip_tgt); |
733 | goto cleanup; | 733 | if (ret < 0) |
734 | 734 | return ret; | |
735 | if (ipt_register_target(&clusterip_tgt)) { | ||
736 | ret = -EINVAL; | ||
737 | goto cleanup_none; | ||
738 | } | ||
739 | 735 | ||
740 | if (nf_register_hook(&cip_arp_ops) < 0) { | 736 | ret = nf_register_hook(&cip_arp_ops); |
741 | ret = -EINVAL; | 737 | if (ret < 0) |
742 | goto cleanup_target; | 738 | goto cleanup_target; |
743 | } | ||
744 | 739 | ||
745 | #ifdef CONFIG_PROC_FS | 740 | #ifdef CONFIG_PROC_FS |
746 | clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net); | 741 | clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net); |
@@ -753,31 +748,24 @@ static int init_or_cleanup(int fini) | |||
753 | 748 | ||
754 | printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", | 749 | printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", |
755 | CLUSTERIP_VERSION); | 750 | CLUSTERIP_VERSION); |
756 | |||
757 | return 0; | 751 | return 0; |
758 | 752 | ||
759 | cleanup: | ||
760 | printk(KERN_NOTICE "ClusterIP Version %s unloading\n", | ||
761 | CLUSTERIP_VERSION); | ||
762 | #ifdef CONFIG_PROC_FS | ||
763 | remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); | ||
764 | #endif | ||
765 | cleanup_hook: | 753 | cleanup_hook: |
766 | nf_unregister_hook(&cip_arp_ops); | 754 | nf_unregister_hook(&cip_arp_ops); |
767 | cleanup_target: | 755 | cleanup_target: |
768 | ipt_unregister_target(&clusterip_tgt); | 756 | ipt_unregister_target(&clusterip_tgt); |
769 | cleanup_none: | 757 | return ret; |
770 | return -EINVAL; | ||
771 | } | ||
772 | |||
773 | static int __init ipt_clusterip_init(void) | ||
774 | { | ||
775 | return init_or_cleanup(0); | ||
776 | } | 758 | } |
777 | 759 | ||
778 | static void __exit ipt_clusterip_fini(void) | 760 | static void __exit ipt_clusterip_fini(void) |
779 | { | 761 | { |
780 | init_or_cleanup(1); | 762 | printk(KERN_NOTICE "ClusterIP Version %s unloading\n", |
763 | CLUSTERIP_VERSION); | ||
764 | #ifdef CONFIG_PROC_FS | ||
765 | remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); | ||
766 | #endif | ||
767 | nf_unregister_hook(&cip_arp_ops); | ||
768 | ipt_unregister_target(&clusterip_tgt); | ||
781 | } | 769 | } |
782 | 770 | ||
783 | module_init(ipt_clusterip_init); | 771 | module_init(ipt_clusterip_init); |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 4269a5440d43..0bba3c2bb786 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
106 | struct rtable *rt; | 106 | struct rtable *rt; |
107 | u_int16_t tmp_port; | 107 | u_int16_t tmp_port; |
108 | u_int32_t tmp_addr; | 108 | u_int32_t tmp_addr; |
109 | unsigned int tcplen; | ||
110 | int needs_ack; | 109 | int needs_ack; |
111 | int hh_len; | 110 | int hh_len; |
112 | 111 | ||
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
124 | return; | 123 | return; |
125 | 124 | ||
126 | /* Check checksum */ | 125 | /* Check checksum */ |
127 | tcplen = oldskb->len - iph->ihl * 4; | 126 | if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) |
128 | if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) || | ||
129 | (hook == NF_IP_LOCAL_IN && | ||
130 | oldskb->ip_summed != CHECKSUM_UNNECESSARY)) && | ||
131 | csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, | ||
132 | oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum : | ||
133 | skb_checksum(oldskb, iph->ihl * 4, tcplen, 0))) | ||
134 | return; | 127 | return; |
135 | 128 | ||
136 | if ((rt = route_reverse(oldskb, oth, hook)) == NULL) | 129 | if ((rt = route_reverse(oldskb, oth, hook)) == NULL) |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 3d80aefe9cfa..7f417484bfbf 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -157,37 +157,20 @@ static int __init iptable_filter_init(void) | |||
157 | return ret; | 157 | return ret; |
158 | 158 | ||
159 | /* Register hooks */ | 159 | /* Register hooks */ |
160 | ret = nf_register_hook(&ipt_ops[0]); | 160 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
161 | if (ret < 0) | 161 | if (ret < 0) |
162 | goto cleanup_table; | 162 | goto cleanup_table; |
163 | 163 | ||
164 | ret = nf_register_hook(&ipt_ops[1]); | ||
165 | if (ret < 0) | ||
166 | goto cleanup_hook0; | ||
167 | |||
168 | ret = nf_register_hook(&ipt_ops[2]); | ||
169 | if (ret < 0) | ||
170 | goto cleanup_hook1; | ||
171 | |||
172 | return ret; | 164 | return ret; |
173 | 165 | ||
174 | cleanup_hook1: | ||
175 | nf_unregister_hook(&ipt_ops[1]); | ||
176 | cleanup_hook0: | ||
177 | nf_unregister_hook(&ipt_ops[0]); | ||
178 | cleanup_table: | 166 | cleanup_table: |
179 | ipt_unregister_table(&packet_filter); | 167 | ipt_unregister_table(&packet_filter); |
180 | |||
181 | return ret; | 168 | return ret; |
182 | } | 169 | } |
183 | 170 | ||
184 | static void __exit iptable_filter_fini(void) | 171 | static void __exit iptable_filter_fini(void) |
185 | { | 172 | { |
186 | unsigned int i; | 173 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
187 | |||
188 | for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) | ||
189 | nf_unregister_hook(&ipt_ops[i]); | ||
190 | |||
191 | ipt_unregister_table(&packet_filter); | 174 | ipt_unregister_table(&packet_filter); |
192 | } | 175 | } |
193 | 176 | ||
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 412fc96cc896..397b95cc026b 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void) | |||
211 | return ret; | 211 | return ret; |
212 | 212 | ||
213 | /* Register hooks */ | 213 | /* Register hooks */ |
214 | ret = nf_register_hook(&ipt_ops[0]); | 214 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
215 | if (ret < 0) | 215 | if (ret < 0) |
216 | goto cleanup_table; | 216 | goto cleanup_table; |
217 | 217 | ||
218 | ret = nf_register_hook(&ipt_ops[1]); | ||
219 | if (ret < 0) | ||
220 | goto cleanup_hook0; | ||
221 | |||
222 | ret = nf_register_hook(&ipt_ops[2]); | ||
223 | if (ret < 0) | ||
224 | goto cleanup_hook1; | ||
225 | |||
226 | ret = nf_register_hook(&ipt_ops[3]); | ||
227 | if (ret < 0) | ||
228 | goto cleanup_hook2; | ||
229 | |||
230 | ret = nf_register_hook(&ipt_ops[4]); | ||
231 | if (ret < 0) | ||
232 | goto cleanup_hook3; | ||
233 | |||
234 | return ret; | 218 | return ret; |
235 | 219 | ||
236 | cleanup_hook3: | ||
237 | nf_unregister_hook(&ipt_ops[3]); | ||
238 | cleanup_hook2: | ||
239 | nf_unregister_hook(&ipt_ops[2]); | ||
240 | cleanup_hook1: | ||
241 | nf_unregister_hook(&ipt_ops[1]); | ||
242 | cleanup_hook0: | ||
243 | nf_unregister_hook(&ipt_ops[0]); | ||
244 | cleanup_table: | 220 | cleanup_table: |
245 | ipt_unregister_table(&packet_mangler); | 221 | ipt_unregister_table(&packet_mangler); |
246 | |||
247 | return ret; | 222 | return ret; |
248 | } | 223 | } |
249 | 224 | ||
250 | static void __exit iptable_mangle_fini(void) | 225 | static void __exit iptable_mangle_fini(void) |
251 | { | 226 | { |
252 | unsigned int i; | 227 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
253 | |||
254 | for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) | ||
255 | nf_unregister_hook(&ipt_ops[i]); | ||
256 | |||
257 | ipt_unregister_table(&packet_mangler); | 228 | ipt_unregister_table(&packet_mangler); |
258 | } | 229 | } |
259 | 230 | ||
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 03cc79a6160a..7912cce1e1b8 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -101,18 +101,18 @@ ipt_hook(unsigned int hook, | |||
101 | /* 'raw' is the very first table. */ | 101 | /* 'raw' is the very first table. */ |
102 | static struct nf_hook_ops ipt_ops[] = { | 102 | static struct nf_hook_ops ipt_ops[] = { |
103 | { | 103 | { |
104 | .hook = ipt_hook, | 104 | .hook = ipt_hook, |
105 | .pf = PF_INET, | 105 | .pf = PF_INET, |
106 | .hooknum = NF_IP_PRE_ROUTING, | 106 | .hooknum = NF_IP_PRE_ROUTING, |
107 | .priority = NF_IP_PRI_RAW, | 107 | .priority = NF_IP_PRI_RAW, |
108 | .owner = THIS_MODULE, | 108 | .owner = THIS_MODULE, |
109 | }, | 109 | }, |
110 | { | 110 | { |
111 | .hook = ipt_hook, | 111 | .hook = ipt_hook, |
112 | .pf = PF_INET, | 112 | .pf = PF_INET, |
113 | .hooknum = NF_IP_LOCAL_OUT, | 113 | .hooknum = NF_IP_LOCAL_OUT, |
114 | .priority = NF_IP_PRI_RAW, | 114 | .priority = NF_IP_PRI_RAW, |
115 | .owner = THIS_MODULE, | 115 | .owner = THIS_MODULE, |
116 | }, | 116 | }, |
117 | }; | 117 | }; |
118 | 118 | ||
@@ -126,31 +126,20 @@ static int __init iptable_raw_init(void) | |||
126 | return ret; | 126 | return ret; |
127 | 127 | ||
128 | /* Register hooks */ | 128 | /* Register hooks */ |
129 | ret = nf_register_hook(&ipt_ops[0]); | 129 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
130 | if (ret < 0) | 130 | if (ret < 0) |
131 | goto cleanup_table; | 131 | goto cleanup_table; |
132 | 132 | ||
133 | ret = nf_register_hook(&ipt_ops[1]); | ||
134 | if (ret < 0) | ||
135 | goto cleanup_hook0; | ||
136 | |||
137 | return ret; | 133 | return ret; |
138 | 134 | ||
139 | cleanup_hook0: | ||
140 | nf_unregister_hook(&ipt_ops[0]); | ||
141 | cleanup_table: | 135 | cleanup_table: |
142 | ipt_unregister_table(&packet_raw); | 136 | ipt_unregister_table(&packet_raw); |
143 | |||
144 | return ret; | 137 | return ret; |
145 | } | 138 | } |
146 | 139 | ||
147 | static void __exit iptable_raw_fini(void) | 140 | static void __exit iptable_raw_fini(void) |
148 | { | 141 | { |
149 | unsigned int i; | 142 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
150 | |||
151 | for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) | ||
152 | nf_unregister_hook(&ipt_ops[i]); | ||
153 | |||
154 | ipt_unregister_table(&packet_raw); | 143 | ipt_unregister_table(&packet_raw); |
155 | } | 144 | } |
156 | 145 | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 4afbc699d3ba..5bc9f64d7b5b 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum, | |||
210 | 210 | ||
211 | /* Connection tracking may drop packets, but never alters them, so | 211 | /* Connection tracking may drop packets, but never alters them, so |
212 | make it the first hook. */ | 212 | make it the first hook. */ |
213 | static struct nf_hook_ops ipv4_conntrack_defrag_ops = { | 213 | static struct nf_hook_ops ipv4_conntrack_ops[] = { |
214 | .hook = ipv4_conntrack_defrag, | 214 | { |
215 | .owner = THIS_MODULE, | 215 | .hook = ipv4_conntrack_defrag, |
216 | .pf = PF_INET, | 216 | .owner = THIS_MODULE, |
217 | .hooknum = NF_IP_PRE_ROUTING, | 217 | .pf = PF_INET, |
218 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | 218 | .hooknum = NF_IP_PRE_ROUTING, |
219 | }; | 219 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, |
220 | 220 | }, | |
221 | static struct nf_hook_ops ipv4_conntrack_in_ops = { | 221 | { |
222 | .hook = ipv4_conntrack_in, | 222 | .hook = ipv4_conntrack_in, |
223 | .owner = THIS_MODULE, | 223 | .owner = THIS_MODULE, |
224 | .pf = PF_INET, | 224 | .pf = PF_INET, |
225 | .hooknum = NF_IP_PRE_ROUTING, | 225 | .hooknum = NF_IP_PRE_ROUTING, |
226 | .priority = NF_IP_PRI_CONNTRACK, | 226 | .priority = NF_IP_PRI_CONNTRACK, |
227 | }; | 227 | }, |
228 | 228 | { | |
229 | static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = { | 229 | .hook = ipv4_conntrack_defrag, |
230 | .hook = ipv4_conntrack_defrag, | 230 | .owner = THIS_MODULE, |
231 | .owner = THIS_MODULE, | 231 | .pf = PF_INET, |
232 | .pf = PF_INET, | 232 | .hooknum = NF_IP_LOCAL_OUT, |
233 | .hooknum = NF_IP_LOCAL_OUT, | 233 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, |
234 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | 234 | }, |
235 | }; | 235 | { |
236 | 236 | .hook = ipv4_conntrack_local, | |
237 | static struct nf_hook_ops ipv4_conntrack_local_out_ops = { | 237 | .owner = THIS_MODULE, |
238 | .hook = ipv4_conntrack_local, | 238 | .pf = PF_INET, |
239 | .owner = THIS_MODULE, | 239 | .hooknum = NF_IP_LOCAL_OUT, |
240 | .pf = PF_INET, | 240 | .priority = NF_IP_PRI_CONNTRACK, |
241 | .hooknum = NF_IP_LOCAL_OUT, | 241 | }, |
242 | .priority = NF_IP_PRI_CONNTRACK, | 242 | { |
243 | }; | 243 | .hook = ipv4_conntrack_help, |
244 | 244 | .owner = THIS_MODULE, | |
245 | /* helpers */ | 245 | .pf = PF_INET, |
246 | static struct nf_hook_ops ipv4_conntrack_helper_out_ops = { | 246 | .hooknum = NF_IP_POST_ROUTING, |
247 | .hook = ipv4_conntrack_help, | 247 | .priority = NF_IP_PRI_CONNTRACK_HELPER, |
248 | .owner = THIS_MODULE, | 248 | }, |
249 | .pf = PF_INET, | 249 | { |
250 | .hooknum = NF_IP_POST_ROUTING, | 250 | .hook = ipv4_conntrack_help, |
251 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | 251 | .owner = THIS_MODULE, |
252 | }; | 252 | .pf = PF_INET, |
253 | 253 | .hooknum = NF_IP_LOCAL_IN, | |
254 | static struct nf_hook_ops ipv4_conntrack_helper_in_ops = { | 254 | .priority = NF_IP_PRI_CONNTRACK_HELPER, |
255 | .hook = ipv4_conntrack_help, | 255 | }, |
256 | .owner = THIS_MODULE, | 256 | { |
257 | .pf = PF_INET, | 257 | .hook = ipv4_confirm, |
258 | .hooknum = NF_IP_LOCAL_IN, | 258 | .owner = THIS_MODULE, |
259 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | 259 | .pf = PF_INET, |
260 | }; | 260 | .hooknum = NF_IP_POST_ROUTING, |
261 | 261 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | |
262 | 262 | }, | |
263 | /* Refragmenter; last chance. */ | 263 | { |
264 | static struct nf_hook_ops ipv4_conntrack_out_ops = { | 264 | .hook = ipv4_confirm, |
265 | .hook = ipv4_confirm, | 265 | .owner = THIS_MODULE, |
266 | .owner = THIS_MODULE, | 266 | .pf = PF_INET, |
267 | .pf = PF_INET, | 267 | .hooknum = NF_IP_LOCAL_IN, |
268 | .hooknum = NF_IP_POST_ROUTING, | 268 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, |
269 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | 269 | }, |
270 | }; | ||
271 | |||
272 | static struct nf_hook_ops ipv4_conntrack_local_in_ops = { | ||
273 | .hook = ipv4_confirm, | ||
274 | .owner = THIS_MODULE, | ||
275 | .pf = PF_INET, | ||
276 | .hooknum = NF_IP_LOCAL_IN, | ||
277 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | ||
278 | }; | 270 | }; |
279 | 271 | ||
280 | #ifdef CONFIG_SYSCTL | 272 | #ifdef CONFIG_SYSCTL |
@@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { | |||
440 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; | 432 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; |
441 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; | 433 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; |
442 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; | 434 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; |
443 | static int init_or_cleanup(int init) | 435 | |
436 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); | ||
437 | MODULE_LICENSE("GPL"); | ||
438 | |||
439 | static int __init nf_conntrack_l3proto_ipv4_init(void) | ||
444 | { | 440 | { |
445 | int ret = 0; | 441 | int ret = 0; |
446 | 442 | ||
447 | if (!init) goto cleanup; | 443 | need_conntrack(); |
448 | 444 | ||
449 | ret = nf_register_sockopt(&so_getorigdst); | 445 | ret = nf_register_sockopt(&so_getorigdst); |
450 | if (ret < 0) { | 446 | if (ret < 0) { |
451 | printk(KERN_ERR "Unable to register netfilter socket option\n"); | 447 | printk(KERN_ERR "Unable to register netfilter socket option\n"); |
452 | goto cleanup_nothing; | 448 | return ret; |
453 | } | 449 | } |
454 | 450 | ||
455 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); | 451 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); |
@@ -476,84 +472,26 @@ static int init_or_cleanup(int init) | |||
476 | goto cleanup_icmp; | 472 | goto cleanup_icmp; |
477 | } | 473 | } |
478 | 474 | ||
479 | ret = nf_register_hook(&ipv4_conntrack_defrag_ops); | 475 | ret = nf_register_hooks(ipv4_conntrack_ops, |
476 | ARRAY_SIZE(ipv4_conntrack_ops)); | ||
480 | if (ret < 0) { | 477 | if (ret < 0) { |
481 | printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); | 478 | printk("nf_conntrack_ipv4: can't register hooks.\n"); |
482 | goto cleanup_ipv4; | 479 | goto cleanup_ipv4; |
483 | } | 480 | } |
484 | ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops); | ||
485 | if (ret < 0) { | ||
486 | printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n"); | ||
487 | goto cleanup_defragops; | ||
488 | } | ||
489 | |||
490 | ret = nf_register_hook(&ipv4_conntrack_in_ops); | ||
491 | if (ret < 0) { | ||
492 | printk("nf_conntrack_ipv4: can't register pre-routing hook.\n"); | ||
493 | goto cleanup_defraglocalops; | ||
494 | } | ||
495 | |||
496 | ret = nf_register_hook(&ipv4_conntrack_local_out_ops); | ||
497 | if (ret < 0) { | ||
498 | printk("nf_conntrack_ipv4: can't register local out hook.\n"); | ||
499 | goto cleanup_inops; | ||
500 | } | ||
501 | |||
502 | ret = nf_register_hook(&ipv4_conntrack_helper_in_ops); | ||
503 | if (ret < 0) { | ||
504 | printk("nf_conntrack_ipv4: can't register local helper hook.\n"); | ||
505 | goto cleanup_inandlocalops; | ||
506 | } | ||
507 | |||
508 | ret = nf_register_hook(&ipv4_conntrack_helper_out_ops); | ||
509 | if (ret < 0) { | ||
510 | printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n"); | ||
511 | goto cleanup_helperinops; | ||
512 | } | ||
513 | |||
514 | ret = nf_register_hook(&ipv4_conntrack_out_ops); | ||
515 | if (ret < 0) { | ||
516 | printk("nf_conntrack_ipv4: can't register post-routing hook.\n"); | ||
517 | goto cleanup_helperoutops; | ||
518 | } | ||
519 | |||
520 | ret = nf_register_hook(&ipv4_conntrack_local_in_ops); | ||
521 | if (ret < 0) { | ||
522 | printk("nf_conntrack_ipv4: can't register local in hook.\n"); | ||
523 | goto cleanup_inoutandlocalops; | ||
524 | } | ||
525 | |||
526 | #ifdef CONFIG_SYSCTL | 481 | #ifdef CONFIG_SYSCTL |
527 | nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | 482 | nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); |
528 | if (nf_ct_ipv4_sysctl_header == NULL) { | 483 | if (nf_ct_ipv4_sysctl_header == NULL) { |
529 | printk("nf_conntrack: can't register to sysctl.\n"); | 484 | printk("nf_conntrack: can't register to sysctl.\n"); |
530 | ret = -ENOMEM; | 485 | ret = -ENOMEM; |
531 | goto cleanup_localinops; | 486 | goto cleanup_hooks; |
532 | } | 487 | } |
533 | #endif | 488 | #endif |
534 | return ret; | 489 | return ret; |
535 | 490 | ||
536 | cleanup: | ||
537 | synchronize_net(); | ||
538 | #ifdef CONFIG_SYSCTL | 491 | #ifdef CONFIG_SYSCTL |
539 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); | 492 | cleanup_hooks: |
540 | cleanup_localinops: | 493 | nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); |
541 | #endif | 494 | #endif |
542 | nf_unregister_hook(&ipv4_conntrack_local_in_ops); | ||
543 | cleanup_inoutandlocalops: | ||
544 | nf_unregister_hook(&ipv4_conntrack_out_ops); | ||
545 | cleanup_helperoutops: | ||
546 | nf_unregister_hook(&ipv4_conntrack_helper_out_ops); | ||
547 | cleanup_helperinops: | ||
548 | nf_unregister_hook(&ipv4_conntrack_helper_in_ops); | ||
549 | cleanup_inandlocalops: | ||
550 | nf_unregister_hook(&ipv4_conntrack_local_out_ops); | ||
551 | cleanup_inops: | ||
552 | nf_unregister_hook(&ipv4_conntrack_in_ops); | ||
553 | cleanup_defraglocalops: | ||
554 | nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops); | ||
555 | cleanup_defragops: | ||
556 | nf_unregister_hook(&ipv4_conntrack_defrag_ops); | ||
557 | cleanup_ipv4: | 495 | cleanup_ipv4: |
558 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); | 496 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); |
559 | cleanup_icmp: | 497 | cleanup_icmp: |
@@ -564,22 +502,21 @@ static int init_or_cleanup(int init) | |||
564 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); | 502 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); |
565 | cleanup_sockopt: | 503 | cleanup_sockopt: |
566 | nf_unregister_sockopt(&so_getorigdst); | 504 | nf_unregister_sockopt(&so_getorigdst); |
567 | cleanup_nothing: | ||
568 | return ret; | 505 | return ret; |
569 | } | 506 | } |
570 | 507 | ||
571 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); | ||
572 | MODULE_LICENSE("GPL"); | ||
573 | |||
574 | static int __init nf_conntrack_l3proto_ipv4_init(void) | ||
575 | { | ||
576 | need_conntrack(); | ||
577 | return init_or_cleanup(1); | ||
578 | } | ||
579 | |||
580 | static void __exit nf_conntrack_l3proto_ipv4_fini(void) | 508 | static void __exit nf_conntrack_l3proto_ipv4_fini(void) |
581 | { | 509 | { |
582 | init_or_cleanup(0); | 510 | synchronize_net(); |
511 | #ifdef CONFIG_SYSCTL | ||
512 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); | ||
513 | #endif | ||
514 | nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); | ||
515 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); | ||
516 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); | ||
517 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); | ||
518 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); | ||
519 | nf_unregister_sockopt(&so_getorigdst); | ||
583 | } | 520 | } |
584 | 521 | ||
585 | module_init(nf_conntrack_l3proto_ipv4_init); | 522 | module_init(nf_conntrack_l3proto_ipv4_init); |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 52dc175be39a..4b0d361cc6e6 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff, | |||
235 | } | 235 | } |
236 | 236 | ||
237 | /* See ip_conntrack_proto_tcp.c */ | 237 | /* See ip_conntrack_proto_tcp.c */ |
238 | if (hooknum != NF_IP_PRE_ROUTING) | 238 | if (hooknum == NF_IP_PRE_ROUTING && |
239 | goto checksum_skipped; | 239 | nf_ip_checksum(skb, hooknum, dataoff, 0)) { |
240 | |||
241 | switch (skb->ip_summed) { | ||
242 | case CHECKSUM_HW: | ||
243 | if (!(u16)csum_fold(skb->csum)) | ||
244 | break; | ||
245 | if (LOG_INVALID(IPPROTO_ICMP)) | 240 | if (LOG_INVALID(IPPROTO_ICMP)) |
246 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | 241 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, |
247 | "nf_ct_icmp: bad HW ICMP checksum "); | 242 | "nf_ct_icmp: bad HW ICMP checksum "); |
248 | return -NF_ACCEPT; | 243 | return -NF_ACCEPT; |
249 | case CHECKSUM_NONE: | ||
250 | if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { | ||
251 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
252 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, | ||
253 | NULL, | ||
254 | "nf_ct_icmp: bad ICMP checksum "); | ||
255 | return -NF_ACCEPT; | ||
256 | } | ||
257 | default: | ||
258 | break; | ||
259 | } | 244 | } |
260 | 245 | ||
261 | checksum_skipped: | ||
262 | /* | 246 | /* |
263 | * 18 is the highest 'known' ICMP type. Anything else is a mystery | 247 | * 18 is the highest 'known' ICMP type. Anything else is a mystery |
264 | * | 248 | * |
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index 0d7d386dac22..8d30c48f090e 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | #include <linux/skbuff.h> | 10 | #include <linux/skbuff.h> |
11 | #include <net/icmp.h> | ||
12 | #include <net/ip.h> | ||
11 | #include <net/protocol.h> | 13 | #include <net/protocol.h> |
12 | #include <net/xfrm.h> | 14 | #include <net/xfrm.h> |
13 | 15 | ||
@@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb) | |||
70 | { | 72 | { |
71 | struct xfrm_tunnel *handler; | 73 | struct xfrm_tunnel *handler; |
72 | 74 | ||
75 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
76 | goto drop; | ||
77 | |||
73 | for (handler = tunnel4_handlers; handler; handler = handler->next) | 78 | for (handler = tunnel4_handlers; handler; handler = handler->next) |
74 | if (!handler->handler(skb)) | 79 | if (!handler->handler(skb)) |
75 | return 0; | 80 | return 0; |
76 | 81 | ||
82 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | ||
83 | |||
84 | drop: | ||
77 | kfree_skb(skb); | 85 | kfree_skb(skb); |
78 | return 0; | 86 | return 0; |
79 | } | 87 | } |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index e1b8f4b90d80..3e174c83bfe7 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) | |||
37 | { | 37 | { |
38 | switch (nexthdr) { | 38 | switch (nexthdr) { |
39 | case IPPROTO_IPIP: | 39 | case IPPROTO_IPIP: |
40 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
41 | return -EINVAL; | ||
42 | *spi = skb->nh.iph->saddr; | 40 | *spi = skb->nh.iph->saddr; |
43 | *seq = 0; | 41 | *seq = 0; |
44 | return 0; | 42 | return 0; |
@@ -90,7 +88,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
90 | if (unlikely(x->km.state != XFRM_STATE_VALID)) | 88 | if (unlikely(x->km.state != XFRM_STATE_VALID)) |
91 | goto drop_unlock; | 89 | goto drop_unlock; |
92 | 90 | ||
93 | if (x->encap->encap_type != encap_type) | 91 | if ((x->encap ? x->encap->encap_type : 0) != encap_type) |
94 | goto drop_unlock; | 92 | goto drop_unlock; |
95 | 93 | ||
96 | if (x->props.replay_window && xfrm_replay_check(x, seq)) | 94 | if (x->props.replay_window && xfrm_replay_check(x, seq)) |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index bb8ffb8a14c5..2ae84c961678 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -23,6 +23,86 @@ | |||
23 | #include <net/inet6_hashtables.h> | 23 | #include <net/inet6_hashtables.h> |
24 | #include <net/ip.h> | 24 | #include <net/ip.h> |
25 | 25 | ||
26 | void __inet6_hash(struct inet_hashinfo *hashinfo, | ||
27 | struct sock *sk) | ||
28 | { | ||
29 | struct hlist_head *list; | ||
30 | rwlock_t *lock; | ||
31 | |||
32 | BUG_TRAP(sk_unhashed(sk)); | ||
33 | |||
34 | if (sk->sk_state == TCP_LISTEN) { | ||
35 | list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)]; | ||
36 | lock = &hashinfo->lhash_lock; | ||
37 | inet_listen_wlock(hashinfo); | ||
38 | } else { | ||
39 | unsigned int hash; | ||
40 | sk->sk_hash = hash = inet6_sk_ehashfn(sk); | ||
41 | hash &= (hashinfo->ehash_size - 1); | ||
42 | list = &hashinfo->ehash[hash].chain; | ||
43 | lock = &hashinfo->ehash[hash].lock; | ||
44 | write_lock(lock); | ||
45 | } | ||
46 | |||
47 | __sk_add_node(sk, list); | ||
48 | sock_prot_inc_use(sk->sk_prot); | ||
49 | write_unlock(lock); | ||
50 | } | ||
51 | EXPORT_SYMBOL(__inet6_hash); | ||
52 | |||
53 | /* | ||
54 | * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so | ||
55 | * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM | ||
56 | * | ||
57 | * The sockhash lock must be held as a reader here. | ||
58 | */ | ||
59 | struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, | ||
60 | const struct in6_addr *saddr, | ||
61 | const u16 sport, | ||
62 | const struct in6_addr *daddr, | ||
63 | const u16 hnum, | ||
64 | const int dif) | ||
65 | { | ||
66 | struct sock *sk; | ||
67 | const struct hlist_node *node; | ||
68 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | ||
69 | /* Optimize here for direct hit, only listening connections can | ||
70 | * have wildcards anyways. | ||
71 | */ | ||
72 | unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport); | ||
73 | struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); | ||
74 | |||
75 | prefetch(head->chain.first); | ||
76 | read_lock(&head->lock); | ||
77 | sk_for_each(sk, node, &head->chain) { | ||
78 | /* For IPV6 do the cheaper port and family tests first. */ | ||
79 | if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) | ||
80 | goto hit; /* You sunk my battleship! */ | ||
81 | } | ||
82 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | ||
83 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { | ||
84 | const struct inet_timewait_sock *tw = inet_twsk(sk); | ||
85 | |||
86 | if(*((__u32 *)&(tw->tw_dport)) == ports && | ||
87 | sk->sk_family == PF_INET6) { | ||
88 | const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); | ||
89 | |||
90 | if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && | ||
91 | ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && | ||
92 | (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)) | ||
93 | goto hit; | ||
94 | } | ||
95 | } | ||
96 | read_unlock(&head->lock); | ||
97 | return NULL; | ||
98 | |||
99 | hit: | ||
100 | sock_hold(sk); | ||
101 | read_unlock(&head->lock); | ||
102 | return sk; | ||
103 | } | ||
104 | EXPORT_SYMBOL(__inet6_lookup_established); | ||
105 | |||
26 | struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | 106 | struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, |
27 | const struct in6_addr *daddr, | 107 | const struct in6_addr *daddr, |
28 | const unsigned short hnum, const int dif) | 108 | const unsigned short hnum, const int dif) |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index ff9040c92556..a995796b5a57 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
519 | struct ipv6hdr *ipv6h; | 519 | struct ipv6hdr *ipv6h; |
520 | struct ip6_tnl *t; | 520 | struct ip6_tnl *t; |
521 | 521 | ||
522 | if (!pskb_may_pull(skb, sizeof (*ipv6h))) | ||
523 | goto discard; | ||
524 | |||
525 | ipv6h = skb->nh.ipv6h; | 522 | ipv6h = skb->nh.ipv6h; |
526 | 523 | ||
527 | read_lock(&ip6ip6_lock); | 524 | read_lock(&ip6ip6_lock); |
@@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
529 | if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { | 526 | if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { |
530 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 527 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
531 | read_unlock(&ip6ip6_lock); | 528 | read_unlock(&ip6ip6_lock); |
532 | kfree_skb(skb); | 529 | goto discard; |
533 | return 0; | ||
534 | } | 530 | } |
535 | 531 | ||
536 | if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { | 532 | if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { |
@@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
557 | return 0; | 553 | return 0; |
558 | } | 554 | } |
559 | read_unlock(&ip6ip6_lock); | 555 | read_unlock(&ip6ip6_lock); |
560 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); | ||
561 | discard: | ||
562 | return 1; | 556 | return 1; |
557 | |||
558 | discard: | ||
559 | kfree_skb(skb); | ||
560 | return 0; | ||
563 | } | 561 | } |
564 | 562 | ||
565 | static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) | 563 | static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index d750cfc019dc..395a417ba955 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
8 | #include <net/ip6_route.h> | 8 | #include <net/ip6_route.h> |
9 | #include <net/xfrm.h> | 9 | #include <net/xfrm.h> |
10 | #include <net/ip6_checksum.h> | ||
10 | 11 | ||
11 | int ip6_route_me_harder(struct sk_buff *skb) | 12 | int ip6_route_me_harder(struct sk_buff *skb) |
12 | { | 13 | { |
@@ -54,7 +55,7 @@ struct ip6_rt_info { | |||
54 | struct in6_addr saddr; | 55 | struct in6_addr saddr; |
55 | }; | 56 | }; |
56 | 57 | ||
57 | static void save(const struct sk_buff *skb, struct nf_info *info) | 58 | static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) |
58 | { | 59 | { |
59 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 60 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
60 | 61 | ||
@@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info) | |||
66 | } | 67 | } |
67 | } | 68 | } |
68 | 69 | ||
69 | static int reroute(struct sk_buff **pskb, const struct nf_info *info) | 70 | static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) |
70 | { | 71 | { |
71 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 72 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
72 | 73 | ||
@@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
79 | return 0; | 80 | return 0; |
80 | } | 81 | } |
81 | 82 | ||
82 | static struct nf_queue_rerouter ip6_reroute = { | 83 | unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
83 | .rer_size = sizeof(struct ip6_rt_info), | 84 | unsigned int dataoff, u_int8_t protocol) |
84 | .save = &save, | 85 | { |
85 | .reroute = &reroute, | 86 | struct ipv6hdr *ip6h = skb->nh.ipv6h; |
87 | unsigned int csum = 0; | ||
88 | |||
89 | switch (skb->ip_summed) { | ||
90 | case CHECKSUM_HW: | ||
91 | if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) | ||
92 | break; | ||
93 | if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | ||
94 | skb->len - dataoff, protocol, | ||
95 | csum_sub(skb->csum, | ||
96 | skb_checksum(skb, 0, | ||
97 | dataoff, 0)))) { | ||
98 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
99 | break; | ||
100 | } | ||
101 | /* fall through */ | ||
102 | case CHECKSUM_NONE: | ||
103 | skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | ||
104 | skb->len - dataoff, | ||
105 | protocol, | ||
106 | csum_sub(0, | ||
107 | skb_checksum(skb, 0, | ||
108 | dataoff, 0))); | ||
109 | csum = __skb_checksum_complete(skb); | ||
110 | } | ||
111 | return csum; | ||
112 | } | ||
113 | |||
114 | EXPORT_SYMBOL(nf_ip6_checksum); | ||
115 | |||
116 | static struct nf_afinfo nf_ip6_afinfo = { | ||
117 | .family = AF_INET6, | ||
118 | .checksum = nf_ip6_checksum, | ||
119 | .saveroute = nf_ip6_saveroute, | ||
120 | .reroute = nf_ip6_reroute, | ||
121 | .route_key_size = sizeof(struct ip6_rt_info), | ||
86 | }; | 122 | }; |
87 | 123 | ||
88 | int __init ipv6_netfilter_init(void) | 124 | int __init ipv6_netfilter_init(void) |
89 | { | 125 | { |
90 | return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); | 126 | return nf_register_afinfo(&nf_ip6_afinfo); |
91 | } | 127 | } |
92 | 128 | ||
93 | /* This can be called from inet6_init() on errors, so it cannot | 129 | /* This can be called from inet6_init() on errors, so it cannot |
@@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void) | |||
95 | */ | 131 | */ |
96 | void ipv6_netfilter_fini(void) | 132 | void ipv6_netfilter_fini(void) |
97 | { | 133 | { |
98 | nf_unregister_queue_rerouter(PF_INET6); | 134 | nf_unregister_afinfo(&nf_ip6_afinfo); |
99 | } | 135 | } |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e81c6a9dab81..b4b7d441af25 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = { | |||
658 | .outfn = &ipq_enqueue_packet, | 658 | .outfn = &ipq_enqueue_packet, |
659 | }; | 659 | }; |
660 | 660 | ||
661 | static int | 661 | static int __init ip6_queue_init(void) |
662 | init_or_cleanup(int init) | ||
663 | { | 662 | { |
664 | int status = -ENOMEM; | 663 | int status = -ENOMEM; |
665 | struct proc_dir_entry *proc; | 664 | struct proc_dir_entry *proc; |
666 | 665 | ||
667 | if (!init) | ||
668 | goto cleanup; | ||
669 | |||
670 | netlink_register_notifier(&ipq_nl_notifier); | 666 | netlink_register_notifier(&ipq_nl_notifier); |
671 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, | 667 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, |
672 | THIS_MODULE); | 668 | THIS_MODULE); |
@@ -693,11 +689,6 @@ init_or_cleanup(int init) | |||
693 | } | 689 | } |
694 | return status; | 690 | return status; |
695 | 691 | ||
696 | cleanup: | ||
697 | nf_unregister_queue_handlers(&nfqh); | ||
698 | synchronize_net(); | ||
699 | ipq_flush(NF_DROP); | ||
700 | |||
701 | cleanup_sysctl: | 692 | cleanup_sysctl: |
702 | unregister_sysctl_table(ipq_sysctl_header); | 693 | unregister_sysctl_table(ipq_sysctl_header); |
703 | unregister_netdevice_notifier(&ipq_dev_notifier); | 694 | unregister_netdevice_notifier(&ipq_dev_notifier); |
@@ -713,15 +704,21 @@ cleanup_netlink_notifier: | |||
713 | return status; | 704 | return status; |
714 | } | 705 | } |
715 | 706 | ||
716 | static int __init ip6_queue_init(void) | ||
717 | { | ||
718 | |||
719 | return init_or_cleanup(1); | ||
720 | } | ||
721 | |||
722 | static void __exit ip6_queue_fini(void) | 707 | static void __exit ip6_queue_fini(void) |
723 | { | 708 | { |
724 | init_or_cleanup(0); | 709 | nf_unregister_queue_handlers(&nfqh); |
710 | synchronize_net(); | ||
711 | ipq_flush(NF_DROP); | ||
712 | |||
713 | unregister_sysctl_table(ipq_sysctl_header); | ||
714 | unregister_netdevice_notifier(&ipq_dev_notifier); | ||
715 | proc_net_remove(IPQ_PROC_FS_NAME); | ||
716 | |||
717 | sock_release(ipqnl->sk_socket); | ||
718 | mutex_lock(&ipqnl_mutex); | ||
719 | mutex_unlock(&ipqnl_mutex); | ||
720 | |||
721 | netlink_unregister_notifier(&ipq_nl_notifier); | ||
725 | } | 722 | } |
726 | 723 | ||
727 | MODULE_DESCRIPTION("IPv6 packet queue handler"); | 724 | MODULE_DESCRIPTION("IPv6 packet queue handler"); |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index e5e724d9ee60..60976c0c58e8 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void) | |||
177 | return ret; | 177 | return ret; |
178 | 178 | ||
179 | /* Register hooks */ | 179 | /* Register hooks */ |
180 | ret = nf_register_hook(&ip6t_ops[0]); | 180 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
181 | if (ret < 0) | 181 | if (ret < 0) |
182 | goto cleanup_table; | 182 | goto cleanup_table; |
183 | 183 | ||
184 | ret = nf_register_hook(&ip6t_ops[1]); | ||
185 | if (ret < 0) | ||
186 | goto cleanup_hook0; | ||
187 | |||
188 | ret = nf_register_hook(&ip6t_ops[2]); | ||
189 | if (ret < 0) | ||
190 | goto cleanup_hook1; | ||
191 | |||
192 | return ret; | 184 | return ret; |
193 | 185 | ||
194 | cleanup_hook1: | ||
195 | nf_unregister_hook(&ip6t_ops[1]); | ||
196 | cleanup_hook0: | ||
197 | nf_unregister_hook(&ip6t_ops[0]); | ||
198 | cleanup_table: | 186 | cleanup_table: |
199 | ip6t_unregister_table(&packet_filter); | 187 | ip6t_unregister_table(&packet_filter); |
200 | |||
201 | return ret; | 188 | return ret; |
202 | } | 189 | } |
203 | 190 | ||
204 | static void __exit ip6table_filter_fini(void) | 191 | static void __exit ip6table_filter_fini(void) |
205 | { | 192 | { |
206 | unsigned int i; | 193 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
207 | |||
208 | for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) | ||
209 | nf_unregister_hook(&ip6t_ops[i]); | ||
210 | |||
211 | ip6t_unregister_table(&packet_filter); | 194 | ip6t_unregister_table(&packet_filter); |
212 | } | 195 | } |
213 | 196 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index e1f0f6ae9841..03a13eab1dae 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void) | |||
238 | return ret; | 238 | return ret; |
239 | 239 | ||
240 | /* Register hooks */ | 240 | /* Register hooks */ |
241 | ret = nf_register_hook(&ip6t_ops[0]); | 241 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
242 | if (ret < 0) | 242 | if (ret < 0) |
243 | goto cleanup_table; | 243 | goto cleanup_table; |
244 | 244 | ||
245 | ret = nf_register_hook(&ip6t_ops[1]); | ||
246 | if (ret < 0) | ||
247 | goto cleanup_hook0; | ||
248 | |||
249 | ret = nf_register_hook(&ip6t_ops[2]); | ||
250 | if (ret < 0) | ||
251 | goto cleanup_hook1; | ||
252 | |||
253 | ret = nf_register_hook(&ip6t_ops[3]); | ||
254 | if (ret < 0) | ||
255 | goto cleanup_hook2; | ||
256 | |||
257 | ret = nf_register_hook(&ip6t_ops[4]); | ||
258 | if (ret < 0) | ||
259 | goto cleanup_hook3; | ||
260 | |||
261 | return ret; | 245 | return ret; |
262 | 246 | ||
263 | cleanup_hook3: | ||
264 | nf_unregister_hook(&ip6t_ops[3]); | ||
265 | cleanup_hook2: | ||
266 | nf_unregister_hook(&ip6t_ops[2]); | ||
267 | cleanup_hook1: | ||
268 | nf_unregister_hook(&ip6t_ops[1]); | ||
269 | cleanup_hook0: | ||
270 | nf_unregister_hook(&ip6t_ops[0]); | ||
271 | cleanup_table: | 247 | cleanup_table: |
272 | ip6t_unregister_table(&packet_mangler); | 248 | ip6t_unregister_table(&packet_mangler); |
273 | |||
274 | return ret; | 249 | return ret; |
275 | } | 250 | } |
276 | 251 | ||
277 | static void __exit ip6table_mangle_fini(void) | 252 | static void __exit ip6table_mangle_fini(void) |
278 | { | 253 | { |
279 | unsigned int i; | 254 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
280 | |||
281 | for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) | ||
282 | nf_unregister_hook(&ip6t_ops[i]); | ||
283 | |||
284 | ip6t_unregister_table(&packet_mangler); | 255 | ip6t_unregister_table(&packet_mangler); |
285 | } | 256 | } |
286 | 257 | ||
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 54d1fffd62ba..61a7c58e99f8 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void) | |||
152 | return ret; | 152 | return ret; |
153 | 153 | ||
154 | /* Register hooks */ | 154 | /* Register hooks */ |
155 | ret = nf_register_hook(&ip6t_ops[0]); | 155 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
156 | if (ret < 0) | 156 | if (ret < 0) |
157 | goto cleanup_table; | 157 | goto cleanup_table; |
158 | 158 | ||
159 | ret = nf_register_hook(&ip6t_ops[1]); | ||
160 | if (ret < 0) | ||
161 | goto cleanup_hook0; | ||
162 | |||
163 | return ret; | 159 | return ret; |
164 | 160 | ||
165 | cleanup_hook0: | ||
166 | nf_unregister_hook(&ip6t_ops[0]); | ||
167 | cleanup_table: | 161 | cleanup_table: |
168 | ip6t_unregister_table(&packet_raw); | 162 | ip6t_unregister_table(&packet_raw); |
169 | |||
170 | return ret; | 163 | return ret; |
171 | } | 164 | } |
172 | 165 | ||
173 | static void __exit ip6table_raw_fini(void) | 166 | static void __exit ip6table_raw_fini(void) |
174 | { | 167 | { |
175 | unsigned int i; | 168 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
176 | |||
177 | for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) | ||
178 | nf_unregister_hook(&ip6t_ops[i]); | ||
179 | |||
180 | ip6t_unregister_table(&packet_raw); | 169 | ip6t_unregister_table(&packet_raw); |
181 | } | 170 | } |
182 | 171 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c8b5a96cbb0f..93bae36f2663 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, | |||
286 | return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); | 286 | return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); |
287 | } | 287 | } |
288 | 288 | ||
289 | /* Connection tracking may drop packets, but never alters them, so | 289 | static struct nf_hook_ops ipv6_conntrack_ops[] = { |
290 | make it the first hook. */ | 290 | { |
291 | static struct nf_hook_ops ipv6_conntrack_defrag_ops = { | 291 | .hook = ipv6_defrag, |
292 | .hook = ipv6_defrag, | 292 | .owner = THIS_MODULE, |
293 | .owner = THIS_MODULE, | 293 | .pf = PF_INET6, |
294 | .pf = PF_INET6, | 294 | .hooknum = NF_IP6_PRE_ROUTING, |
295 | .hooknum = NF_IP6_PRE_ROUTING, | 295 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, |
296 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | 296 | }, |
297 | }; | 297 | { |
298 | 298 | .hook = ipv6_conntrack_in, | |
299 | static struct nf_hook_ops ipv6_conntrack_in_ops = { | 299 | .owner = THIS_MODULE, |
300 | .hook = ipv6_conntrack_in, | 300 | .pf = PF_INET6, |
301 | .owner = THIS_MODULE, | 301 | .hooknum = NF_IP6_PRE_ROUTING, |
302 | .pf = PF_INET6, | 302 | .priority = NF_IP6_PRI_CONNTRACK, |
303 | .hooknum = NF_IP6_PRE_ROUTING, | 303 | }, |
304 | .priority = NF_IP6_PRI_CONNTRACK, | 304 | { |
305 | }; | 305 | .hook = ipv6_conntrack_local, |
306 | 306 | .owner = THIS_MODULE, | |
307 | static struct nf_hook_ops ipv6_conntrack_local_out_ops = { | 307 | .pf = PF_INET6, |
308 | .hook = ipv6_conntrack_local, | 308 | .hooknum = NF_IP6_LOCAL_OUT, |
309 | .owner = THIS_MODULE, | 309 | .priority = NF_IP6_PRI_CONNTRACK, |
310 | .pf = PF_INET6, | 310 | }, |
311 | .hooknum = NF_IP6_LOCAL_OUT, | 311 | { |
312 | .priority = NF_IP6_PRI_CONNTRACK, | 312 | .hook = ipv6_defrag, |
313 | }; | 313 | .owner = THIS_MODULE, |
314 | 314 | .pf = PF_INET6, | |
315 | static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = { | 315 | .hooknum = NF_IP6_LOCAL_OUT, |
316 | .hook = ipv6_defrag, | 316 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, |
317 | .owner = THIS_MODULE, | 317 | }, |
318 | .pf = PF_INET6, | 318 | { |
319 | .hooknum = NF_IP6_LOCAL_OUT, | 319 | .hook = ipv6_confirm, |
320 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | 320 | .owner = THIS_MODULE, |
321 | }; | 321 | .pf = PF_INET6, |
322 | 322 | .hooknum = NF_IP6_POST_ROUTING, | |
323 | /* Refragmenter; last chance. */ | 323 | .priority = NF_IP6_PRI_LAST, |
324 | static struct nf_hook_ops ipv6_conntrack_out_ops = { | 324 | }, |
325 | .hook = ipv6_confirm, | 325 | { |
326 | .owner = THIS_MODULE, | 326 | .hook = ipv6_confirm, |
327 | .pf = PF_INET6, | 327 | .owner = THIS_MODULE, |
328 | .hooknum = NF_IP6_POST_ROUTING, | 328 | .pf = PF_INET6, |
329 | .priority = NF_IP6_PRI_LAST, | 329 | .hooknum = NF_IP6_LOCAL_IN, |
330 | }; | 330 | .priority = NF_IP6_PRI_LAST-1, |
331 | 331 | }, | |
332 | static struct nf_hook_ops ipv6_conntrack_local_in_ops = { | ||
333 | .hook = ipv6_confirm, | ||
334 | .owner = THIS_MODULE, | ||
335 | .pf = PF_INET6, | ||
336 | .hooknum = NF_IP6_LOCAL_IN, | ||
337 | .priority = NF_IP6_PRI_LAST-1, | ||
338 | }; | 332 | }; |
339 | 333 | ||
340 | #ifdef CONFIG_SYSCTL | 334 | #ifdef CONFIG_SYSCTL |
@@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6; | |||
470 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; | 464 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; |
471 | extern int nf_ct_frag6_init(void); | 465 | extern int nf_ct_frag6_init(void); |
472 | extern void nf_ct_frag6_cleanup(void); | 466 | extern void nf_ct_frag6_cleanup(void); |
473 | static int init_or_cleanup(int init) | 467 | |
468 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | ||
469 | MODULE_LICENSE("GPL"); | ||
470 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | ||
471 | |||
472 | static int __init nf_conntrack_l3proto_ipv6_init(void) | ||
474 | { | 473 | { |
475 | int ret = 0; | 474 | int ret = 0; |
476 | 475 | ||
477 | if (!init) goto cleanup; | 476 | need_conntrack(); |
478 | 477 | ||
479 | ret = nf_ct_frag6_init(); | 478 | ret = nf_ct_frag6_init(); |
480 | if (ret < 0) { | 479 | if (ret < 0) { |
481 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); | 480 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); |
482 | goto cleanup_nothing; | 481 | return ret; |
483 | } | 482 | } |
484 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); | 483 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); |
485 | if (ret < 0) { | 484 | if (ret < 0) { |
@@ -505,71 +504,27 @@ static int init_or_cleanup(int init) | |||
505 | goto cleanup_icmpv6; | 504 | goto cleanup_icmpv6; |
506 | } | 505 | } |
507 | 506 | ||
508 | ret = nf_register_hook(&ipv6_conntrack_defrag_ops); | 507 | ret = nf_register_hooks(ipv6_conntrack_ops, |
508 | ARRAY_SIZE(ipv6_conntrack_ops)); | ||
509 | if (ret < 0) { | 509 | if (ret < 0) { |
510 | printk("nf_conntrack_ipv6: can't register pre-routing defrag " | 510 | printk("nf_conntrack_ipv6: can't register pre-routing defrag " |
511 | "hook.\n"); | 511 | "hook.\n"); |
512 | goto cleanup_ipv6; | 512 | goto cleanup_ipv6; |
513 | } | 513 | } |
514 | |||
515 | ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops); | ||
516 | if (ret < 0) { | ||
517 | printk("nf_conntrack_ipv6: can't register local_out defrag " | ||
518 | "hook.\n"); | ||
519 | goto cleanup_defragops; | ||
520 | } | ||
521 | |||
522 | ret = nf_register_hook(&ipv6_conntrack_in_ops); | ||
523 | if (ret < 0) { | ||
524 | printk("nf_conntrack_ipv6: can't register pre-routing hook.\n"); | ||
525 | goto cleanup_defraglocalops; | ||
526 | } | ||
527 | |||
528 | ret = nf_register_hook(&ipv6_conntrack_local_out_ops); | ||
529 | if (ret < 0) { | ||
530 | printk("nf_conntrack_ipv6: can't register local out hook.\n"); | ||
531 | goto cleanup_inops; | ||
532 | } | ||
533 | |||
534 | ret = nf_register_hook(&ipv6_conntrack_out_ops); | ||
535 | if (ret < 0) { | ||
536 | printk("nf_conntrack_ipv6: can't register post-routing hook.\n"); | ||
537 | goto cleanup_inandlocalops; | ||
538 | } | ||
539 | |||
540 | ret = nf_register_hook(&ipv6_conntrack_local_in_ops); | ||
541 | if (ret < 0) { | ||
542 | printk("nf_conntrack_ipv6: can't register local in hook.\n"); | ||
543 | goto cleanup_inoutandlocalops; | ||
544 | } | ||
545 | |||
546 | #ifdef CONFIG_SYSCTL | 514 | #ifdef CONFIG_SYSCTL |
547 | nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | 515 | nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); |
548 | if (nf_ct_ipv6_sysctl_header == NULL) { | 516 | if (nf_ct_ipv6_sysctl_header == NULL) { |
549 | printk("nf_conntrack: can't register to sysctl.\n"); | 517 | printk("nf_conntrack: can't register to sysctl.\n"); |
550 | ret = -ENOMEM; | 518 | ret = -ENOMEM; |
551 | goto cleanup_localinops; | 519 | goto cleanup_hooks; |
552 | } | 520 | } |
553 | #endif | 521 | #endif |
554 | return ret; | 522 | return ret; |
555 | 523 | ||
556 | cleanup: | ||
557 | synchronize_net(); | ||
558 | #ifdef CONFIG_SYSCTL | 524 | #ifdef CONFIG_SYSCTL |
559 | unregister_sysctl_table(nf_ct_ipv6_sysctl_header); | 525 | cleanup_hooks: |
560 | cleanup_localinops: | 526 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); |
561 | #endif | 527 | #endif |
562 | nf_unregister_hook(&ipv6_conntrack_local_in_ops); | ||
563 | cleanup_inoutandlocalops: | ||
564 | nf_unregister_hook(&ipv6_conntrack_out_ops); | ||
565 | cleanup_inandlocalops: | ||
566 | nf_unregister_hook(&ipv6_conntrack_local_out_ops); | ||
567 | cleanup_inops: | ||
568 | nf_unregister_hook(&ipv6_conntrack_in_ops); | ||
569 | cleanup_defraglocalops: | ||
570 | nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops); | ||
571 | cleanup_defragops: | ||
572 | nf_unregister_hook(&ipv6_conntrack_defrag_ops); | ||
573 | cleanup_ipv6: | 528 | cleanup_ipv6: |
574 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); | 529 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); |
575 | cleanup_icmpv6: | 530 | cleanup_icmpv6: |
@@ -580,23 +535,21 @@ static int init_or_cleanup(int init) | |||
580 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); | 535 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); |
581 | cleanup_frag6: | 536 | cleanup_frag6: |
582 | nf_ct_frag6_cleanup(); | 537 | nf_ct_frag6_cleanup(); |
583 | cleanup_nothing: | ||
584 | return ret; | 538 | return ret; |
585 | } | 539 | } |
586 | 540 | ||
587 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | ||
588 | MODULE_LICENSE("GPL"); | ||
589 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | ||
590 | |||
591 | static int __init nf_conntrack_l3proto_ipv6_init(void) | ||
592 | { | ||
593 | need_conntrack(); | ||
594 | return init_or_cleanup(1); | ||
595 | } | ||
596 | |||
597 | static void __exit nf_conntrack_l3proto_ipv6_fini(void) | 541 | static void __exit nf_conntrack_l3proto_ipv6_fini(void) |
598 | { | 542 | { |
599 | init_or_cleanup(0); | 543 | synchronize_net(); |
544 | #ifdef CONFIG_SYSCTL | ||
545 | unregister_sysctl_table(nf_ct_ipv6_sysctl_header); | ||
546 | #endif | ||
547 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); | ||
548 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); | ||
549 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); | ||
550 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); | ||
551 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); | ||
552 | nf_ct_frag6_cleanup(); | ||
600 | } | 553 | } |
601 | 554 | ||
602 | module_init(nf_conntrack_l3proto_ipv6_init); | 555 | module_init(nf_conntrack_l3proto_ipv6_init); |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 09945c333055..86c6703265d0 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, | |||
233 | return -NF_ACCEPT; | 233 | return -NF_ACCEPT; |
234 | } | 234 | } |
235 | 235 | ||
236 | if (hooknum != NF_IP6_PRE_ROUTING) | 236 | if (hooknum == NF_IP6_PRE_ROUTING && |
237 | goto skipped; | 237 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { |
238 | |||
239 | /* Ignore it if the checksum's bogus. */ | ||
240 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, | ||
241 | skb->len - dataoff, IPPROTO_ICMPV6, | ||
242 | skb_checksum(skb, dataoff, | ||
243 | skb->len - dataoff, 0))) { | ||
244 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 238 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, |
245 | "nf_ct_icmpv6: ICMPv6 checksum failed\n"); | 239 | "nf_ct_icmpv6: ICMPv6 checksum failed\n"); |
246 | return -NF_ACCEPT; | 240 | return -NF_ACCEPT; |
247 | } | 241 | } |
248 | 242 | ||
249 | skipped: | ||
250 | |||
251 | /* is not error message ? */ | 243 | /* is not error message ? */ |
252 | if (icmp6h->icmp6_type >= 128) | 244 | if (icmp6h->icmp6_type >= 128) |
253 | return NF_ACCEPT; | 245 | return NF_ACCEPT; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index c2d3e17beae6..6578c3080f47 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
397 | return 0; | 397 | return 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); | 400 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
401 | kfree_skb(skb); | 401 | kfree_skb(skb); |
402 | read_unlock(&ipip6_lock); | 402 | read_unlock(&ipip6_lock); |
403 | out: | 403 | out: |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 5659b52284bd..0ef9a35798d1 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -19,11 +19,13 @@ | |||
19 | * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 19 | * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/icmpv6.h> | ||
22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
25 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
26 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
28 | #include <net/ipv6.h> | ||
27 | #include <net/protocol.h> | 29 | #include <net/protocol.h> |
28 | #include <net/xfrm.h> | 30 | #include <net/xfrm.h> |
29 | 31 | ||
@@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb) | |||
87 | struct sk_buff *skb = *pskb; | 89 | struct sk_buff *skb = *pskb; |
88 | struct xfrm6_tunnel *handler; | 90 | struct xfrm6_tunnel *handler; |
89 | 91 | ||
92 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
93 | goto drop; | ||
94 | |||
90 | for (handler = tunnel6_handlers; handler; handler = handler->next) | 95 | for (handler = tunnel6_handlers; handler; handler = handler->next) |
91 | if (!handler->handler(skb)) | 96 | if (!handler->handler(skb)) |
92 | return 0; | 97 | return 0; |
93 | 98 | ||
99 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); | ||
100 | |||
101 | drop: | ||
94 | kfree_skb(skb); | 102 | kfree_skb(skb); |
95 | return 0; | 103 | return 0; |
96 | } | 104 | } |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 1ceb1a6c254b..8455a32ea5c4 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -27,6 +27,29 @@ | |||
27 | 27 | ||
28 | #include "nf_internals.h" | 28 | #include "nf_internals.h" |
29 | 29 | ||
30 | static DEFINE_SPINLOCK(afinfo_lock); | ||
31 | |||
32 | struct nf_afinfo *nf_afinfo[NPROTO]; | ||
33 | EXPORT_SYMBOL(nf_afinfo); | ||
34 | |||
35 | int nf_register_afinfo(struct nf_afinfo *afinfo) | ||
36 | { | ||
37 | spin_lock(&afinfo_lock); | ||
38 | rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo); | ||
39 | spin_unlock(&afinfo_lock); | ||
40 | return 0; | ||
41 | } | ||
42 | EXPORT_SYMBOL_GPL(nf_register_afinfo); | ||
43 | |||
44 | void nf_unregister_afinfo(struct nf_afinfo *afinfo) | ||
45 | { | ||
46 | spin_lock(&afinfo_lock); | ||
47 | rcu_assign_pointer(nf_afinfo[afinfo->family], NULL); | ||
48 | spin_unlock(&afinfo_lock); | ||
49 | synchronize_rcu(); | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(nf_unregister_afinfo); | ||
52 | |||
30 | /* In this code, we can be waiting indefinitely for userspace to | 53 | /* In this code, we can be waiting indefinitely for userspace to |
31 | * service a packet if a hook returns NF_QUEUE. We could keep a count | 54 | * service a packet if a hook returns NF_QUEUE. We could keep a count |
32 | * of skbuffs queued for userspace, and not deregister a hook unless | 55 | * of skbuffs queued for userspace, and not deregister a hook unless |
@@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg) | |||
63 | } | 86 | } |
64 | EXPORT_SYMBOL(nf_unregister_hook); | 87 | EXPORT_SYMBOL(nf_unregister_hook); |
65 | 88 | ||
89 | int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n) | ||
90 | { | ||
91 | unsigned int i; | ||
92 | int err = 0; | ||
93 | |||
94 | for (i = 0; i < n; i++) { | ||
95 | err = nf_register_hook(®[i]); | ||
96 | if (err) | ||
97 | goto err; | ||
98 | } | ||
99 | return err; | ||
100 | |||
101 | err: | ||
102 | if (i > 0) | ||
103 | nf_unregister_hooks(reg, i); | ||
104 | return err; | ||
105 | } | ||
106 | EXPORT_SYMBOL(nf_register_hooks); | ||
107 | |||
108 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | ||
109 | { | ||
110 | unsigned int i; | ||
111 | |||
112 | for (i = 0; i < n; i++) | ||
113 | nf_unregister_hook(®[i]); | ||
114 | } | ||
115 | EXPORT_SYMBOL(nf_unregister_hooks); | ||
116 | |||
66 | unsigned int nf_iterate(struct list_head *head, | 117 | unsigned int nf_iterate(struct list_head *head, |
67 | struct sk_buff **skb, | 118 | struct sk_buff **skb, |
68 | int hook, | 119 | int hook, |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 6492ed66fb3c..69899f27d26a 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb, | |||
799 | unsigned int dataoff, | 799 | unsigned int dataoff, |
800 | enum ip_conntrack_info *ctinfo, | 800 | enum ip_conntrack_info *ctinfo, |
801 | int pf, | 801 | int pf, |
802 | unsigned int hooknum, | 802 | unsigned int hooknum) |
803 | int(*csum)(const struct sk_buff *,unsigned int)) | ||
804 | { | 803 | { |
805 | struct tcphdr _tcph, *th; | 804 | struct tcphdr _tcph, *th; |
806 | unsigned int tcplen = skb->len - dataoff; | 805 | unsigned int tcplen = skb->len - dataoff; |
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb, | |||
830 | */ | 829 | */ |
831 | /* FIXME: Source route IP option packets --RR */ | 830 | /* FIXME: Source route IP option packets --RR */ |
832 | if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || | 831 | if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || |
833 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) | 832 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && |
834 | && skb->ip_summed != CHECKSUM_UNNECESSARY | 833 | nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { |
835 | && csum(skb, dataoff)) { | ||
836 | if (LOG_INVALID(IPPROTO_TCP)) | 834 | if (LOG_INVALID(IPPROTO_TCP)) |
837 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 835 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
838 | "nf_ct_tcp: bad TCP checksum "); | 836 | "nf_ct_tcp: bad TCP checksum "); |
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb, | |||
851 | return NF_ACCEPT; | 849 | return NF_ACCEPT; |
852 | } | 850 | } |
853 | 851 | ||
854 | static int csum4(const struct sk_buff *skb, unsigned int dataoff) | ||
855 | { | ||
856 | return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, | ||
857 | skb->len - dataoff, IPPROTO_TCP, | ||
858 | skb->ip_summed == CHECKSUM_HW ? skb->csum | ||
859 | : skb_checksum(skb, dataoff, | ||
860 | skb->len - dataoff, 0)); | ||
861 | } | ||
862 | |||
863 | static int csum6(const struct sk_buff *skb, unsigned int dataoff) | ||
864 | { | ||
865 | return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, | ||
866 | skb->len - dataoff, IPPROTO_TCP, | ||
867 | skb->ip_summed == CHECKSUM_HW | ||
868 | ? csum_sub(skb->csum, | ||
869 | skb_checksum(skb, 0, dataoff, 0)) | ||
870 | : skb_checksum(skb, dataoff, skb->len - dataoff, | ||
871 | 0)); | ||
872 | } | ||
873 | |||
874 | static int tcp_error4(struct sk_buff *skb, | ||
875 | unsigned int dataoff, | ||
876 | enum ip_conntrack_info *ctinfo, | ||
877 | int pf, | ||
878 | unsigned int hooknum) | ||
879 | { | ||
880 | return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4); | ||
881 | } | ||
882 | |||
883 | static int tcp_error6(struct sk_buff *skb, | ||
884 | unsigned int dataoff, | ||
885 | enum ip_conntrack_info *ctinfo, | ||
886 | int pf, | ||
887 | unsigned int hooknum) | ||
888 | { | ||
889 | return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6); | ||
890 | } | ||
891 | |||
892 | /* Returns verdict for packet, or -1 for invalid. */ | 852 | /* Returns verdict for packet, or -1 for invalid. */ |
893 | static int tcp_packet(struct nf_conn *conntrack, | 853 | static int tcp_packet(struct nf_conn *conntrack, |
894 | const struct sk_buff *skb, | 854 | const struct sk_buff *skb, |
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 = | |||
1218 | .print_conntrack = tcp_print_conntrack, | 1178 | .print_conntrack = tcp_print_conntrack, |
1219 | .packet = tcp_packet, | 1179 | .packet = tcp_packet, |
1220 | .new = tcp_new, | 1180 | .new = tcp_new, |
1221 | .error = tcp_error4, | 1181 | .error = tcp_error, |
1222 | #if defined(CONFIG_NF_CT_NETLINK) || \ | 1182 | #if defined(CONFIG_NF_CT_NETLINK) || \ |
1223 | defined(CONFIG_NF_CT_NETLINK_MODULE) | 1183 | defined(CONFIG_NF_CT_NETLINK_MODULE) |
1224 | .to_nfattr = tcp_to_nfattr, | 1184 | .to_nfattr = tcp_to_nfattr, |
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 = | |||
1239 | .print_conntrack = tcp_print_conntrack, | 1199 | .print_conntrack = tcp_print_conntrack, |
1240 | .packet = tcp_packet, | 1200 | .packet = tcp_packet, |
1241 | .new = tcp_new, | 1201 | .new = tcp_new, |
1242 | .error = tcp_error6, | 1202 | .error = tcp_error, |
1243 | #if defined(CONFIG_NF_CT_NETLINK) || \ | 1203 | #if defined(CONFIG_NF_CT_NETLINK) || \ |
1244 | defined(CONFIG_NF_CT_NETLINK_MODULE) | 1204 | defined(CONFIG_NF_CT_NETLINK_MODULE) |
1245 | .to_nfattr = tcp_to_nfattr, | 1205 | .to_nfattr = tcp_to_nfattr, |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 831d206344e0..d93edbfde9e3 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
103 | static int udp_error(struct sk_buff *skb, unsigned int dataoff, | 103 | static int udp_error(struct sk_buff *skb, unsigned int dataoff, |
104 | enum ip_conntrack_info *ctinfo, | 104 | enum ip_conntrack_info *ctinfo, |
105 | int pf, | 105 | int pf, |
106 | unsigned int hooknum, | 106 | unsigned int hooknum) |
107 | int (*csum)(const struct sk_buff *, unsigned int)) | ||
108 | { | 107 | { |
109 | unsigned int udplen = skb->len - dataoff; | 108 | unsigned int udplen = skb->len - dataoff; |
110 | struct udphdr _hdr, *hdr; | 109 | struct udphdr _hdr, *hdr; |
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, | |||
136 | * and moreover root might send raw packets. | 135 | * and moreover root might send raw packets. |
137 | * FIXME: Source route IP option packets --RR */ | 136 | * FIXME: Source route IP option packets --RR */ |
138 | if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || | 137 | if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || |
139 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) | 138 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && |
140 | && skb->ip_summed != CHECKSUM_UNNECESSARY | 139 | nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { |
141 | && csum(skb, dataoff)) { | ||
142 | if (LOG_INVALID(IPPROTO_UDP)) | 140 | if (LOG_INVALID(IPPROTO_UDP)) |
143 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 141 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
144 | "nf_ct_udp: bad UDP checksum "); | 142 | "nf_ct_udp: bad UDP checksum "); |
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, | |||
148 | return NF_ACCEPT; | 146 | return NF_ACCEPT; |
149 | } | 147 | } |
150 | 148 | ||
151 | static int csum4(const struct sk_buff *skb, unsigned int dataoff) | ||
152 | { | ||
153 | return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, | ||
154 | skb->len - dataoff, IPPROTO_UDP, | ||
155 | skb->ip_summed == CHECKSUM_HW ? skb->csum | ||
156 | : skb_checksum(skb, dataoff, | ||
157 | skb->len - dataoff, 0)); | ||
158 | } | ||
159 | |||
160 | static int csum6(const struct sk_buff *skb, unsigned int dataoff) | ||
161 | { | ||
162 | return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, | ||
163 | skb->len - dataoff, IPPROTO_UDP, | ||
164 | skb->ip_summed == CHECKSUM_HW | ||
165 | ? csum_sub(skb->csum, | ||
166 | skb_checksum(skb, 0, dataoff, 0)) | ||
167 | : skb_checksum(skb, dataoff, skb->len - dataoff, | ||
168 | 0)); | ||
169 | } | ||
170 | |||
171 | static int udp_error4(struct sk_buff *skb, | ||
172 | unsigned int dataoff, | ||
173 | enum ip_conntrack_info *ctinfo, | ||
174 | int pf, | ||
175 | unsigned int hooknum) | ||
176 | { | ||
177 | return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4); | ||
178 | } | ||
179 | |||
180 | static int udp_error6(struct sk_buff *skb, | ||
181 | unsigned int dataoff, | ||
182 | enum ip_conntrack_info *ctinfo, | ||
183 | int pf, | ||
184 | unsigned int hooknum) | ||
185 | { | ||
186 | return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6); | ||
187 | } | ||
188 | |||
189 | struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = | 149 | struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = |
190 | { | 150 | { |
191 | .l3proto = PF_INET, | 151 | .l3proto = PF_INET, |
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = | |||
197 | .print_conntrack = udp_print_conntrack, | 157 | .print_conntrack = udp_print_conntrack, |
198 | .packet = udp_packet, | 158 | .packet = udp_packet, |
199 | .new = udp_new, | 159 | .new = udp_new, |
200 | .error = udp_error4, | 160 | .error = udp_error, |
201 | #if defined(CONFIG_NF_CT_NETLINK) || \ | 161 | #if defined(CONFIG_NF_CT_NETLINK) || \ |
202 | defined(CONFIG_NF_CT_NETLINK_MODULE) | 162 | defined(CONFIG_NF_CT_NETLINK_MODULE) |
203 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | 163 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, |
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 = | |||
216 | .print_conntrack = udp_print_conntrack, | 176 | .print_conntrack = udp_print_conntrack, |
217 | .packet = udp_packet, | 177 | .packet = udp_packet, |
218 | .new = udp_new, | 178 | .new = udp_new, |
219 | .error = udp_error6, | 179 | .error = udp_error, |
220 | #if defined(CONFIG_NF_CT_NETLINK) || \ | 180 | #if defined(CONFIG_NF_CT_NETLINK) || \ |
221 | defined(CONFIG_NF_CT_NETLINK_MODULE) | 181 | defined(CONFIG_NF_CT_NETLINK_MODULE) |
222 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | 182 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index c72aa3cd22e4..408960c6a544 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = { | |||
649 | EXPORT_SYMBOL(nf_ct_log_invalid); | 649 | EXPORT_SYMBOL(nf_ct_log_invalid); |
650 | #endif /* CONFIG_SYSCTL */ | 650 | #endif /* CONFIG_SYSCTL */ |
651 | 651 | ||
652 | static int init_or_cleanup(int init) | ||
653 | { | ||
654 | #ifdef CONFIG_PROC_FS | ||
655 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; | ||
656 | #endif | ||
657 | int ret = 0; | ||
658 | |||
659 | if (!init) goto cleanup; | ||
660 | |||
661 | ret = nf_conntrack_init(); | ||
662 | if (ret < 0) | ||
663 | goto cleanup_nothing; | ||
664 | |||
665 | #ifdef CONFIG_PROC_FS | ||
666 | proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); | ||
667 | if (!proc) goto cleanup_init; | ||
668 | |||
669 | proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, | ||
670 | &exp_file_ops); | ||
671 | if (!proc_exp) goto cleanup_proc; | ||
672 | |||
673 | proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); | ||
674 | if (!proc_stat) | ||
675 | goto cleanup_proc_exp; | ||
676 | |||
677 | proc_stat->proc_fops = &ct_cpu_seq_fops; | ||
678 | proc_stat->owner = THIS_MODULE; | ||
679 | #endif | ||
680 | #ifdef CONFIG_SYSCTL | ||
681 | nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | ||
682 | if (nf_ct_sysctl_header == NULL) { | ||
683 | printk("nf_conntrack: can't register to sysctl.\n"); | ||
684 | ret = -ENOMEM; | ||
685 | goto cleanup_proc_stat; | ||
686 | } | ||
687 | #endif | ||
688 | |||
689 | return ret; | ||
690 | |||
691 | cleanup: | ||
692 | #ifdef CONFIG_SYSCTL | ||
693 | unregister_sysctl_table(nf_ct_sysctl_header); | ||
694 | cleanup_proc_stat: | ||
695 | #endif | ||
696 | #ifdef CONFIG_PROC_FS | ||
697 | remove_proc_entry("nf_conntrack", proc_net_stat); | ||
698 | cleanup_proc_exp: | ||
699 | proc_net_remove("nf_conntrack_expect"); | ||
700 | cleanup_proc: | ||
701 | proc_net_remove("nf_conntrack"); | ||
702 | cleanup_init: | ||
703 | #endif /* CNFIG_PROC_FS */ | ||
704 | nf_conntrack_cleanup(); | ||
705 | cleanup_nothing: | ||
706 | return ret; | ||
707 | } | ||
708 | |||
709 | int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | 652 | int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) |
710 | { | 653 | { |
711 | int ret = 0; | 654 | int ret = 0; |
@@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) | |||
808 | 751 | ||
809 | static int __init nf_conntrack_standalone_init(void) | 752 | static int __init nf_conntrack_standalone_init(void) |
810 | { | 753 | { |
811 | return init_or_cleanup(1); | 754 | #ifdef CONFIG_PROC_FS |
755 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; | ||
756 | #endif | ||
757 | int ret = 0; | ||
758 | |||
759 | ret = nf_conntrack_init(); | ||
760 | if (ret < 0) | ||
761 | return ret; | ||
762 | |||
763 | #ifdef CONFIG_PROC_FS | ||
764 | proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); | ||
765 | if (!proc) goto cleanup_init; | ||
766 | |||
767 | proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, | ||
768 | &exp_file_ops); | ||
769 | if (!proc_exp) goto cleanup_proc; | ||
770 | |||
771 | proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); | ||
772 | if (!proc_stat) | ||
773 | goto cleanup_proc_exp; | ||
774 | |||
775 | proc_stat->proc_fops = &ct_cpu_seq_fops; | ||
776 | proc_stat->owner = THIS_MODULE; | ||
777 | #endif | ||
778 | #ifdef CONFIG_SYSCTL | ||
779 | nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | ||
780 | if (nf_ct_sysctl_header == NULL) { | ||
781 | printk("nf_conntrack: can't register to sysctl.\n"); | ||
782 | ret = -ENOMEM; | ||
783 | goto cleanup_proc_stat; | ||
784 | } | ||
785 | #endif | ||
786 | return ret; | ||
787 | |||
788 | #ifdef CONFIG_SYSCTL | ||
789 | cleanup_proc_stat: | ||
790 | #endif | ||
791 | #ifdef CONFIG_PROC_FS | ||
792 | remove_proc_entry("nf_conntrack", proc_net_stat); | ||
793 | cleanup_proc_exp: | ||
794 | proc_net_remove("nf_conntrack_expect"); | ||
795 | cleanup_proc: | ||
796 | proc_net_remove("nf_conntrack"); | ||
797 | cleanup_init: | ||
798 | #endif /* CNFIG_PROC_FS */ | ||
799 | nf_conntrack_cleanup(); | ||
800 | return ret; | ||
812 | } | 801 | } |
813 | 802 | ||
814 | static void __exit nf_conntrack_standalone_fini(void) | 803 | static void __exit nf_conntrack_standalone_fini(void) |
815 | { | 804 | { |
816 | init_or_cleanup(0); | 805 | #ifdef CONFIG_SYSCTL |
806 | unregister_sysctl_table(nf_ct_sysctl_header); | ||
807 | #endif | ||
808 | #ifdef CONFIG_PROC_FS | ||
809 | remove_proc_entry("nf_conntrack", proc_net_stat); | ||
810 | proc_net_remove("nf_conntrack_expect"); | ||
811 | proc_net_remove("nf_conntrack"); | ||
812 | #endif /* CNFIG_PROC_FS */ | ||
813 | nf_conntrack_cleanup(); | ||
817 | } | 814 | } |
818 | 815 | ||
819 | module_init(nf_conntrack_standalone_init); | 816 | module_init(nf_conntrack_standalone_init); |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d9f0d7ef103b..ee8f70889f47 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * for queueing and must reinject all packets it receives, no matter what. | 17 | * for queueing and must reinject all packets it receives, no matter what. |
18 | */ | 18 | */ |
19 | static struct nf_queue_handler *queue_handler[NPROTO]; | 19 | static struct nf_queue_handler *queue_handler[NPROTO]; |
20 | static struct nf_queue_rerouter *queue_rerouter[NPROTO]; | ||
21 | 20 | ||
22 | static DEFINE_RWLOCK(queue_handler_lock); | 21 | static DEFINE_RWLOCK(queue_handler_lock); |
23 | 22 | ||
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf) | |||
59 | } | 58 | } |
60 | EXPORT_SYMBOL(nf_unregister_queue_handler); | 59 | EXPORT_SYMBOL(nf_unregister_queue_handler); |
61 | 60 | ||
62 | int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer) | ||
63 | { | ||
64 | if (pf >= NPROTO) | ||
65 | return -EINVAL; | ||
66 | |||
67 | write_lock_bh(&queue_handler_lock); | ||
68 | rcu_assign_pointer(queue_rerouter[pf], rer); | ||
69 | write_unlock_bh(&queue_handler_lock); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); | ||
74 | |||
75 | int nf_unregister_queue_rerouter(int pf) | ||
76 | { | ||
77 | if (pf >= NPROTO) | ||
78 | return -EINVAL; | ||
79 | |||
80 | write_lock_bh(&queue_handler_lock); | ||
81 | rcu_assign_pointer(queue_rerouter[pf], NULL); | ||
82 | write_unlock_bh(&queue_handler_lock); | ||
83 | synchronize_rcu(); | ||
84 | return 0; | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); | ||
87 | |||
88 | void nf_unregister_queue_handlers(struct nf_queue_handler *qh) | 61 | void nf_unregister_queue_handlers(struct nf_queue_handler *qh) |
89 | { | 62 | { |
90 | int pf; | 63 | int pf; |
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb, | |||
116 | struct net_device *physindev = NULL; | 89 | struct net_device *physindev = NULL; |
117 | struct net_device *physoutdev = NULL; | 90 | struct net_device *physoutdev = NULL; |
118 | #endif | 91 | #endif |
119 | struct nf_queue_rerouter *rerouter; | 92 | struct nf_afinfo *afinfo; |
120 | 93 | ||
121 | /* QUEUE == DROP if noone is waiting, to be safe. */ | 94 | /* QUEUE == DROP if noone is waiting, to be safe. */ |
122 | read_lock(&queue_handler_lock); | 95 | read_lock(&queue_handler_lock); |
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb, | |||
126 | return 1; | 99 | return 1; |
127 | } | 100 | } |
128 | 101 | ||
129 | info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); | 102 | afinfo = nf_get_afinfo(pf); |
103 | if (!afinfo) { | ||
104 | read_unlock(&queue_handler_lock); | ||
105 | kfree_skb(*skb); | ||
106 | return 1; | ||
107 | } | ||
108 | |||
109 | info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC); | ||
130 | if (!info) { | 110 | if (!info) { |
131 | if (net_ratelimit()) | 111 | if (net_ratelimit()) |
132 | printk(KERN_ERR "OOM queueing packet %p\n", | 112 | printk(KERN_ERR "OOM queueing packet %p\n", |
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb, | |||
158 | if (physoutdev) dev_hold(physoutdev); | 138 | if (physoutdev) dev_hold(physoutdev); |
159 | } | 139 | } |
160 | #endif | 140 | #endif |
161 | rerouter = rcu_dereference(queue_rerouter[pf]); | 141 | afinfo->saveroute(*skb, info); |
162 | if (rerouter) | ||
163 | rerouter->save(*skb, info); | ||
164 | |||
165 | status = queue_handler[pf]->outfn(*skb, info, queuenum, | 142 | status = queue_handler[pf]->outfn(*skb, info, queuenum, |
166 | queue_handler[pf]->data); | 143 | queue_handler[pf]->data); |
167 | 144 | ||
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, | |||
190 | { | 167 | { |
191 | struct list_head *elem = &info->elem->list; | 168 | struct list_head *elem = &info->elem->list; |
192 | struct list_head *i; | 169 | struct list_head *i; |
193 | struct nf_queue_rerouter *rerouter; | 170 | struct nf_afinfo *afinfo; |
194 | 171 | ||
195 | rcu_read_lock(); | 172 | rcu_read_lock(); |
196 | 173 | ||
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, | |||
228 | } | 205 | } |
229 | 206 | ||
230 | if (verdict == NF_ACCEPT) { | 207 | if (verdict == NF_ACCEPT) { |
231 | rerouter = rcu_dereference(queue_rerouter[info->pf]); | 208 | afinfo = nf_get_afinfo(info->pf); |
232 | if (rerouter && rerouter->reroute(&skb, info) < 0) | 209 | if (!afinfo || afinfo->reroute(&skb, info) < 0) |
233 | verdict = NF_DROP; | 210 | verdict = NF_DROP; |
234 | } | 211 | } |
235 | 212 | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3e3f5448bacb..c60273cad778 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = { | |||
1033 | 1033 | ||
1034 | #endif /* PROC_FS */ | 1034 | #endif /* PROC_FS */ |
1035 | 1035 | ||
1036 | static int | 1036 | static int __init nfnetlink_log_init(void) |
1037 | init_or_cleanup(int init) | ||
1038 | { | 1037 | { |
1039 | int i, status = -ENOMEM; | 1038 | int i, status = -ENOMEM; |
1040 | #ifdef CONFIG_PROC_FS | 1039 | #ifdef CONFIG_PROC_FS |
1041 | struct proc_dir_entry *proc_nful; | 1040 | struct proc_dir_entry *proc_nful; |
1042 | #endif | 1041 | #endif |
1043 | 1042 | ||
1044 | if (!init) | ||
1045 | goto cleanup; | ||
1046 | |||
1047 | for (i = 0; i < INSTANCE_BUCKETS; i++) | 1043 | for (i = 0; i < INSTANCE_BUCKETS; i++) |
1048 | INIT_HLIST_HEAD(&instance_table[i]); | 1044 | INIT_HLIST_HEAD(&instance_table[i]); |
1049 | 1045 | ||
@@ -1066,30 +1062,25 @@ init_or_cleanup(int init) | |||
1066 | goto cleanup_subsys; | 1062 | goto cleanup_subsys; |
1067 | proc_nful->proc_fops = &nful_file_ops; | 1063 | proc_nful->proc_fops = &nful_file_ops; |
1068 | #endif | 1064 | #endif |
1069 | |||
1070 | return status; | 1065 | return status; |
1071 | 1066 | ||
1072 | cleanup: | ||
1073 | nf_log_unregister_logger(&nfulnl_logger); | ||
1074 | #ifdef CONFIG_PROC_FS | 1067 | #ifdef CONFIG_PROC_FS |
1075 | remove_proc_entry("nfnetlink_log", proc_net_netfilter); | ||
1076 | cleanup_subsys: | 1068 | cleanup_subsys: |
1077 | #endif | ||
1078 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1069 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
1070 | #endif | ||
1079 | cleanup_netlink_notifier: | 1071 | cleanup_netlink_notifier: |
1080 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 1072 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
1081 | return status; | 1073 | return status; |
1082 | } | 1074 | } |
1083 | 1075 | ||
1084 | static int __init nfnetlink_log_init(void) | ||
1085 | { | ||
1086 | |||
1087 | return init_or_cleanup(1); | ||
1088 | } | ||
1089 | |||
1090 | static void __exit nfnetlink_log_fini(void) | 1076 | static void __exit nfnetlink_log_fini(void) |
1091 | { | 1077 | { |
1092 | init_or_cleanup(0); | 1078 | nf_log_unregister_logger(&nfulnl_logger); |
1079 | #ifdef CONFIG_PROC_FS | ||
1080 | remove_proc_entry("nfnetlink_log", proc_net_netfilter); | ||
1081 | #endif | ||
1082 | nfnetlink_subsys_unregister(&nfulnl_subsys); | ||
1083 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | ||
1093 | } | 1084 | } |
1094 | 1085 | ||
1095 | MODULE_DESCRIPTION("netfilter userspace logging"); | 1086 | MODULE_DESCRIPTION("netfilter userspace logging"); |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index d0e62f68139f..86a4ac33de34 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = { | |||
1071 | 1071 | ||
1072 | #endif /* PROC_FS */ | 1072 | #endif /* PROC_FS */ |
1073 | 1073 | ||
1074 | static int | 1074 | static int __init nfnetlink_queue_init(void) |
1075 | init_or_cleanup(int init) | ||
1076 | { | 1075 | { |
1077 | int i, status = -ENOMEM; | 1076 | int i, status = -ENOMEM; |
1078 | #ifdef CONFIG_PROC_FS | 1077 | #ifdef CONFIG_PROC_FS |
1079 | struct proc_dir_entry *proc_nfqueue; | 1078 | struct proc_dir_entry *proc_nfqueue; |
1080 | #endif | 1079 | #endif |
1081 | 1080 | ||
1082 | if (!init) | ||
1083 | goto cleanup; | ||
1084 | |||
1085 | for (i = 0; i < INSTANCE_BUCKETS; i++) | 1081 | for (i = 0; i < INSTANCE_BUCKETS; i++) |
1086 | INIT_HLIST_HEAD(&instance_table[i]); | 1082 | INIT_HLIST_HEAD(&instance_table[i]); |
1087 | 1083 | ||
@@ -1101,31 +1097,26 @@ init_or_cleanup(int init) | |||
1101 | #endif | 1097 | #endif |
1102 | 1098 | ||
1103 | register_netdevice_notifier(&nfqnl_dev_notifier); | 1099 | register_netdevice_notifier(&nfqnl_dev_notifier); |
1104 | |||
1105 | return status; | 1100 | return status; |
1106 | 1101 | ||
1107 | cleanup: | ||
1108 | nf_unregister_queue_handlers(&nfqh); | ||
1109 | unregister_netdevice_notifier(&nfqnl_dev_notifier); | ||
1110 | #ifdef CONFIG_PROC_FS | 1102 | #ifdef CONFIG_PROC_FS |
1111 | remove_proc_entry("nfnetlink_queue", proc_net_netfilter); | ||
1112 | cleanup_subsys: | 1103 | cleanup_subsys: |
1113 | #endif | ||
1114 | nfnetlink_subsys_unregister(&nfqnl_subsys); | 1104 | nfnetlink_subsys_unregister(&nfqnl_subsys); |
1105 | #endif | ||
1115 | cleanup_netlink_notifier: | 1106 | cleanup_netlink_notifier: |
1116 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1107 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
1117 | return status; | 1108 | return status; |
1118 | } | 1109 | } |
1119 | 1110 | ||
1120 | static int __init nfnetlink_queue_init(void) | ||
1121 | { | ||
1122 | |||
1123 | return init_or_cleanup(1); | ||
1124 | } | ||
1125 | |||
1126 | static void __exit nfnetlink_queue_fini(void) | 1111 | static void __exit nfnetlink_queue_fini(void) |
1127 | { | 1112 | { |
1128 | init_or_cleanup(0); | 1113 | nf_unregister_queue_handlers(&nfqh); |
1114 | unregister_netdevice_notifier(&nfqnl_dev_notifier); | ||
1115 | #ifdef CONFIG_PROC_FS | ||
1116 | remove_proc_entry("nfnetlink_queue", proc_net_netfilter); | ||
1117 | #endif | ||
1118 | nfnetlink_subsys_unregister(&nfqnl_subsys); | ||
1119 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | ||
1129 | } | 1120 | } |
1130 | 1121 | ||
1131 | MODULE_DESCRIPTION("netfilter packet queue handler"); | 1122 | MODULE_DESCRIPTION("netfilter packet queue handler"); |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index fa877f8f652c..24c348fa8922 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | #ifdef CONFIG_NET_CLS_ACT | 68 | #ifdef CONFIG_NET_CLS_ACT |
69 | static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | 69 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, |
70 | int type, struct tc_action *a) | 70 | int type, struct tc_action *a) |
71 | { | 71 | { |
72 | struct tcf_police *p; | 72 | struct tcf_police *p; |
@@ -113,7 +113,7 @@ rtattr_failure: | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static inline int | 115 | static inline int |
116 | tcf_hash_search(struct tc_action *a, u32 index) | 116 | tcf_act_police_hash_search(struct tc_action *a, u32 index) |
117 | { | 117 | { |
118 | struct tcf_police *p = tcf_police_lookup(index); | 118 | struct tcf_police *p = tcf_police_lookup(index); |
119 | 119 | ||
@@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = { | |||
387 | .act = tcf_act_police, | 387 | .act = tcf_act_police, |
388 | .dump = tcf_act_police_dump, | 388 | .dump = tcf_act_police_dump, |
389 | .cleanup = tcf_act_police_cleanup, | 389 | .cleanup = tcf_act_police_cleanup, |
390 | .lookup = tcf_hash_search, | 390 | .lookup = tcf_act_police_hash_search, |
391 | .init = tcf_act_police_locate, | 391 | .init = tcf_act_police_locate, |
392 | .walk = tcf_generic_walker | 392 | .walk = tcf_act_police_walker |
393 | }; | 393 | }; |
394 | 394 | ||
395 | static int __init | 395 | static int __init |
diff --git a/security/keys/key.c b/security/keys/key.c index a057e3311aad..b6061fa29da7 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -785,6 +785,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
785 | 785 | ||
786 | key_check(keyring); | 786 | key_check(keyring); |
787 | 787 | ||
788 | key_ref = ERR_PTR(-ENOTDIR); | ||
789 | if (keyring->type != &key_type_keyring) | ||
790 | goto error_2; | ||
791 | |||
788 | down_write(&keyring->sem); | 792 | down_write(&keyring->sem); |
789 | 793 | ||
790 | /* if we're going to allocate a new key, we're going to have | 794 | /* if we're going to allocate a new key, we're going to have |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index d65a180f888d..bffa924c1f88 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -437,6 +437,7 @@ EXPORT_SYMBOL(keyring_search); | |||
437 | /* | 437 | /* |
438 | * search the given keyring only (no recursion) | 438 | * search the given keyring only (no recursion) |
439 | * - keyring must be locked by caller | 439 | * - keyring must be locked by caller |
440 | * - caller must guarantee that the keyring is a keyring | ||
440 | */ | 441 | */ |
441 | key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 442 | key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
442 | const struct key_type *ktype, | 443 | const struct key_type *ktype, |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index dfab6c886698..abe99d881376 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -281,7 +281,7 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb) | |||
281 | int i; | 281 | int i; |
282 | 282 | ||
283 | for (i = sp->len-1; i >= 0; i--) { | 283 | for (i = sp->len-1; i >= 0; i--) { |
284 | struct xfrm_state *x = sp->x[i].xvec; | 284 | struct xfrm_state *x = sp->xvec[i]; |
285 | if (selinux_authorizable_xfrm(x)) { | 285 | if (selinux_authorizable_xfrm(x)) { |
286 | struct xfrm_sec_ctx *ctx = x->security; | 286 | struct xfrm_sec_ctx *ctx = x->security; |
287 | return ctx->ctx_sid; | 287 | return ctx->ctx_sid; |
@@ -314,7 +314,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) | |||
314 | * Only need to verify the existence of an authorizable sp. | 314 | * Only need to verify the existence of an authorizable sp. |
315 | */ | 315 | */ |
316 | for (i = 0; i < sp->len; i++) { | 316 | for (i = 0; i < sp->len; i++) { |
317 | struct xfrm_state *x = sp->x[i].xvec; | 317 | struct xfrm_state *x = sp->xvec[i]; |
318 | 318 | ||
319 | if (x && selinux_authorizable_xfrm(x)) | 319 | if (x && selinux_authorizable_xfrm(x)) |
320 | goto accept; | 320 | goto accept; |