summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Jones <davej@tetrachloride.(none)>2003-01-08 08:39:06 -0100
committerDave Jones <davej@tetrachloride.(none)>2003-01-08 08:39:06 -0100
commitd72c8aafbe183a8745419b3e2221d9513c1df3f6 (patch)
tree5ca60e8778f6339db0a6025cc713e4d7028aeadb
parent2c3929fa0a5827140e032d661e43c75c62e5bdd4 (diff)
parent9a0a4cb166a73286c4991c212425bc8f3cdc11db (diff)
Merge tetrachloride.(none):/mnt/stuff/kernel/2.5/bk-linus
into tetrachloride.(none):/mnt/stuff/kernel/2.5/agpgart
-rw-r--r--arch/i386/Kconfig5
-rw-r--r--arch/i386/kernel/smp.c1
-rw-r--r--arch/i386/kernel/smpboot.c166
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c1
-rw-r--r--arch/i386/pci/numa.c2
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c76
-rw-r--r--drivers/hotplug/ibmphp_core.c10
-rw-r--r--drivers/hotplug/pci_hotplug_core.c41
-rw-r--r--drivers/net/sungem.c1
-rw-r--r--drivers/pci/hotplug.c2
-rw-r--r--drivers/scsi/aic7xxx/Makefile49
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c16
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c25
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h13
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c25
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h3
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.seq4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c74
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c29
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h15
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c6
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c34
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped4
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_gram.y15
-rw-r--r--drivers/serial/sunsab.c99
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/jfs_logmgr.c51
-rw-r--r--fs/jfs/jfs_logmgr.h3
-rw-r--r--fs/jfs/jfs_txnmgr.c8
-rw-r--r--fs/jfs/jfs_umount.c4
-rw-r--r--fs/jfs/resize.c2
-rw-r--r--fs/jfs/super.c12
-rw-r--r--include/asm-i386/mach-default/mach_apic.h13
-rw-r--r--include/asm-i386/mach-default/mach_wakecpu.h41
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h20
-rw-r--r--include/asm-i386/mach-numaq/mach_wakecpu.h43
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h14
-rw-r--r--include/asm-i386/numaq.h2
-rw-r--r--include/asm-i386/smp.h29
-rw-r--r--include/asm-i386/smpboot.h48
-rw-r--r--include/asm-i386/topology.h56
-rw-r--r--include/linux/if_arp.h1
-rw-r--r--include/linux/module.h2
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--include/net/icmp.h15
-rw-r--r--include/net/ip.h6
-rw-r--r--include/net/ipv6.h11
-rw-r--r--include/net/route.h6
-rw-r--r--include/net/sctp/sctp.h2
-rw-r--r--include/net/snmp.h39
-rw-r--r--include/net/tcp.h6
-rw-r--r--include/net/udp.h3
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/rtnetlink.c66
-rw-r--r--net/core/skbuff.c6
-rw-r--r--net/ipv4/af_inet.c61
-rw-r--r--net/ipv4/icmp.c96
-rw-r--r--net/ipv4/ip_input.c2
-rw-r--r--net/ipv4/proc.c37
-rw-r--r--net/ipv4/route.c71
-rw-r--r--net/ipv4/tcp.c13
-rw-r--r--net/ipv4/tcp_input.c4
-rw-r--r--net/ipv4/tcp_minisocks.c4
-rw-r--r--net/ipv4/tcp_timer.c3
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/af_inet6.c83
-rw-r--r--net/ipv6/icmp.c8
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/proc.c38
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/sctp/protocol.c44
-rw-r--r--net/socket.c14
77 files changed, 1031 insertions, 705 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index e26819f478ba..568d9e228146 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -456,11 +456,6 @@ config NR_CPUS
This is purely to save memory - each supported CPU adds
approximately eight kilobytes to the kernel image.
-config CLUSTERED_APIC
- bool
- depends on X86_NUMAQ || X86_SUMMIT
- default y
-
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation Support"
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 3f42c6e3f011..4a77837cca8b 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -23,7 +23,6 @@
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
-#include <asm/smpboot.h>
#include <mach_ipi.h>
/*
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 1330f0d33bf7..c393236ad8e5 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -47,12 +47,12 @@
#include <linux/mc146818rtc.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
-#include <asm/smpboot.h>
#include <asm/desc.h>
#include <asm/arch_hooks.h>
#include "smpboot_hooks.h"
#include <mach_apic.h>
+#include <mach_wakecpu.h>
/* Set if we find a B stepping CPU */
static int __initdata smp_b_stepping;
@@ -348,8 +348,7 @@ void __init smp_callin(void)
* our local APIC. We have to wait for the IPI or we'll
* lock up on an APIC access.
*/
- if (!clustered_apic_mode)
- while (!atomic_read(&init_deasserted));
+ wait_for_init_deassert(&init_deasserted);
/*
* (This works even if the APIC is not enabled.)
@@ -398,13 +397,9 @@ void __init smp_callin(void)
*/
Dprintk("CALLIN, before setup_local_APIC().\n");
- /*
- * Because we use NMIs rather than the INIT-STARTUP sequence to
- * bootstrap the CPUs, the APIC may be in a weird state. Kick it.
- */
- if (clustered_apic_mode)
- clear_local_APIC();
+ smp_callin_clear_local_apic();
setup_local_APIC();
+ map_cpu_to_logical_apicid();
local_irq_enable();
@@ -503,63 +498,58 @@ static struct task_struct * __init fork_by_hand(void)
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
}
-/* which physical APIC ID maps to which logical CPU number */
-volatile int physical_apicid_2_cpu[MAX_APICID];
-/* which logical CPU number maps to which physical APIC ID */
-volatile int cpu_2_physical_apicid[NR_CPUS];
+#ifdef CONFIG_NUMA
-/* which logical APIC ID maps to which logical CPU number */
-volatile int logical_apicid_2_cpu[MAX_APICID];
-/* which logical CPU number maps to which logical APIC ID */
-volatile int cpu_2_logical_apicid[NR_CPUS];
+/* which logical CPUs are on which nodes */
+volatile unsigned long node_2_cpu_mask[MAX_NR_NODES] =
+ { [0 ... MAX_NR_NODES-1] = 0 };
+/* which node each logical CPU is on */
+volatile int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
-static inline void init_cpu_to_apicid(void)
-/* Initialize all maps between cpu number and apicids */
+/* set up a mapping between cpu and node. */
+static inline void map_cpu_to_node(int cpu, int node)
{
- int apicid, cpu;
+ printk("Mapping cpu %d to node %d\n", cpu, node);
+ node_2_cpu_mask[node] |= (1 << cpu);
+ cpu_2_node[cpu] = node;
+}
- for (apicid = 0; apicid < MAX_APICID; apicid++) {
- physical_apicid_2_cpu[apicid] = -1;
- logical_apicid_2_cpu[apicid] = -1;
- }
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- cpu_2_physical_apicid[cpu] = -1;
- cpu_2_logical_apicid[cpu] = -1;
- }
+/* undo a mapping between cpu and node. */
+static inline void unmap_cpu_to_node(int cpu)
+{
+ int node;
+
+ printk("Unmapping cpu %d from all nodes\n", cpu);
+ for (node = 0; node < MAX_NR_NODES; node ++)
+ node_2_cpu_mask[node] &= ~(1 << cpu);
+ cpu_2_node[cpu] = -1;
}
+#else /* !CONFIG_NUMA */
-static inline void map_cpu_to_boot_apicid(int cpu, int apicid)
-/*
- * set up a mapping between cpu and apicid. Uses logical apicids for multiquad,
- * else physical apic ids
- */
+#define map_cpu_to_node(cpu, node) ({})
+#define unmap_cpu_to_node(cpu) ({})
+
+#endif /* CONFIG_NUMA */
+
+volatile u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+
+void map_cpu_to_logical_apicid(void)
{
- if (clustered_apic_mode) {
- logical_apicid_2_cpu[apicid] = cpu;
- cpu_2_logical_apicid[cpu] = apicid;
- } else {
- physical_apicid_2_cpu[apicid] = cpu;
- cpu_2_physical_apicid[cpu] = apicid;
- }
+ int cpu = smp_processor_id();
+ int apicid = logical_smp_processor_id();
+
+ cpu_2_logical_apicid[cpu] = apicid;
+ map_cpu_to_node(cpu, apicid_to_node(apicid));
}
-static inline void unmap_cpu_to_boot_apicid(int cpu, int apicid)
-/*
- * undo a mapping between cpu and apicid. Uses logical apicids for multiquad,
- * else physical apic ids
- */
+void unmap_cpu_to_logical_apicid(int cpu)
{
- if (clustered_apic_mode) {
- logical_apicid_2_cpu[apicid] = -1;
- cpu_2_logical_apicid[cpu] = -1;
- } else {
- physical_apicid_2_cpu[apicid] = -1;
- cpu_2_physical_apicid[cpu] = -1;
- }
+ cpu_2_logical_apicid[cpu] = BAD_APICID;
+ unmap_cpu_to_node(cpu);
}
#if APIC_DEBUG
-static inline void inquire_remote_apic(int apicid)
+static inline void __inquire_remote_apic(int apicid)
{
int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
char *names[] = { "ID", "VERSION", "SPIV" };
@@ -654,6 +644,15 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
unsigned long send_status = 0, accept_status = 0;
int maxlvt, timeout, num_starts, j;
+ /*
+ * Be paranoid about clearing APIC errors.
+ */
+ if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+ apic_read_around(APIC_SPIV);
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
+ }
+
Dprintk("Asserting INIT.\n");
/*
@@ -775,17 +774,18 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
extern unsigned long cpu_initialized;
-static void __init do_boot_cpu (int apicid)
+static int __init do_boot_cpu(int apicid)
/*
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
+ * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
*/
{
struct task_struct *idle;
- unsigned long boot_error = 0;
+ unsigned long boot_error;
int timeout, cpu;
unsigned long start_eip;
- unsigned short nmi_high, nmi_low;
+ unsigned short nmi_high = 0, nmi_low = 0;
cpu = ++cpucount;
/*
@@ -802,8 +802,6 @@ static void __init do_boot_cpu (int apicid)
*/
init_idle(idle, cpu);
- map_cpu_to_boot_apicid(cpu, apicid);
-
idle->thread.eip = (unsigned long) start_secondary;
unhash_process(idle);
@@ -825,11 +823,7 @@ static void __init do_boot_cpu (int apicid)
Dprintk("Setting warm reset code and vector.\n");
- if (clustered_apic_mode) {
- /* stash the current NMI vector, so we can put things back */
- nmi_high = *((volatile unsigned short *) TRAMPOLINE_HIGH);
- nmi_low = *((volatile unsigned short *) TRAMPOLINE_LOW);
- }
+ store_NMI_vector(&nmi_high, &nmi_low);
CMOS_WRITE(0xa, 0xf);
local_flush_tlb();
@@ -840,23 +834,9 @@ static void __init do_boot_cpu (int apicid)
Dprintk("3.\n");
/*
- * Be paranoid about clearing APIC errors.
- */
- if (!clustered_apic_mode && APIC_INTEGRATED(apic_version[apicid])) {
- apic_read_around(APIC_SPIV);
- apic_write(APIC_ESR, 0);
- apic_read(APIC_ESR);
- }
-
- /*
- * Status is now clean
- */
- boot_error = 0;
-
- /*
* Starting actual IPI sequence...
*/
- wakeup_secondary_cpu(apicid, start_eip);
+ boot_error = wakeup_secondary_cpu(apicid, start_eip);
if (!boot_error) {
/*
@@ -890,15 +870,12 @@ static void __init do_boot_cpu (int apicid)
else
/* trampoline code not run */
printk("Not responding.\n");
-#if APIC_DEBUG
- if (!clustered_apic_mode)
- inquire_remote_apic(apicid);
-#endif
+ inquire_remote_apic(apicid);
}
}
if (boot_error) {
/* Try to put things back the way they were before ... */
- unmap_cpu_to_boot_apicid(cpu, apicid);
+ unmap_cpu_to_logical_apicid(cpu);
clear_bit(cpu, &cpu_callout_map); /* was set here (do_boot_cpu()) */
clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
cpucount--;
@@ -907,11 +884,7 @@ static void __init do_boot_cpu (int apicid)
/* mark "stuck" area as not stuck */
*((volatile unsigned long *)trampoline_base) = 0;
- if(clustered_apic_mode) {
- printk("Restoring NMI vector\n");
- *((volatile unsigned short *) TRAMPOLINE_HIGH) = nmi_high;
- *((volatile unsigned short *) TRAMPOLINE_LOW) = nmi_low;
- }
+ return boot_error;
}
cycles_t cacheflush_time;
@@ -987,8 +960,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
prof_multiplier[cpu] = 1;
}
- init_cpu_to_apicid();
-
/*
* Setup boot CPU information
*/
@@ -997,7 +968,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
print_cpu_info(&cpu_data[0]);
boot_cpu_logical_apicid = logical_smp_processor_id();
- map_cpu_to_boot_apicid(0, boot_cpu_apicid);
current_thread_info()->cpu = 0;
smp_tune_scheduling();
@@ -1021,10 +991,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
* CPU too, but we do it for the sake of robustness anyway.
* Makes no sense to do this check in clustered apic mode, so skip it
*/
- if (!clustered_apic_mode &&
- !test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map)) {
+ if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
- boot_cpu_physical_apicid);
+ boot_cpu_physical_apicid);
phys_cpu_present_map |= (1 << hard_smp_processor_id());
}
@@ -1055,6 +1024,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
connect_bsp_APIC();
setup_local_APIC();
+ map_cpu_to_logical_apicid();
if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid)
BUG();
@@ -1083,13 +1053,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (max_cpus <= cpucount+1)
continue;
- do_boot_cpu(apicid);
-
- /*
- * Make sure we unmap all failed CPUs
- */
- if ((boot_apicid_to_cpu(apicid) == -1) &&
- (phys_cpu_present_map & (1 << bit)))
+ if (do_boot_cpu(apicid))
printk("CPU #%d not responding - cannot use it.\n",
apicid);
}
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index fe3569203ce6..cdbc7915b438 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -28,7 +28,6 @@
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
-#include <asm/smpboot.h>
#include <asm/desc.h>
#include <asm/arch_hooks.h>
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
index 58123c0e0cdb..433e1bbc577c 100644
--- a/arch/i386/pci/numa.c
+++ b/arch/i386/pci/numa.c
@@ -127,7 +127,7 @@ static int __init pci_numa_init(void)
return 0;
pci_root_bus = pcibios_scan_root(0);
- if (clustered_apic_mode && (numnodes > 1)) {
+ if (numnodes > 1) {
for (quad = 1; quad < numnodes; ++quad) {
printk("Scanning PCI bus %d for quad %d\n",
QUADLOCAL2BUS(quad,0), quad);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index d18415e983c9..140141c99c74 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -53,6 +53,7 @@
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/vfs.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -2527,6 +2528,78 @@ out:
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
char *optval, int optlen);
+static int do_netfilter_replace(int fd, int level, int optname,
+ char *optval, int optlen)
+{
+ struct ipt_replace32 {
+ char name[IPT_TABLE_MAXNAMELEN];
+ __u32 valid_hooks;
+ __u32 num_entries;
+ __u32 size;
+ __u32 hook_entry[NF_IP_NUMHOOKS];
+ __u32 underflow[NF_IP_NUMHOOKS];
+ __u32 num_counters;
+ __u32 counters;
+ struct ipt_entry entries[0];
+ } *repl32 = (struct ipt_replace32 *)optval;
+ struct ipt_replace *krepl;
+ struct ipt_counters *counters32;
+ __u32 origsize;
+ unsigned int kreplsize, kcountersize;
+ mm_segment_t old_fs;
+ int ret;
+
+ if (optlen < sizeof(repl32))
+ return -EINVAL;
+
+ if (copy_from_user(&origsize,
+ &repl32->size,
+ sizeof(origsize)))
+ return -EFAULT;
+
+ kreplsize = sizeof(*krepl) + origsize;
+ kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (optlen != kreplsize)
+ return -ENOPROTOOPT;
+
+ krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
+ if (krepl == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(krepl, optval, kreplsize)) {
+ kfree(krepl);
+ return -EFAULT;
+ }
+
+ counters32 = (struct ipt_counters *)AA(
+ ((struct ipt_replace32 *)krepl)->counters);
+
+ kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+ krepl->counters = (struct ipt_counters *)kmalloc(
+ kcountersize, GFP_KERNEL);
+ if (krepl->counters == NULL) {
+ kfree(krepl);
+ return -ENOMEM;
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_setsockopt(fd, level, optname,
+ (char *)krepl, kreplsize);
+ set_fs(old_fs);
+
+ if (ret == 0 &&
+ copy_to_user(counters32, krepl->counters, kcountersize))
+ ret = -EFAULT;
+
+ kfree(krepl->counters);
+ kfree(krepl);
+
+ return ret;
+}
+
static int do_set_attach_filter(int fd, int level, int optname,
char *optval, int optlen)
{
@@ -2620,6 +2693,9 @@ static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
char *optval, int optlen)
{
+ if (optname == IPT_SO_SET_REPLACE)
+ return do_netfilter_replace(fd, level, optname,
+ optval, optlen);
if (optname == SO_ATTACH_FILTER)
return do_set_attach_filter(fd, level, optname,
optval, optlen);
diff --git a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
index e99063f226db..2fec0d5c4e80 100644
--- a/drivers/hotplug/ibmphp_core.c
+++ b/drivers/hotplug/ibmphp_core.c
@@ -769,11 +769,11 @@ static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function)
* Parameters: bus number
* Returns : pci_bus * or NULL if not found
*/
-static struct pci_bus *find_bus (u8 busno)
+static struct pci_bus *ibmphp_find_bus (u8 busno)
{
const struct list_head *tmp;
struct pci_bus *bus;
- debug ("inside find_bus, busno = %x \n", busno);
+ debug ("inside %s, busno = %x \n", __FUNCTION__, busno);
list_for_each (tmp, &pci_root_buses) {
bus = (struct pci_bus *) pci_bus_b (tmp);
@@ -1002,7 +1002,7 @@ static u8 bus_structure_fixup (u8 busno)
struct pci_dev *dev;
u16 l;
- if (find_bus (busno) || !(ibmphp_find_same_bus_num (busno)))
+ if (ibmphp_find_bus (busno) || !(ibmphp_find_same_bus_num (busno)))
return 1;
bus = kmalloc (sizeof (*bus), GFP_KERNEL);
@@ -1056,7 +1056,7 @@ static int ibm_configure_device (struct pci_func *func)
func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7));
if (func->dev == NULL) {
- dev0.bus = find_bus (func->busno);
+ dev0.bus = ibmphp_find_bus (func->busno);
dev0.devfn = ((func->device << 3) + (func->function & 0x7));
dev0.sysdata = dev0.bus->sysdata;
@@ -1636,7 +1636,7 @@ static int __init ibmphp_init (void)
return -ENOMEM;
}
- bus = find_bus (0);
+ bus = ibmphp_find_bus (0);
if (!bus) {
err ("Can't find the root pci bus, can not continue\n");
return -ENODEV;
diff --git a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
index 5e4c1748b7d1..b6426a2277c8 100644
--- a/drivers/hotplug/pci_hotplug_core.c
+++ b/drivers/hotplug/pci_hotplug_core.c
@@ -561,7 +561,7 @@ static void fs_remove_file (struct dentry *dentry)
up(&parent->d_inode->i_sem);
}
-/* yuck, WFT is this? */
+/* Weee, fun with macros... */
#define GET_STATUS(name,type) \
static int get_##name (struct hotplug_slot *slot, type *value) \
{ \
@@ -661,29 +661,26 @@ static ssize_t power_write_file (struct file *file, const char *ubuff, size_t co
power = (u8)(lpower & 0xff);
dbg ("power = %d\n", power);
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
+ }
switch (power) {
case 0:
- if (!slot->ops->disable_slot)
- break;
- if (try_module_get(slot->ops->owner)) {
+ if (slot->ops->disable_slot)
retval = slot->ops->disable_slot(slot);
- module_put(slot->ops->owner);
- }
break;
case 1:
- if (!slot->ops->enable_slot)
- break;
- if (try_module_get(slot->ops->owner)) {
+ if (slot->ops->enable_slot)
retval = slot->ops->enable_slot(slot);
- module_put(slot->ops->owner);
- }
break;
default:
err ("Illegal value specified for power\n");
retval = -EINVAL;
}
+ module_put(slot->ops->owner);
exit:
kfree (buff);
@@ -770,12 +767,13 @@ static ssize_t attention_write_file (struct file *file, const char *ubuff, size_
attention = (u8)(lattention & 0xff);
dbg (" - attention = %d\n", attention);
- if (slot->ops->set_attention_status) {
- if (try_module_get(slot->ops->owner)) {
- retval = slot->ops->set_attention_status(slot, attention);
- module_put(slot->ops->owner);
- }
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
}
+ if (slot->ops->set_attention_status)
+ retval = slot->ops->set_attention_status(slot, attention);
+ module_put(slot->ops->owner);
exit:
kfree (buff);
@@ -1007,12 +1005,13 @@ static ssize_t test_write_file (struct file *file, const char *ubuff, size_t cou
test = (u32)(ltest & 0xffffffff);
dbg ("test = %d\n", test);
- if (slot->ops->hardware_test) {
- if (try_module_get(slot->ops->owner)) {
- retval = slot->ops->hardware_test(slot, test);
- module_put(slot->ops->owner);
- }
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
}
+ if (slot->ops->hardware_test)
+ retval = slot->ops->hardware_test(slot, test);
+ module_put(slot->ops->owner);
exit:
kfree (buff);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 5e125088f47c..8f6f9bde40a8 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2850,6 +2850,7 @@ static int __devinit gem_get_device_address(struct gem *gp)
printk(KERN_ERR "%s: can't get mac-address\n", dev->name);
return -1;
}
+#warning MAX_ADDR_LEN is now 32 bytes instead of 8, please fix this as appropriate
memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);
#else
get_gem_mac_nonobp(gp->pdev, gp->dev->dev_addr);
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index 1aca6c7d187f..a483c4ff4e93 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -105,7 +105,7 @@ pci_free_resources(struct pci_dev *dev)
void
pci_remove_device(struct pci_dev *dev)
{
- put_device(&dev->dev);
+ device_unregister(&dev->dev);
list_del(&dev->bus_list);
list_del(&dev->global_list);
pci_free_resources(dev);
diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile
index ebd922a22c97..7b404a1f051f 100644
--- a/drivers/scsi/aic7xxx/Makefile
+++ b/drivers/scsi/aic7xxx/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the Linux aic7xxx SCSI driver.
#
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#3 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#5 $
#
# Let kbuild descend into aicasm when cleaning
@@ -44,40 +44,39 @@ clean-files += aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c
$(obj)/aic7xxx_core.o: $(obj)/aic7xxx_seq.h
$(obj)/aic79xx_core.o: $(obj)/aic79xx_seq.h
+$(obj)/aic79xx_reg_print.c: $(src)/aic79xx_reg_print.c_shipped
+$(obj)/aic7xxx_reg_print.c: $(src)/aic7xxx_reg_print.c_shipped
$(addprefix $(obj)/,$(aic7xxx-y)): $(obj)/aic7xxx_reg.h
$(addprefix $(obj)/,$(aic79xx-y)): $(obj)/aic79xx_reg.h
+aic7xxx-gen-$(CONFIG_AIC7XXX_BUILD_FIRMWARE) := $(obj)/aic7xxx_seq.h \
+ $(obj)/aic7xxx_reg.h
+aic7xxx-gen-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) += $(obj)/aic7xxx_reg_print.c
+
+aicasm-7xxx-opts-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) := \
+ -p $(obj)/aic7xxx_reg_print.c -i aic7xxx_osm.h
+
ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
-aic7xxx_gen = $(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h
-ifeq ($(CONFIG_AIC7XXX_REG_PRETTY_PRINT),y)
-aic7xxx_gen += $(obj)/aic7xxx_reg_print.c
-aic7xxx_asm_cmd = $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
- -p $(obj)/aic7xxx_reg_print.c -i aic7xxx_osm.h \
- -o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq
-else
-aic7xxx_asm_cmd = $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
- -o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq
+$(aic7xxx-gen-y): $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm
+ $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
+ $(aicasm-7xxx-opts-y) -o $(obj)/aic7xxx_seq.h \
+ $(src)/aic7xxx.seq
endif
-$(aic7xxx_gen): $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm
- $(aic7xxx_asm_cmd)
-endif
+aic79xx-gen-$(CONFIG_AIC79XX_BUILD_FIRMWARE) := $(obj)/aic79xx_seq.h \
+ $(obj)/aic79xx_reg.h
+aic79xx-gen-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) += $(obj)/aic79xx_reg_print.c
+
+aicasm-79xx-opts-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) := \
+ -p $(obj)/aic79xx_reg_print.c -i aic79xx_osm.h
ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y)
-aic79xx_gen = $(obj)/aic79xx_seq.h $(obj)/aic79xx_reg.h
-ifeq ($(CONFIG_AIC79XX_REG_PRETTY_PRINT),y)
-aic79xx_gen += $(obj)/aic79xx_reg_print.c
-aic79xx_asm_cmd = $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
- -p $(obj)/aic79xx_reg_print.c -i aic79xx_osm.h \
- -o $(obj)/aic79xx_seq.h $(src)/aic79xx.seq
-else
-aic79xx_asm_cmd = $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
- -o $(obj)/aic79xx_seq.h $(src)/aic79xx.seq
+$(aic79xx-gen-y): $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm
+ $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
+ $(aicasm-79xx-opts-y) -o $(obj)/aic79xx_seq.h \
+ $(src)/aic79xx.seq
endif
-$(aic79xx_gen): $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm
- $(aic79xx_asm_cmd)
-endif
$(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl]
$(MAKE) -C $(src)/aicasm
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index a288ed9f9b3e..1cd5afa6ebcd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#148 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#150 $
*
* $FreeBSD$
*/
@@ -2321,13 +2321,13 @@ ahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
/* Skip all PACED only entries if IU is not available */
if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
- && maxsync < AHD_SYNCRATE_DT)
- maxsync = AHD_SYNCRATE_DT;
+ && *period < AHD_SYNCRATE_DT)
+ *period = AHD_SYNCRATE_DT;
/* Skip all DT only entries if DT is not available */
if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
- && maxsync < AHD_SYNCRATE_ULTRA2)
- maxsync = AHD_SYNCRATE_ULTRA2;
+ && *period < AHD_SYNCRATE_ULTRA2)
+ *period = AHD_SYNCRATE_ULTRA2;
}
/*
@@ -5680,7 +5680,8 @@ ahd_init(struct ahd_softc *ahd)
/*lowaddr*/BUS_SPACE_MAXADDR,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/MAXBSIZE, /*nsegments*/AHD_NSEG,
+ /*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE,
+ /*nsegments*/AHD_NSEG,
/*maxsegsz*/AHD_MAXTRANSFER_SIZE,
/*flags*/BUS_DMA_ALLOCNOW,
&ahd->buffer_dmat) != 0) {
@@ -7856,7 +7857,8 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MISC) != 0) {
ahd_print_path(ahd, scb);
- printf("Handled Residual of %d bytes\n", resid);
+ printf("Handled %sResidual of %d bytes\n",
+ (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
}
#endif
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 02a7612a7efd..05edbed59319 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1,7 +1,7 @@
/*
* Adaptec AIC79xx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#103 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#104 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
@@ -2058,7 +2058,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
* negotiation will occur for the first command, and DV
* will comence should that first command be successful.
*/
- for (target = 0; target < AHD_NUM_TARGETS; target++)
+ for (target = 0; target < host->max_id; target++)
ahd_linux_alloc_target(ahd, 0, target);
ahd_intr_enable(ahd, TRUE);
ahd_linux_start_dv(ahd);
@@ -2883,6 +2883,23 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
break;
}
+#ifdef AHD_DEBUG
+ if (ahd_debug & AHD_SHOW_DV) {
+ int i;
+
+ ahd_print_devinfo(ahd, devinfo);
+ printf("Inquiry buffer mismatch:");
+ for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
+ if ((i & 0xF) == 0)
+ printf("\n ");
+ printf("0x%x:0x0%x ",
+ ((uint8_t *)targ->inq_data)[i],
+ targ->dv_buffer[i]);
+ }
+ printf("\n");
+ }
+#endif
+
if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
break;
@@ -3525,6 +3542,8 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
if (targ->dv_next_wide_period == 0)
targ->dv_next_wide_period = period;
+ if (targ->dv_max_width == 0)
+ targ->dv_max_width = width;
if (targ->dv_max_ppr_options == 0)
targ->dv_max_ppr_options = ppr_options;
if (targ->dv_last_ppr_options == 0)
@@ -3619,7 +3638,7 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
period++;
}
} else if ((ahd->features & AHD_WIDE) != 0
- && tinfo->user.width != 0
+ && targ->dv_max_width != 0
&& wide_speed >= fallback_speed
&& (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
|| period >= AHD_ASYNC_XFER_PERIOD)) {
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index a3377dcc6f50..ecf6fdf9ef01 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#99 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#102 $
*
*/
#ifndef _AIC79XX_LINUX_H_
@@ -288,7 +288,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
#include <linux/smp.h>
#endif
-#define AIC79XX_DRIVER_VERSION "1.3.0.ALPHA6"
+#define AIC79XX_DRIVER_VERSION "1.3.0.BETA2"
/**************************** Front End Queues ********************************/
/*
@@ -458,10 +458,11 @@ struct ahd_linux_target {
/*
* The next "fallback" period to use for narrow/wide transfers.
*/
- u_int dv_next_narrow_period;
- u_int dv_next_wide_period;
- u_int dv_max_ppr_options;
- u_int dv_last_ppr_options;
+ uint8_t dv_next_narrow_period;
+ uint8_t dv_next_wide_period;
+ uint8_t dv_max_width;
+ uint8_t dv_max_ppr_options;
+ uint8_t dv_last_ppr_options;
u_int dv_echo_size;
ahd_dv_state dv_state;
u_int dv_state_retry;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 115fcbf89e65..e8e0261dbf8f 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#19 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#20 $
*/
#include "aic79xx_osm.h"
@@ -170,6 +170,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahd->platform_data->hw_dma_mask =
(bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0);
}
+ } else {
+ ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF);
+ ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
}
#endif
ahd->dev_softc = pci;
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 7dd68a3746fd..79b1a172d6be 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#60 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#61 $
*
* $FreeBSD$
*/
@@ -379,15 +379,20 @@ int
ahd_pci_test_register_access(struct ahd_softc *ahd)
{
ahd_mode_state saved_modes;
+ uint32_t cmd;
int error;
- uint8_t seqctl;
+ uint8_t hcntrl;
saved_modes = ahd_save_modes(ahd);
error = EIO;
- /* Enable PCI error interrupt status */
- seqctl = ahd_inb(ahd, SEQCTL0);
- ahd_outb(ahd, SEQCTL0, seqctl & ~FAILDIS);
+ /*
+ * Enable PCI error interrupt status, but suppress NMIs
+ * generated by SERR raised due to target aborts.
+ */
+ cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
+ ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+ cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
/*
* First a simple test to see if any
@@ -397,7 +402,8 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
* be zero so it is a good register to
* use for this test.
*/
- if (ahd_inb(ahd, HCNTRL) == 0xFF)
+ hcntrl = ahd_inb(ahd, HCNTRL);
+ if (hcntrl == 0xFF)
goto fail;
/*
@@ -407,6 +413,10 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
* either, so look for data corruption and/or flaged
* PCI errors.
*/
+ ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
+ while (ahd_is_paused(ahd) == 0)
+ ;
+ ahd_outb(ahd, SEQCTL0, PERRORDIS);
ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
goto fail;
@@ -440,7 +450,8 @@ fail:
}
ahd_restore_modes(ahd, saved_modes);
- ahd_outb(ahd, SEQCTL0, seqctl);
+ ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
+ ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
return (error);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 6fa90708ad8f..2940896d5e3a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#66 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#67 $
*
* $FreeBSD$
*/
@@ -1053,7 +1053,6 @@ struct ahc_softc {
u_int pci_cachesize;
u_int stack_size;
- uint16_t *saved_stack;
/* Per-Unit descriptive information */
const char *description;
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 1744f4f9bb54..7dc8f6d9ab69 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#36 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#37 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -673,6 +673,8 @@ register STACK {
access_mode RO
}
+const STACK_SIZE 4
+
/*
* Board Control (p. 3-43)
*/
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
index b7846350c3f2..c8cd622d52b6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#52 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#53 $"
PATCH_ARG_LIST = "struct ahc_softc *ahc"
PREFIX = "ahc_"
@@ -70,7 +70,7 @@ bus_free_sel:
* Turn off the selection hardware. We need to reset the
* selection request in order to perform a new selection.
*/
- and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;
+ and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;
and SIMODE1, ~ENBUSFREE;
poll_for_work:
call clear_target_state;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index a69c1194203e..75cb92373161 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#105 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#108 $
*
* $FreeBSD$
*/
@@ -230,7 +230,6 @@ static int ahc_check_patch(struct ahc_softc *ahc,
u_int start_instr, u_int *skip_addr);
static void ahc_download_instr(struct ahc_softc *ahc,
u_int instrptr, uint8_t *dconsts);
-static int ahc_probe_stack_size(struct ahc_softc *ahc);
#ifdef AHC_TARGET_MODE
static void ahc_queue_lstate_event(struct ahc_softc *ahc,
struct ahc_tmode_lstate *lstate,
@@ -1166,6 +1165,13 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_name(ahc), scbptr, scb_index);
ahc_dump_card_state(ahc);
} else {
+#ifdef AHC_DEBUG
+ if ((ahc_debug & AHC_SHOW_SELTO) != 0) {
+ ahc_print_path(ahc, scb);
+ printf("Saw Selection Timeout for SCB 0x%x\n",
+ scb_index);
+ }
+#endif
/*
* Force a renegotiation with this target just in
* case the cable was pulled and will later be
@@ -1178,13 +1184,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_force_renegotiation(ahc);
ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahc_freeze_devq(ahc, scb);
-#ifdef AHC_DEBUG
- if ((ahc_debug & AHC_SHOW_SELTO) != 0) {
- ahc_print_path(ahc, scb);
- printf("Saw Selection Timeout for SCB 0x%x\n",
- scb_index);
- }
-#endif
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_restart(ahc);
@@ -4005,8 +4004,6 @@ ahc_free(struct ahc_softc *ahc)
free(ahc->name, M_DEVBUF);
if (ahc->seep_config != NULL)
free(ahc->seep_config, M_DEVBUF);
- if (ahc->saved_stack != NULL)
- free(ahc->saved_stack, M_DEVBUF);
#ifndef __FreeBSD__
free(ahc, M_DEVBUF);
#endif
@@ -4542,12 +4539,6 @@ ahc_init(struct ahc_softc *ahc)
size_t driver_data_size;
uint32_t physaddr;
- ahc->stack_size = ahc_probe_stack_size(ahc);
- ahc->saved_stack = malloc(ahc->stack_size * sizeof(uint16_t),
- M_DEVBUF, M_NOWAIT);
- if (ahc->saved_stack == NULL)
- return (ENOMEM);
-
#ifdef AHC_DEBUG_SEQUENCER
ahc->flags |= AHC_SEQUENCER_DEBUG;
#endif
@@ -4602,7 +4593,8 @@ ahc_init(struct ahc_softc *ahc)
/*lowaddr*/BUS_SPACE_MAXADDR,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
- /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG,
+ /*maxsize*/(AHC_NSEG - 1) * PAGE_SIZE,
+ /*nsegments*/AHC_NSEG,
/*maxsegsz*/AHC_MAXTRANSFER_SIZE,
/*flags*/BUS_DMA_ALLOCNOW,
&ahc->buffer_dmat) != 0) {
@@ -6275,7 +6267,8 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
#ifdef AHC_DEBUG
if ((ahc_debug & AHC_SHOW_MISC) != 0) {
ahc_print_path(ahc, scb);
- printf("Handled Residual of %d bytes\n", resid);
+ printf("Handled %sResidual of %d bytes\n",
+ (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
}
#endif
}
@@ -6655,41 +6648,6 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
}
}
-static int
-ahc_probe_stack_size(struct ahc_softc *ahc)
-{
- int last_probe;
-
- last_probe = 0;
- while (1) {
- int i;
-
- /*
- * We avoid using 0 as a pattern to avoid
- * confusion if the stack implementation
- * "back-fills" with zeros when "poping'
- * entries.
- */
- for (i = 1; i <= last_probe+1; i++) {
- ahc_outb(ahc, STACK, i & 0xFF);
- ahc_outb(ahc, STACK, (i >> 8) & 0xFF);
- }
-
- /* Verify */
- for (i = last_probe+1; i > 0; i--) {
- u_int stack_entry;
-
- stack_entry = ahc_inb(ahc, STACK)
- |(ahc_inb(ahc, STACK) << 8);
- if (stack_entry != i)
- goto sized;
- }
- last_probe++;
- }
-sized:
- return (last_probe);
-}
-
int
ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
@@ -6768,6 +6726,7 @@ ahc_dump_card_state(struct ahc_softc *ahc)
cur_col = 0;
if ((ahc->features & AHC_DT) != 0)
ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50);
+ ahc_error_print(ahc_inb(ahc, ERROR), &cur_col, 50);
ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50);
ahc_scsibusl_print(ahc_inb(ahc, SCSIBUSL), &cur_col, 50);
ahc_lastphase_print(ahc_inb(ahc, LASTPHASE), &cur_col, 50);
@@ -6787,11 +6746,8 @@ ahc_dump_card_state(struct ahc_softc *ahc)
if (cur_col != 0)
printf("\n");
printf("STACK:");
- for (i = 0; i < ahc->stack_size; i++) {
- ahc->saved_stack[i] =
- ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8);
- printf(" 0x%x", ahc->saved_stack[i]);
- }
+ for (i = 0; i < STACK_SIZE; i++)
+ printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8));
printf("\nSCB count = %d\n", ahc->scb_data->numscbs);
printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag);
printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB));
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index e8e2a4e91527..07087d348cd6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1,7 +1,7 @@
/*
* Adaptec AIC7xxx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#166 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#169 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
@@ -576,6 +576,7 @@ static void ahc_linux_run_device_queue(struct ahc_softc*,
static void ahc_linux_setup_tag_info(char *p, char *end, char *s);
static void ahc_linux_setup_tag_info_global(char *p);
static void ahc_linux_setup_dv(char *p, char *end, char *s);
+static int aic7xxx_setup(char *s);
static int ahc_linux_next_unit(void);
static void ahc_runq_tasklet(unsigned long data);
static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf);
@@ -1297,6 +1298,7 @@ Scsi_Host_Template aic7xxx_driver_template = {
*/
.max_sectors = 8192,
#endif
+#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
/* Assume RedHat Distribution with its different HIGHIO conventions. */
.can_dma_32 = 1,
@@ -1304,6 +1306,7 @@ Scsi_Host_Template aic7xxx_driver_template = {
#else
.highmem_io = 1,
#endif
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
.name = "aic7xxx",
.slave_alloc = ahc_linux_slave_alloc,
@@ -1764,7 +1767,7 @@ ahc_linux_setup_dv(char *p, char *end, char *s)
* to a parameter with a ':' between the parameter and the value.
* ie. aic7xxx=stpwlev:1,extended
*/
-int
+static int
aic7xxx_setup(char *s)
{
int i, n;
@@ -1888,7 +1891,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
* negotiation will occur for the first command, and DV
* will comence should that first command be successful.
*/
- for (target = 0; target < AHC_NUM_TARGETS; target++) {
+ for (target = 0; target < host->max_id*host->max_channel+1; target++) {
u_int channel;
channel = 0;
@@ -2732,6 +2735,22 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
+#ifdef AHC_DEBUG
+ if (ahc_debug & AHC_SHOW_DV) {
+ int i;
+
+ ahc_print_devinfo(ahc, devinfo);
+ printf("Inquiry buffer mismatch:");
+ for (i = 0; i < AHC_LINUX_DV_INQ_LEN; i++) {
+ if ((i & 0xF) == 0)
+ printf("\n ");
+ printf("0x%x:0x0%x ",
+ ((uint8_t *)targ->inq_data)[i],
+ targ->dv_buffer[i]);
+ }
+ printf("\n");
+ }
+#endif
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
@@ -3365,6 +3384,8 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2);
if (targ->dv_next_wide_period == 0)
targ->dv_next_wide_period = period;
+ if (targ->dv_max_width == 0)
+ targ->dv_max_width = width;
if (targ->dv_max_ppr_options == 0)
targ->dv_max_ppr_options = ppr_options;
if (targ->dv_last_ppr_options == 0)
@@ -3459,7 +3480,7 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
period++;
}
} else if ((ahc->features & AHC_WIDE) != 0
- && tinfo->user.width != 0
+ && targ->dv_max_width != 0
&& wide_speed >= fallback_speed
&& (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD
|| period >= AHC_ASYNC_XFER_PERIOD)) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 3b4b602f969f..c3a8ceb6fbdf 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#114 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#118 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
@@ -72,7 +72,6 @@
#endif
#include <linux/module.h>
#include <asm/byteorder.h>
-#include <asm/io.h>
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
@@ -302,7 +301,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
#include <linux/smp.h>
#endif
-#define AIC7XXX_DRIVER_VERSION "6.2.25"
+#define AIC7XXX_DRIVER_VERSION "6.2.26"
/**************************** Front End Queues ********************************/
/*
@@ -472,10 +471,11 @@ struct ahc_linux_target {
/*
* The next "fallback" period to use for narrow/wide transfers.
*/
- u_int dv_next_narrow_period;
- u_int dv_next_wide_period;
- u_int dv_max_ppr_options;
- u_int dv_last_ppr_options;
+ uint8_t dv_next_narrow_period;
+ uint8_t dv_next_wide_period;
+ uint8_t dv_max_width;
+ uint8_t dv_max_ppr_options;
+ uint8_t dv_last_ppr_options;
u_int dv_echo_size;
ahc_dv_state dv_state;
u_int dv_state_retry;
@@ -864,6 +864,7 @@ ahc_list_unlock(unsigned long *flags)
#define PCIM_CMD_BUSMASTEREN 0x0004
#define PCIM_CMD_MWRICEN 0x0010
#define PCIM_CMD_PERRESPEN 0x0040
+#define PCIM_CMD_SERRESPEN 0x0100
#define PCIR_STATUS 0x06
#define PCIR_REVID 0x08
#define PCIR_PROGIF 0x09
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index fcc865041b62..5c7bb1a2e002 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#42 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#43 $
*/
#include "aic7xxx_osm.h"
@@ -167,8 +167,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc->platform_data->hw_dma_mask =
(bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0);
} else {
- ahc_pci_set_dma_mask(pdev, 0xffffffffULL);
- ahc->platform_data->hw_dma_mask = 0xffffffffULL;
+ ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF);
+ ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
}
#endif
ahc->dev_softc = pci;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index b335373099f9..3522870b999e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -39,7 +39,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#54 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#55 $
*
* $FreeBSD$
*/
@@ -1202,15 +1202,20 @@ done:
int
ahc_pci_test_register_access(struct ahc_softc *ahc)
{
- int error;
- u_int status1;
- uint8_t seqctl;
+ int error;
+ u_int status1;
+ uint32_t cmd;
+ uint8_t hcntrl;
error = EIO;
- /* Enable PCI error interrupt status */
- seqctl = ahc_inb(ahc, SEQCTL);
- ahc_outb(ahc, SEQCTL, seqctl & ~FAILDIS);
+ /*
+ * Enable PCI error interrupt status, but suppress NMIs
+ * generated by SERR raised due to target aborts.
+ */
+ cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+ cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
/*
* First a simple test to see if any
@@ -1220,7 +1225,8 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* be zero so it is a good register to
* use for this test.
*/
- if (ahc_inb(ahc, HCNTRL) == 0xFF)
+ hcntrl = ahc_inb(ahc, HCNTRL);
+ if (hcntrl == 0xFF)
goto fail;
/*
@@ -1230,8 +1236,13 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* either, so look for data corruption and/or flagged
* PCI errors.
*/
- ahc_outl(ahc, SRAM_BASE, 0x5aa555aa);
- if (ahc_inl(ahc, SRAM_BASE) != 0x5aa555aa)
+ ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
+ while (ahc_is_paused(ahc) == 0)
+ ;
+ ahc_outb(ahc, SEQCTL, PERRORDIS);
+ ahc_outb(ahc, SCBPTR, 0);
+ ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
+ if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
goto fail;
status1 = ahc_pci_read_config(ahc->dev_softc,
@@ -1248,7 +1259,8 @@ fail:
ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
status1, /*bytes*/1);
ahc_outb(ahc, CLRINT, CLRPARERR);
- ahc_outb(ahc, SEQCTL, seqctl);
+ ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
return (error);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
index bb46dc495ac4..54a592722f7f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#52 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#36 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#53 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#37 $
*/
typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahc_reg_parse_entry {
@@ -1779,6 +1779,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
#define MAX_OFFSET 0xff
#define BUS_16_BIT 0x01
#define SCB_UPLOAD_SIZE 0x20
+#define STACK_SIZE 0x04
/* Downloaded Constant Definitions */
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
index 0f6df05e0315..1f5ea340c9b3 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#52 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#36 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#53 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#37 $
*/
#include "aic7xxx_osm.h"
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
index 4f97b79f97c1..bea4cd639915 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#52 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#36 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#53 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#37 $
*/
static uint8_t seqprog[] = {
0xb2, 0x00, 0x00, 0x08,
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index 69749944b326..67e046d96625 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#28 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
*
* $FreeBSD$
*/
@@ -209,7 +209,7 @@ static int is_download_const(expression_t *immed);
%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
-%type <value> numerical_value mode_value mode_list macro_arglist
+%type <value> mode_value mode_list macro_arglist
%left '|'
%left '&'
@@ -784,17 +784,6 @@ macro_arglist:
}
;
-numerical_value:
- T_NUMBER
- {
- $$ = $1;
- }
-| '-' T_NUMBER
- {
- $$ = -$2;
- }
-;
-
scratch_ram:
T_SRAM '{'
{
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 3871d801407b..e93c8e9b3b7a 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -47,8 +47,6 @@ struct uart_sunsab_port {
struct uart_port port; /* Generic UART port */
union sab82532_async_regs *regs; /* Chip registers */
unsigned long irqflags; /* IRQ state flags */
- int xmit_fifo_size; /* TX fifo size */
- int recv_fifo_size; /* RX fifo size */
int dsr; /* Current DSR state */
unsigned int cec_timeout; /* Chip poll timeout... */
unsigned int tec_timeout; /* likewise */
@@ -57,8 +55,6 @@ struct uart_sunsab_port {
unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
int type; /* SAB82532 version */
- int sab_line; /* Internal numbering */
- unsigned int irq; /* Device interrupt */
};
/*
@@ -76,6 +72,9 @@ static char *sab82532_version[16] = {
#define SAB82532_MAX_TEC_TIMEOUT 200000 /* 1 character time (at 50 baud) */
#define SAB82532_MAX_CEC_TIMEOUT 50000 /* 2.5 TX CLKs (at 50 baud) */
+#define SAB82532_RECV_FIFO_SIZE 32 /* Standard async fifo sizes */
+#define SAB82532_XMIT_FIFO_SIZE 32
+
static __inline__ void sunsab_tec_wait(struct uart_sunsab_port *up)
{
int timeout = up->tec_timeout;
@@ -105,12 +104,12 @@ static void receive_chars(struct uart_sunsab_port *up,
/* Read number of BYTES (Character + Status) available. */
if (stat->sreg.isr0 & SAB82532_ISR0_RPF) {
- count = up->recv_fifo_size;
+ count = SAB82532_RECV_FIFO_SIZE;
free_fifo++;
}
if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
- count = readb(&up->regs->r.rbcl) & (up->recv_fifo_size - 1);
+ count = readb(&up->regs->r.rbcl) & (SAB82532_RECV_FIFO_SIZE - 1);
free_fifo++;
}
@@ -246,13 +245,13 @@ static void transmit_chars(struct uart_sunsab_port *up,
return;
}
- up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+ up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR);
writeb(up->interrupt_mask1, &up->regs->w.imr1);
clear_bit(SAB82532_ALLS, &up->irqflags);
/* Stuff 32 bytes into Transmit FIFO. */
clear_bit(SAB82532_XPR, &up->irqflags);
- for (i = 0; i < up->xmit_fifo_size; i++) {
+ for (i = 0; i < up->port.fifosize; i++) {
writeb(xmit->buf[xmit->tail],
&up->regs->w.xfifo[i]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -422,15 +421,16 @@ static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start)
struct circ_buf *xmit = &up->port.info->xmit;
int i;
+ up->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS|SAB82532_IMR1_XPR);
+ writeb(up->interrupt_mask1, &up->regs->w.imr1);
+
if (!test_bit(SAB82532_XPR, &up->irqflags))
return;
- up->interrupt_mask1 &= ~SAB82532_IMR1_XPR;
- writeb(up->interrupt_mask1, &up->regs->w.imr1);
clear_bit(SAB82532_ALLS, &up->irqflags);
clear_bit(SAB82532_XPR, &up->irqflags);
- for (i = 0; i < up->xmit_fifo_size; i++) {
+ for (i = 0; i < up->port.fifosize; i++) {
writeb(xmit->buf[xmit->tail],
&up->regs->w.xfifo[i]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -533,34 +533,8 @@ static int sunsab_startup(struct uart_port *port)
writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4);
writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
SAB82532_MODE_RAC, &up->regs->w.mode);
- writeb(SAB82532_RFC_DPS | SAB82532_RFC_RFDF, &up->regs->w.rfc);
-
- switch (up->recv_fifo_size) {
- case 1:
- tmp = readb(&up->regs->w.rfc);
- tmp |= SAB82532_RFC_RFTH_1;
- writeb(tmp, &up->regs->w.rfc);
- break;
- case 4:
- tmp = readb(&up->regs->w.rfc);
- tmp |= SAB82532_RFC_RFTH_4;
- writeb(tmp, &up->regs->w.rfc);
- break;
- case 16:
- tmp = readb(&up->regs->w.rfc);
- tmp |= SAB82532_RFC_RFTH_16;
- writeb(tmp, &up->regs->w.rfc);
- break;
- default:
- up->recv_fifo_size = 32;
- /* fall through */
- case 32:
- tmp = readb(&up->regs->w.rfc);
- tmp |= SAB82532_RFC_RFTH_32;
- writeb(tmp, &up->regs->w.rfc);
- break;
- };
-
+ writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc);
+
tmp = readb(&up->regs->rw.ccr0);
tmp |= SAB82532_CCR0_PU; /* power-up */
writeb(tmp, &up->regs->rw.ccr0);
@@ -796,7 +770,11 @@ static void sunsab_change_speed(struct uart_port *port, unsigned int cflag,
static const char *sunsab_type(struct uart_port *port)
{
- return "SunSAB";
+ struct uart_sunsab_port *up = (void *)port;
+ static char buf[36];
+
+ sprintf(buf, "SAB82532 %s", sab82532_version[up->type]);
+ return buf;
}
static void sunsab_release_port(struct uart_port *port)
@@ -1011,22 +989,25 @@ static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg
unsigned long regs, offset;
int i;
+ /* Note: ports are located in reverse order */
regs = edev->resource[0].start;
offset = sizeof(union sab82532_async_regs);
for (i = 0; i < 2; i++) {
- up = &sunsab_ports[(*instance_p * 2) + i];
+ up = &sunsab_ports[(*instance_p * 2) + 1 - i];
memset(up, 0, sizeof(*up));
up->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs));
- up->irq = edev->irqs[0];
- up->sab_line = 1 - i;
- up->xmit_fifo_size = 32;
- up->recv_fifo_size = 32;
+ up->port.irq = edev->irqs[0];
+ up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
+ up->port.mapbase = (unsigned long)up->regs;
+ up->port.iotype = SERIAL_IO_MEM;
writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
offset -= sizeof(union sab82532_async_regs);
}
+
+ (*instance_p)++;
}
static int __init probe_for_sabs(void)
@@ -1066,7 +1047,7 @@ static void __init sunsab_init_hw(void)
up->type = readb(&up->regs->r.vstr) & 0x0f;
writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
writeb(0xff, &up->regs->w.pim);
- if (up->sab_line == 0) {
+ if (up->port.line == 0) {
up->pvr_dsr_bit = (1 << 0);
up->pvr_dtr_bit = (1 << 1);
} else {
@@ -1082,19 +1063,14 @@ static void __init sunsab_init_hw(void)
up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
- if (!(up->sab_line & 0x01)) {
- if (request_irq(up->irq, sunsab_interrupt, SA_SHIRQ,
- "serial(sab82532)", up)) {
+ if (!(up->port.line & 0x01)) {
+ if (request_irq(up->port.irq, sunsab_interrupt,
+ SA_SHIRQ, "serial(sab82532)", up)) {
printk("sunsab%d: can't get IRQ %x\n",
- i, up->irq);
+ i, up->port.irq);
continue;
}
}
-
- printk(KERN_INFO
- "sunsab%d at 0x%lx (irq = %s) is a SAB82532 %s\n",
- i, (unsigned long)up->regs,
- __irq_itoa(up->irq), sab82532_version[up->type]);
}
}
@@ -1109,8 +1085,6 @@ static int __init sunsab_init(void)
sunsab_init_hw();
sunsab_reg.minor = sunserial_current_minor;
- sunserial_current_minor += num_channels;
-
sunsab_reg.nr = num_channels;
sunsab_reg.cons = &sunsab_console;
@@ -1121,8 +1095,8 @@ static int __init sunsab_init(void)
for (i = 0; i < num_channels; i++) {
struct uart_sunsab_port *up = &sunsab_ports[i];
- if (!(up->sab_line & 0x01))
- free_irq(up->irq, up);
+ if (!(up->port.line & 0x01))
+ free_irq(up->port.irq, up);
iounmap(up->regs);
}
kfree(sunsab_ports);
@@ -1131,6 +1105,8 @@ static int __init sunsab_init(void)
return ret;
}
+ sunserial_current_minor += num_channels;
+
for (i = 0; i < num_channels; i++) {
struct uart_sunsab_port *up = &sunsab_ports[i];
@@ -1151,11 +1127,12 @@ static void __exit sunsab_exit(void)
uart_remove_one_port(&sunsab_reg, &up->port);
- if (!(up->sab_line & 0x01))
- free_irq(up->irq, up);
+ if (!(up->port.line & 0x01))
+ free_irq(up->port.irq, up);
iounmap(up->regs);
}
+ sunserial_current_minor -= num_channels;
uart_unregister_driver(&sunsab_reg);
kfree(sunsab_ports);
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index a813a45d8e88..cfc55c2d230a 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -102,6 +102,8 @@ struct file_operations jfs_file_operations = {
.llseek = generic_file_llseek,
.write = generic_file_write,
.read = generic_file_read,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.readv = generic_file_readv,
.writev = generic_file_writev,
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 7ef944b90a07..bc5720ac2510 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -184,9 +184,9 @@ static void lbmWrite(struct jfs_log * log, struct lbuf * bp, int flag, int cant_
static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag);
static int lbmIOWait(struct lbuf * bp, int flag);
static bio_end_io_t lbmIODone;
+static void lbmStartIO(struct lbuf * bp);
+static void lmGCwrite(struct jfs_log * log, int cant_block);
-void lbmStartIO(struct lbuf * bp);
-void lmGCwrite(struct jfs_log * log, int cant_block);
/*
@@ -744,7 +744,7 @@ int lmGroupCommit(struct jfs_log * log, struct tblock * tblk)
* LOGGC_LOCK must be held by caller.
* N.B. LOG_LOCK is NOT held during lmGroupCommit().
*/
-void lmGCwrite(struct jfs_log * log, int cant_write)
+static void lmGCwrite(struct jfs_log * log, int cant_write)
{
struct lbuf *bp;
struct logpage *lp;
@@ -893,8 +893,7 @@ void lmPostGC(struct lbuf * bp)
*/
if ((tblk = log->cqueue.head) &&
((log->gcrtc > 0) || (tblk->bp->l_wqnext != NULL) ||
- test_bit(log_SYNCBARRIER, &log->flag) ||
- test_bit(log_QUIESCE, &log->flag)))
+ test_bit(log_FLUSH, &log->flag)))
/*
* Call lmGCwrite with new group leader
*/
@@ -902,11 +901,13 @@ void lmPostGC(struct lbuf * bp)
/* no transaction are ready yet (transactions are only just
* queued (GC_QUEUE) and not entered for group commit yet).
- * let the first transaction entering group commit
- * will elect hetself as new group leader.
+ * the first transaction entering group commit
+ * will elect herself as new group leader.
*/
- else
+ else {
log->cflag &= ~logGC_PAGEOUT;
+ clear_bit(log_FLUSH, &log->flag);
+ }
//LOGGC_UNLOCK(log);
spin_unlock_irqrestore(&log->gclock, flags);
@@ -1049,18 +1050,12 @@ int lmLogSync(struct jfs_log * log, int nosyncwait)
set_bit(log_SYNCBARRIER, &log->flag);
jFYI(1, ("log barrier on: lsn=0x%x syncpt=0x%x\n", lsn,
log->syncpt));
+ /*
+ * We may have to initiate group commit
+ */
+ jfs_flush_journal(log, 0);
}
- /*
- * We may have to initiate group commit
- */
- LOGGC_LOCK(log);
- if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
- log->cflag |= logGC_PAGEOUT;
- lmGCwrite(log, 0);
- }
- LOGGC_UNLOCK(log);
-
return lsn;
}
@@ -1416,21 +1411,22 @@ int lmLogClose(struct super_block *sb, struct jfs_log * log)
/*
- * NAME: lmLogWait()
+ * NAME: jfs_flush_journal()
*
- * FUNCTION: wait for all outstanding log records to be written to disk
+ * FUNCTION: initiate write of any outstanding transactions to the journal
+ * and optionally wait until they are all written to disk
*/
-void lmLogWait(struct jfs_log *log)
+void jfs_flush_journal(struct jfs_log *log, int wait)
{
int i;
- jFYI(1, ("lmLogWait: log:0x%p\n", log));
+ jFYI(1, ("jfs_flush_journal: log:0x%p wait=%d\n", log, wait));
/*
* This ensures that we will keep writing to the journal as long
* as there are unwritten commit records
*/
- set_bit(log_QUIESCE, &log->flag);
+ set_bit(log_FLUSH, &log->flag);
/*
* Initiate I/O on outstanding transactions
@@ -1442,6 +1438,9 @@ void lmLogWait(struct jfs_log *log)
}
LOGGC_UNLOCK(log);
+ if (!wait)
+ return;
+
if (log->cqueue.head || !list_empty(&log->synclist)) {
/*
* If there was very recent activity, we may need to wait
@@ -1459,7 +1458,7 @@ void lmLogWait(struct jfs_log *log)
assert(log->cqueue.head == NULL);
assert(list_empty(&log->synclist));
- clear_bit(log_QUIESCE, &log->flag); /* Probably not needed */
+ clear_bit(log_FLUSH, &log->flag);
}
/*
@@ -1488,7 +1487,7 @@ int lmLogShutdown(struct jfs_log * log)
jFYI(1, ("lmLogShutdown: log:0x%p\n", log));
- lmLogWait(log);
+ jfs_flush_journal(log, 1);
/*
* We need to make sure all of the "written" metapages
@@ -1946,7 +1945,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
*
* serialization: LCACHE_LOCK() is NOT held during log i/o;
*/
-void lbmStartIO(struct lbuf * bp)
+static void lbmStartIO(struct lbuf * bp)
{
struct bio *bio;
struct jfs_log *log = bp->l_log;
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 112877ce045f..45eb3316d991 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -424,6 +424,7 @@ struct jfs_log {
#define log_INLINELOG 1
#define log_SYNCBARRIER 2
#define log_QUIESCE 3
+#define log_FLUSH 4
/*
* group commit flag
@@ -501,11 +502,11 @@ struct logsyncblk {
}
extern int lmLogOpen(struct super_block *sb, struct jfs_log ** log);
-extern void lmLogWait(struct jfs_log * log);
extern int lmLogClose(struct super_block *sb, struct jfs_log * log);
extern int lmLogSync(struct jfs_log * log, int nosyncwait);
extern int lmLogShutdown(struct jfs_log * log);
extern int lmLogInit(struct jfs_log * log);
extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
+extern void jfs_flush_journal(struct jfs_log * log, int wait);
#endif /* _H_JFS_LOGMGR */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e7971c7dd725..3a9fef349e74 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -158,7 +158,6 @@ struct {
* external references
*/
extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern int lmGCwrite(struct jfs_log *, int);
extern void lmSync(struct jfs_log *);
extern int jfs_commit_inode(struct inode *, int);
extern int jfs_stop_threads;
@@ -2969,12 +2968,7 @@ restart:
/*
* We may need to kick off the group commit
*/
- spin_lock_irq(&log->gclock); // LOGGC_LOCK
- if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
- log->cflag |= logGC_PAGEOUT;
- lmGCwrite(log, 0);
- }
- spin_unlock_irq(&log->gclock); // LOGGC_UNLOCK
+ jfs_flush_journal(log, 0);
}
/*
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 88e747f514c1..a81ef8c832bb 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -69,7 +69,7 @@ int jfs_umount(struct super_block *sb)
/*
* Wait for outstanding transactions to be written to log:
*/
- lmLogWait(log);
+ jfs_flush_journal(log, 1);
/*
* close fileset inode allocation map (aka fileset inode)
@@ -153,7 +153,7 @@ int jfs_umount_rw(struct super_block *sb)
*
* remove file system from log active file system list.
*/
- lmLogWait(log);
+ jfs_flush_journal(log, 1);
/*
* Make sure all metadata makes it to disk
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 0094be7e0e1b..07cde7e7cad8 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -514,7 +514,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
mark_buffer_dirty(bh);
ll_rw_block(WRITE, 1, &bh2);
wait_on_buffer(bh2);
- brelse(bh);
+ brelse(bh2);
}
/* write primary superblock */
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index cc2731f0ca6d..fcc1ad80ceba 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -382,6 +382,17 @@ static struct super_block *jfs_get_sb(struct file_system_type *fs_type,
return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
}
+static int jfs_sync_fs(struct super_block *sb, int wait)
+{
+ struct jfs_log *log = JFS_SBI(sb)->log;
+
+ /* log == NULL indicates read-only mount */
+ if (log)
+ jfs_flush_journal(log, wait);
+
+ return 0;
+}
+
static struct super_operations jfs_super_operations = {
.alloc_inode = jfs_alloc_inode,
.destroy_inode = jfs_destroy_inode,
@@ -389,6 +400,7 @@ static struct super_operations jfs_super_operations = {
.write_inode = jfs_write_inode,
.delete_inode = jfs_delete_inode,
.put_super = jfs_put_super,
+ .sync_fs = jfs_sync_fs,
.write_super_lockfs = jfs_write_super_lockfs,
.unlockfs = jfs_unlockfs,
.statfs = jfs_statfs,
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index 905bc7a1284d..9405531fb35b 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -10,6 +10,7 @@
#endif
#define no_balance_irq (0)
+#define esr_disable (0)
#define APIC_BROADCAST_ID 0x0F
#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
@@ -53,6 +54,11 @@ static inline int multi_timer_check(int apic, int irq)
return 0;
}
+static inline int apicid_to_node(int logical_apicid)
+{
+ return 0;
+}
+
static inline int cpu_present_to_apicid(int mps_cpu)
{
return mps_cpu;
@@ -73,10 +79,13 @@ static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
return (m->mpc_apicid);
}
-#define WAKE_SECONDARY_VIA_INIT
-
static inline void setup_portio_remap(void)
{
}
+static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-default/mach_wakecpu.h b/include/asm-i386/mach-default/mach_wakecpu.h
new file mode 100644
index 000000000000..673b85c9b273
--- /dev/null
+++ b/include/asm-i386/mach-default/mach_wakecpu.h
@@ -0,0 +1,41 @@
+#ifndef __ASM_MACH_WAKECPU_H
+#define __ASM_MACH_WAKECPU_H
+
+/*
+ * This file copes with machines that wakeup secondary CPUs by the
+ * INIT, INIT, STARTUP sequence.
+ */
+
+#define WAKE_SECONDARY_VIA_INIT
+
+#define TRAMPOLINE_LOW phys_to_virt(0x467)
+#define TRAMPOLINE_HIGH phys_to_virt(0x469)
+
+#define boot_cpu_apicid boot_cpu_physical_apicid
+
+static inline void wait_for_init_deassert(atomic_t *deassert)
+{
+ while (!atomic_read(deassert));
+ return;
+}
+
+/* Nothing to do for most platforms, since cleared by the INIT cycle */
+static inline void smp_callin_clear_local_apic(void)
+{
+}
+
+static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+#if APIC_DEBUG
+ #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
+#else
+ #define inquire_remote_apic(apicid) {}
+#endif
+
+#endif /* __ASM_MACH_WAKECPU_H */
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index 94d2f5f28275..05c0fd19266d 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -1,14 +1,15 @@
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
-#define APIC_DFR_VALUE (APIC_DFR_FLAT)
+#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
#define TARGET_CPUS (0xf)
#define no_balance_irq (1)
+#define esr_disable (1)
#define APIC_BROADCAST_ID 0x0F
-#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
+#define check_apicid_used(bitmap, apicid) ((bitmap) & (1 << (apicid)))
static inline int apic_id_registered(void)
{
@@ -26,6 +27,10 @@ static inline void clustered_apic_check(void)
"NUMA-Q", nr_ioapics);
}
+/*
+ * Skip adding the timer int on secondary nodes, which causes
+ * a small but painful rift in the time-space continuum.
+ */
static inline int multi_timer_check(int apic, int irq)
{
return (apic != 0 && irq == 0);
@@ -47,14 +52,14 @@ static inline int generate_logical_apicid(int quad, int phys_apicid)
return ( (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1) );
}
-static inline int apicid_to_quad(int logical_apicid)
+static inline int apicid_to_node(int logical_apicid)
{
return (logical_apicid >> 4);
}
static inline unsigned long apicid_to_cpu_present(int logical_apicid)
{
- return ( (logical_apicid&0xf) << (4*apicid_to_quad(logical_apicid)) );
+ return ( (logical_apicid&0xf) << (4*apicid_to_node(logical_apicid)) );
}
static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
@@ -69,8 +74,6 @@ static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
return logical_apicid;
}
-#define WAKE_SECONDARY_VIA_NMI
-
static inline void setup_portio_remap(void)
{
if (numnodes <= 1)
@@ -82,4 +85,9 @@ static inline void setup_portio_remap(void)
(u_long) xquad_portio, (u_long) numnodes*XQUAD_PORTIO_QUAD);
}
+static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return (1);
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-numaq/mach_wakecpu.h b/include/asm-i386/mach-numaq/mach_wakecpu.h
new file mode 100644
index 000000000000..00530041a991
--- /dev/null
+++ b/include/asm-i386/mach-numaq/mach_wakecpu.h
@@ -0,0 +1,43 @@
+#ifndef __ASM_MACH_WAKECPU_H
+#define __ASM_MACH_WAKECPU_H
+
+/* This file copes with machines that wakeup secondary CPUs by NMIs */
+
+#define WAKE_SECONDARY_VIA_NMI
+
+#define TRAMPOLINE_LOW phys_to_virt(0x8)
+#define TRAMPOLINE_HIGH phys_to_virt(0xa)
+
+#define boot_cpu_apicid boot_cpu_logical_apicid
+
+/* We don't do anything here because we use NMI's to boot instead */
+static inline void wait_for_init_deassert(atomic_t *deassert)
+{
+}
+
+/*
+ * Because we use NMIs rather than the INIT-STARTUP sequence to
+ * bootstrap the CPUs, the APIC may be in a weird state. Kick it.
+ */
+static inline void smp_callin_clear_local_apic(void)
+{
+ clear_local_APIC();
+}
+
+static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
+{
+ printk("Storing NMI vector\n");
+ *high = *((volatile unsigned short *) TRAMPOLINE_HIGH);
+ *low = *((volatile unsigned short *) TRAMPOLINE_LOW);
+}
+
+static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
+{
+ printk("Restoring NMI vector\n");
+ *((volatile unsigned short *) TRAMPOLINE_HIGH) = *high;
+ *((volatile unsigned short *) TRAMPOLINE_LOW) = *low;
+}
+
+#define inquire_remote_apic(apicid) {}
+
+#endif /* __ASM_MACH_WAKECPU_H */
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index bf601c3368ad..78f6b26f0ead 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -3,6 +3,8 @@
extern int x86_summit;
+#define esr_disable (1)
+
#define XAPIC_DEST_CPUS_MASK 0x0Fu
#define XAPIC_DEST_CLUSTER_MASK 0xF0u
@@ -32,6 +34,11 @@ static inline void clustered_apic_check(void)
(x86_summit ? "Summit" : "Flat"), nr_ioapics);
}
+static inline int apicid_to_node(int logical_apicid)
+{
+ return (logical_apicid >> 5); /* 2 clusterids per CEC */
+}
+
static inline int cpu_present_to_apicid(int mps_cpu)
{
if (x86_summit)
@@ -54,10 +61,13 @@ static inline unsigned long apicid_to_phys_cpu_present(int apicid)
return (1ul << apicid);
}
-#define WAKE_SECONDARY_VIA_INIT
-
static inline void setup_portio_remap(void)
{
}
+static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return (1);
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h
index 6f52745df91c..1d9c8d48f06a 100644
--- a/include/asm-i386/numaq.h
+++ b/include/asm-i386/numaq.h
@@ -28,8 +28,6 @@
#ifdef CONFIG_X86_NUMAQ
-#include <asm/smpboot.h>
-
/*
* for now assume that 64Gb is max amount of RAM for whole system
* 64Gb / 4096bytes/page = 16777216 pages
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 71d58561d39c..85c61d5f9497 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -22,22 +22,12 @@
#endif
#endif
-#ifdef CONFIG_CLUSTERED_APIC
+#ifdef CONFIG_X86_NUMAQ
#define INT_DELIVERY_MODE 0 /* physical delivery on LOCAL quad */
#else
#define INT_DELIVERY_MODE 1 /* logical delivery broadcast to all procs */
#endif
-#ifndef clustered_apic_mode
- #ifdef CONFIG_CLUSTERED_APIC
- #define clustered_apic_mode (1)
- #define esr_disable (1)
- #else /* !CONFIG_CLUSTERED_APIC */
- #define clustered_apic_mode (0)
- #define esr_disable (0)
- #endif /* CONFIG_CLUSTERED_APIC */
-#endif
-
#define BAD_APICID 0xFFu
#ifdef CONFIG_SMP
#ifndef __ASSEMBLY__
@@ -62,15 +52,7 @@ extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
-/*
- * Some lowlevel functions might want to know about
- * the real APIC ID <-> CPU # mapping.
- */
#define MAX_APICID 256
-extern volatile int cpu_to_physical_apicid[NR_CPUS];
-extern volatile int physical_apicid_to_cpu[MAX_APICID];
-extern volatile int cpu_to_logical_apicid[NR_CPUS];
-extern volatile int logical_apicid_to_cpu[MAX_APICID];
/*
* This function is needed by all SMP systems. It must _always_ be valid
@@ -100,6 +82,15 @@ static inline int num_booting_cpus(void)
return hweight32(cpu_callout_map);
}
+/* Mapping from cpu number to logical apicid */
+extern volatile u8 cpu_2_logical_apicid[];
+static inline int cpu_to_logical_apicid(int cpu)
+{
+ return (int)cpu_2_logical_apicid[cpu];
+}
+extern void map_cpu_to_logical_apicid(void);
+extern void unmap_cpu_to_logical_apicid(int cpu);
+
extern inline int any_online_cpu(unsigned int mask)
{
if (mask & cpu_online_map)
diff --git a/include/asm-i386/smpboot.h b/include/asm-i386/smpboot.h
deleted file mode 100644
index a3840aa6eca8..000000000000
--- a/include/asm-i386/smpboot.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __ASM_SMPBOOT_H
-#define __ASM_SMPBOOT_H
-
-#ifndef clustered_apic_mode
- #ifdef CONFIG_CLUSTERED_APIC
- #define clustered_apic_mode (1)
- #else /* !CONFIG_CLUSTERED_APIC */
- #define clustered_apic_mode (0)
- #endif /* CONFIG_CLUSTERED_APIC */
-#endif
-
-#ifdef CONFIG_CLUSTERED_APIC
- #define TRAMPOLINE_LOW phys_to_virt(0x8)
- #define TRAMPOLINE_HIGH phys_to_virt(0xa)
-#else /* !CONFIG_CLUSTERED_APIC */
- #define TRAMPOLINE_LOW phys_to_virt(0x467)
- #define TRAMPOLINE_HIGH phys_to_virt(0x469)
-#endif /* CONFIG_CLUSTERED_APIC */
-
-#ifdef CONFIG_CLUSTERED_APIC
- #define boot_cpu_apicid boot_cpu_logical_apicid
-#else /* !CONFIG_CLUSTERED_APIC */
- #define boot_cpu_apicid boot_cpu_physical_apicid
-#endif /* CONFIG_CLUSTERED_APIC */
-
-/*
- * Mappings between logical cpu number and logical / physical apicid
- * The first four macros are trivial, but it keeps the abstraction consistent
- */
-extern volatile int logical_apicid_2_cpu[];
-extern volatile int cpu_2_logical_apicid[];
-extern volatile int physical_apicid_2_cpu[];
-extern volatile int cpu_2_physical_apicid[];
-
-#define logical_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
-#define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu]
-#define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
-#define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu]
-#ifdef CONFIG_CLUSTERED_APIC /* use logical IDs to bootstrap */
-#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
-#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu]
-#else /* !CONFIG_CLUSTERED_APIC */ /* use physical IDs to bootstrap */
-#define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
-#define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu]
-#endif /* CONFIG_CLUSTERED_APIC */
-
-
-#endif
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index d3bdbb0c40c6..3609d59e8c30 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -27,12 +27,17 @@
#ifndef _ASM_I386_TOPOLOGY_H
#define _ASM_I386_TOPOLOGY_H
-#ifdef CONFIG_X86_NUMAQ
+#ifdef CONFIG_NUMA
-#include <asm/smpboot.h>
+/* Mappings between logical cpu number and node number */
+extern volatile unsigned long node_2_cpu_mask[];
+extern volatile int cpu_2_node[];
/* Returns the number of the node containing CPU 'cpu' */
-#define __cpu_to_node(cpu) (cpu_to_logical_apicid(cpu) >> 4)
+static inline int __cpu_to_node(int cpu)
+{
+ return cpu_2_node[cpu];
+}
/* Returns the number of the node containing MemBlk 'memblk' */
#define __memblk_to_node(memblk) (memblk)
@@ -41,49 +46,22 @@
so it is a pretty simple function! */
#define __parent_node(node) (node)
-/* Returns the number of the first CPU on Node 'node'.
- * This should be changed to a set of cached values
- * but this will do for now.
- */
-static inline int __node_to_first_cpu(int node)
-{
- int i, cpu, logical_apicid = node << 4;
-
- for(i = 1; i < 16; i <<= 1)
- /* check to see if the cpu is in the system */
- if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
- /* if yes, return it to caller */
- return cpu;
-
- BUG(); /* couldn't find a cpu on given node */
- return -1;
-}
-
-/* Returns a bitmask of CPUs on Node 'node'.
- * This should be changed to a set of cached bitmasks
- * but this will do for now.
- */
+/* Returns a bitmask of CPUs on Node 'node'. */
static inline unsigned long __node_to_cpu_mask(int node)
{
- int i, cpu, logical_apicid = node << 4;
- unsigned long mask = 0UL;
-
- if (sizeof(unsigned long) * 8 < NR_CPUS)
- BUG();
-
- for(i = 1; i < 16; i <<= 1)
- /* check to see if the cpu is in the system */
- if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
- /* if yes, add to bitmask */
- mask |= 1 << cpu;
+ return node_2_cpu_mask[node];
+}
- return mask;
+/* Returns the number of the first CPU on Node 'node'. */
+static inline int __node_to_first_cpu(int node)
+{
+ return __ffs(__node_to_cpu_mask(node));
}
/* Returns the number of the first MemBlk on Node 'node' */
#define __node_to_memblk(node) (node)
-#else /* !CONFIG_X86_NUMAQ */
+#else /* !CONFIG_NUMA */
/*
* Other i386 platforms should define their own version of the
* above macros here.
@@ -91,6 +69,6 @@ static inline unsigned long __node_to_cpu_mask(int node)
#include <asm-generic/topology.h>
-#endif /* CONFIG_X86_NUMAQ */
+#endif /* CONFIG_NUMA */
#endif /* _ASM_I386_TOPOLOGY_H */
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index dd936fe6180e..77906e130efd 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -40,6 +40,7 @@
#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */
#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */
#define ARPHRD_EUI64 27 /* EUI-64 */
+#define ARPHRD_INFINIBAND 32 /* InfiniBand */
/* Dummy types for non ARP hardware */
#define ARPHRD_SLIP 256
diff --git a/include/linux/module.h b/include/linux/module.h
index 54214da9a651..8b0084419604 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -328,7 +328,7 @@ search_module_extables(unsigned long addr)
}
/* Is this address in a module? */
-static int module_text_address(unsigned long addr)
+static inline int module_text_address(unsigned long addr)
{
return 0;
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 888d520fd319..2a6e10e6e598 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -66,7 +66,7 @@ struct vlan_group;
#endif
-#define MAX_ADDR_LEN 8 /* Largest hardware address length */
+#define MAX_ADDR_LEN 32 /* Largest hardware address length */
/*
* Compute the worst case header length according to the protocols
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 57296f48dc02..40ceec333586 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -17,6 +17,7 @@
#define RTM_NEWLINK (RTM_BASE+0)
#define RTM_DELLINK (RTM_BASE+1)
#define RTM_GETLINK (RTM_BASE+2)
+#define RTM_SETLINK (RTM_BASE+3)
#define RTM_NEWADDR (RTM_BASE+4)
#define RTM_DELADDR (RTM_BASE+5)
diff --git a/include/net/icmp.h b/include/net/icmp.h
index f757af415632..2e11a0b2355c 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -23,6 +23,7 @@
#include <net/sock.h>
#include <net/protocol.h>
+#include <net/snmp.h>
#include <linux/ip.h>
struct icmp_err {
@@ -31,10 +32,22 @@ struct icmp_err {
};
extern struct icmp_err icmp_err_convert[];
-extern struct icmp_mib icmp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics);
#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)
+#define ICMP_INC_STATS_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[!in_softirq()],\
+ smp_processor_id())) + offt))++;
+#define ICMP_INC_STATS_BH_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[0], \
+ smp_processor_id())) + offt))++;
+#define ICMP_INC_STATS_USER_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[1], \
+ smp_processor_id())) + offt))++;
extern void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info);
extern int icmp_rcv(struct sk_buff *skb);
diff --git a/include/net/ip.h b/include/net/ip.h
index 7b365788fe00..f3c975e75409 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -149,14 +149,16 @@ struct ipv4_config
};
extern struct ipv4_config ipv4_config;
-extern struct ip_mib ip_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct ip_mib, ip_statistics);
#define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field)
#define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field)
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)
-extern struct linux_mib net_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
#define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field)
#define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field)
#define NET_INC_STATS_USER(field) SNMP_INC_STATS_USER(net_statistics, field)
+#define NET_ADD_STATS_BH(field, adnd) SNMP_ADD_STATS_BH(net_statistics, field, adnd)
+#define NET_ADD_STATS_USER(field, adnd) SNMP_ADD_STATS_USER(net_statistics, field, adnd)
extern int sysctl_local_port_range[2];
extern int sysctl_ip_default_ttl;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5b4af83c5b52..e9ee8854929e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -19,6 +19,7 @@
#include <asm/hardirq.h>
#include <net/ndisc.h>
#include <net/flow.h>
+#include <net/snmp.h>
#define SIN6_LEN_RFC2133 24
@@ -105,15 +106,19 @@ struct frag_hdr {
/* sysctls */
extern int sysctl_ipv6_bindv6only;
-extern struct ipv6_mib ipv6_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field)
-extern struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
#define ICMP6_INC_STATS(field) SNMP_INC_STATS(icmpv6_statistics, field)
#define ICMP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpv6_statistics, field)
#define ICMP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpv6_statistics, field)
-extern struct udp_mib udp_stats_in6[NR_CPUS*2];
+#define ICMP6_STATS_PTR_BH(field) \
+ (& \
+ ((per_cpu_ptr(icmpv6_statistics[0], smp_processor_id()))-> \
+ field))
+DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field)
#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field)
#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
diff --git a/include/net/route.h b/include/net/route.h
index 593311a57fca..ba15b5140798 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -102,7 +102,11 @@ struct rt_cache_stat
unsigned int gc_ignored;
unsigned int gc_goal_miss;
unsigned int gc_dst_overflow;
-} ____cacheline_aligned_in_smp;
+};
+
+extern struct rt_cache_stat *rt_cache_stat;
+#define RT_CACHE_STAT_INC(field) \
+ (per_cpu_ptr(rt_cache_stat, smp_processor_id())->field++)
extern struct ip_rt_acct *ip_rt_acct;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f12e54cd4919..297e83dc6c25 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -203,7 +203,7 @@ extern void sctp_hash_digest(const char *secret, const int secret_len,
#define SCTP_SOCK_SLEEP_POST(sk) SOCK_SLEEP_POST(sk)
/* SCTP SNMP MIB stats handlers */
-extern struct sctp_mib sctp_statistics[NR_CPUS * 2];
+DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
#define SCTP_INC_STATS(field) SNMP_INC_STATS(sctp_statistics, field)
#define SCTP_INC_STATS_BH(field) SNMP_INC_STATS_BH(sctp_statistics, field)
#define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 553e8c0eedce..3b3ed7252d38 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -62,7 +62,7 @@ struct ip_mib
unsigned long IpFragFails;
unsigned long IpFragCreates;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct ipv6_mib
{
@@ -89,7 +89,7 @@ struct ipv6_mib
unsigned long Ip6InMcastPkts;
unsigned long Ip6OutMcastPkts;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct icmp_mib
{
@@ -121,7 +121,7 @@ struct icmp_mib
unsigned long IcmpOutAddrMaskReps;
unsigned long dummy;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct icmpv6_mib
{
@@ -159,7 +159,7 @@ struct icmpv6_mib
unsigned long Icmp6OutGroupMembResponses;
unsigned long Icmp6OutGroupMembReductions;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct tcp_mib
{
@@ -178,7 +178,7 @@ struct tcp_mib
unsigned long TcpInErrs;
unsigned long TcpOutRsts;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct udp_mib
{
@@ -187,7 +187,7 @@ struct udp_mib
unsigned long UdpInErrors;
unsigned long UdpOutDatagrams;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
/* draft-ietf-sigtran-sctp-mib-07.txt */
struct sctp_mib
@@ -216,7 +216,7 @@ struct sctp_mib
unsigned long SctpValCookieLife;
unsigned long SctpMaxInitRetr;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct linux_mib
{
@@ -286,7 +286,7 @@ struct linux_mib
unsigned long TCPAbortFailed;
unsigned long TCPMemoryPressures;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
/*
@@ -294,8 +294,25 @@ struct linux_mib
* addl $1,memory is atomic against interrupts (but atomic_inc would be overkill because of the lock
* cycles). Wants new nonlocked_atomic_inc() primitives -AK
*/
-#define SNMP_INC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_softirq()].field++)
-#define SNMP_INC_STATS_BH(mib, field) ((mib)[2*smp_processor_id()].field++)
-#define SNMP_INC_STATS_USER(mib, field) ((mib)[2*smp_processor_id()+1].field++)
+#define DEFINE_SNMP_STAT(type, name) \
+ __typeof__(type) *name[2]
+#define DECLARE_SNMP_STAT(type, name) \
+ extern __typeof__(type) *name[2]
+
+#define SNMP_STAT_USRPTR(name) (name[0])
+#define SNMP_STAT_BHPTR(name) (name[1])
+
+#define SNMP_INC_STATS_BH(mib, field) \
+ (per_cpu_ptr(mib[0], smp_processor_id())->field++)
+#define SNMP_INC_STATS_USER(mib, field) \
+ (per_cpu_ptr(mib[1], smp_processor_id())->field++)
+#define SNMP_INC_STATS(mib, field) \
+ (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field++)
+#define SNMP_DEC_STATS(mib, field) \
+ (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field--)
+#define SNMP_ADD_STATS_BH(mib, field, addend) \
+ (per_cpu_ptr(mib[0], smp_processor_id())->field += addend)
+#define SNMP_ADD_STATS_USER(mib, field, addend) \
+ (per_cpu_ptr(mib[1], smp_processor_id())->field += addend)
#endif
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 38cc0e90793b..052621f03bc8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -28,6 +28,7 @@
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/cache.h>
+#include <linux/percpu.h>
#include <net/checksum.h>
#include <net/sock.h>
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -630,10 +631,11 @@ extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
extern struct proto tcp_prot;
-extern struct tcp_mib tcp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics);
#define TCP_INC_STATS(field) SNMP_INC_STATS(tcp_statistics, field)
#define TCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(tcp_statistics, field)
#define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field)
+#define TCP_DEC_STATS(field) SNMP_DEC_STATS(tcp_statistics, field)
extern void tcp_put_port(struct sock *sk);
extern void __tcp_put_port(struct sock *sk);
@@ -1399,7 +1401,7 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
/* fall through */
default:
if (oldstate==TCP_ESTABLISHED)
- tcp_statistics[smp_processor_id()*2+!in_softirq()].TcpCurrEstab--;
+ TCP_DEC_STATS(TcpCurrEstab);
}
/* Change state AFTER socket is unhashed to avoid closed
diff --git a/include/net/udp.h b/include/net/udp.h
index 63a24bdd3b06..4684cba23be2 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -25,6 +25,7 @@
#include <linux/udp.h>
#include <linux/ip.h>
#include <net/sock.h>
+#include <net/snmp.h>
#define UDP_HTABLE_SIZE 128
@@ -71,7 +72,7 @@ extern int udp_rcv(struct sk_buff *skb);
extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int udp_disconnect(struct sock *sk, int flags);
-extern struct udp_mib udp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9b5ee08067eb..227e6d24e0ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2133,7 +2133,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
case SIOCGIFHWADDR:
memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
- MAX_ADDR_LEN);
+ min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
ifr->ifr_hwaddr.sa_family = dev->type;
return 0;
@@ -2154,7 +2154,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
if (ifr->ifr_hwaddr.sa_family != dev->type)
return -EINVAL;
memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
- MAX_ADDR_LEN);
+ min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
notifier_call_chain(&netdev_chain,
NETDEV_CHANGEADDR, dev);
return 0;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1702d8aa0ad0..e324ae6f75f3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -220,6 +220,40 @@ int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
+static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+ struct rtattr **ida = arg;
+ struct net_device *dev;
+ int err;
+
+ dev = dev_get_by_index(ifm->ifi_index);
+ if (!dev)
+ return -ENODEV;
+
+ err = -EINVAL;
+
+ if (ida[IFLA_ADDRESS - 1]) {
+ if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
+ goto out;
+ memcpy(dev->dev_addr, RTA_DATA(ida[IFLA_ADDRESS - 1]),
+ dev->addr_len);
+ }
+
+ if (ida[IFLA_BROADCAST - 1]) {
+ if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
+ goto out;
+ memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
+ dev->addr_len);
+ }
+
+ err = 0;
+
+out:
+ dev_put(dev);
+ return err;
+}
+
int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
@@ -457,33 +491,15 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
{
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, rtnetlink_dump_ifinfo, },
- { NULL, NULL, },
-
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, rtnetlink_dump_all, },
- { NULL, NULL, },
-
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, rtnetlink_dump_all, },
- { NULL, NULL, },
-
- { neigh_add, NULL, },
- { neigh_delete, NULL, },
- { NULL, neigh_dump_info, },
- { NULL, NULL, },
-
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
+ [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+ [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
+ [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
+ [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
+ [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }
};
-
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f4d80a269118..9d2ff54b8ecb 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -324,7 +324,9 @@ void __kfree_skb(struct sk_buff *skb)
}
dst_release(skb->dst);
+#ifdef CONFIG_INET
secpath_put(skb->sp);
+#endif
if(skb->destructor) {
if (in_irq())
printk(KERN_WARNING "Warning: kfree_skb on "
@@ -378,7 +380,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
C(dst);
dst_clone(n->dst);
C(sp);
+#ifdef CONFIG_INET
secpath_get(n->sp);
+#endif
memcpy(n->cb, skb->cb, sizeof(skb->cb));
C(len);
C(data_len);
@@ -438,7 +442,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->priority = old->priority;
new->protocol = old->protocol;
new->dst = dst_clone(old->dst);
+#ifdef CONFIG_INET
new->sp = secpath_get(old->sp);
+#endif
new->h.raw = old->h.raw + offset;
new->nh.raw = old->nh.raw + offset;
new->mac.raw = old->mac.raw + offset;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 6d5a73065d48..941737af67f0 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -113,7 +113,7 @@
#include <linux/mroute.h>
#endif
-struct linux_mib net_statistics[NR_CPUS * 2];
+DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
#ifdef INET_REFCNT_DEBUG
atomic_t inet_sock_nr;
@@ -1053,6 +1053,59 @@ static struct inet_protocol icmp_protocol = {
.handler = icmp_rcv,
};
+static int __init init_ipv4_mibs(void)
+{
+ int i;
+
+ net_statistics[0] =
+ kmalloc_percpu(sizeof (struct linux_mib), GFP_KERNEL);
+ net_statistics[1] =
+ kmalloc_percpu(sizeof (struct linux_mib), GFP_KERNEL);
+ ip_statistics[0] = kmalloc_percpu(sizeof (struct ip_mib), GFP_KERNEL);
+ ip_statistics[1] = kmalloc_percpu(sizeof (struct ip_mib), GFP_KERNEL);
+ icmp_statistics[0] =
+ kmalloc_percpu(sizeof (struct icmp_mib), GFP_KERNEL);
+ icmp_statistics[1] =
+ kmalloc_percpu(sizeof (struct icmp_mib), GFP_KERNEL);
+ tcp_statistics[0] = kmalloc_percpu(sizeof (struct tcp_mib), GFP_KERNEL);
+ tcp_statistics[1] = kmalloc_percpu(sizeof (struct tcp_mib), GFP_KERNEL);
+ udp_statistics[0] = kmalloc_percpu(sizeof (struct udp_mib), GFP_KERNEL);
+ udp_statistics[1] = kmalloc_percpu(sizeof (struct udp_mib), GFP_KERNEL);
+ if (!
+ (net_statistics[0] && net_statistics[1] && ip_statistics[0]
+ && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1]
+ && udp_statistics[0] && udp_statistics[1]))
+ return -ENOMEM;
+
+ /* Set all the per cpu copies of the mibs to zero */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_possible(i)) {
+ memset(per_cpu_ptr(net_statistics[0], i), 0,
+ sizeof (struct linux_mib));
+ memset(per_cpu_ptr(net_statistics[1], i), 0,
+ sizeof (struct linux_mib));
+ memset(per_cpu_ptr(ip_statistics[0], i), 0,
+ sizeof (struct ip_mib));
+ memset(per_cpu_ptr(ip_statistics[1], i), 0,
+ sizeof (struct ip_mib));
+ memset(per_cpu_ptr(icmp_statistics[0], i), 0,
+ sizeof (struct icmp_mib));
+ memset(per_cpu_ptr(icmp_statistics[1], i), 0,
+ sizeof (struct icmp_mib));
+ memset(per_cpu_ptr(tcp_statistics[0], i), 0,
+ sizeof (struct tcp_mib));
+ memset(per_cpu_ptr(tcp_statistics[1], i), 0,
+ sizeof (struct tcp_mib));
+ memset(per_cpu_ptr(udp_statistics[0], i), 0,
+ sizeof (struct udp_mib));
+ memset(per_cpu_ptr(udp_statistics[1], i), 0,
+ sizeof (struct udp_mib));
+ }
+ }
+
+ return 0;
+}
+
int ipv4_proc_init(void);
static int __init inet_init(void)
@@ -1148,7 +1201,13 @@ static int __init inet_init(void)
#if defined(CONFIG_IP_MROUTE)
ip_mr_init();
#endif
+ /*
+ * Initialise per-cpu ipv4 mibs
+ */
+ if(init_ipv4_mibs())
+ printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
+
ipv4_proc_init();
return 0;
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 6be6e91d01cf..1db9547314c4 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -113,7 +113,7 @@ struct icmp_bxm {
/*
* Statistics
*/
-struct icmp_mib icmp_statistics[NR_CPUS * 2];
+DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
/* An array of errno for error messages from dest unreach. */
/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */
@@ -213,12 +213,11 @@ int sysctl_icmp_ratemask = 0x1818;
* ICMP control array. This specifies what to do with each ICMP.
*/
-struct icmp_control
-{
- unsigned long *output; /* Address to increment on output */
- unsigned long *input; /* Address to increment on input */
+struct icmp_control {
+ int output_off; /* Field offset for increment on output */
+ int input_off; /* Field offset for increment on input */
void (*handler)(struct sk_buff *skb);
- short error; /* This ICMP is classed as an error message */
+ short error; /* This ICMP is classed as an error message */
};
static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
@@ -343,10 +342,7 @@ out:
static void icmp_out_count(int type)
{
if (type <= NR_ICMP_TYPES) {
- (icmp_pointers[type].output)[(smp_processor_id() * 2 +
- !in_softirq()) *
- sizeof(struct icmp_mib) /
- sizeof(unsigned long)]++;
+ ICMP_INC_STATS_FIELD(icmp_pointers[type].output_off);
ICMP_INC_STATS(IcmpOutMsgs);
}
}
@@ -1005,9 +1001,7 @@ int icmp_rcv(struct sk_buff *skb)
}
}
- icmp_pointers[icmph->type].input[smp_processor_id() * 2 *
- sizeof(struct icmp_mib) /
- sizeof(unsigned long)]++;
+ ICMP_INC_STATS_BH_FIELD(icmp_pointers[icmph->type].input_off);
(icmp_pointers[icmph->type].handler)(skb);
drop:
@@ -1024,122 +1018,122 @@ error:
static struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
/* ECHO REPLY (0) */
[0] = {
- .output = &icmp_statistics[0].IcmpOutEchoReps,
- .input = &icmp_statistics[0].IcmpInEchoReps,
+ .output_off = offsetof(struct icmp_mib, IcmpOutEchoReps),
+ .input_off = offsetof(struct icmp_mib, IcmpInEchoReps),
.handler = icmp_discard,
},
[1] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib,IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
[2] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib,IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
/* DEST UNREACH (3) */
[3] = {
- .output = &icmp_statistics[0].IcmpOutDestUnreachs,
- .input = &icmp_statistics[0].IcmpInDestUnreachs,
+ .output_off = offsetof(struct icmp_mib, IcmpOutDestUnreachs),
+ .input_off = offsetof(struct icmp_mib, IcmpInDestUnreachs),
.handler = icmp_unreach,
.error = 1,
},
/* SOURCE QUENCH (4) */
[4] = {
- .output = &icmp_statistics[0].IcmpOutSrcQuenchs,
- .input = &icmp_statistics[0].IcmpInSrcQuenchs,
+ .output_off = offsetof(struct icmp_mib, IcmpOutSrcQuenchs),
+ .input_off = offsetof(struct icmp_mib, IcmpInSrcQuenchs),
icmp_unreach,
.error = 1,
},
/* REDIRECT (5) */
[5] = {
- .output = &icmp_statistics[0].IcmpOutRedirects,
- .input = &icmp_statistics[0].IcmpInRedirects,
+ .output_off = offsetof(struct icmp_mib, IcmpOutRedirects),
+ .input_off = offsetof(struct icmp_mib, IcmpInRedirects),
.handler = icmp_redirect,
.error = 1,
},
[6] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
[7] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
/* ECHO (8) */
[8] = {
- .output = &icmp_statistics[0].IcmpOutEchos,
- .input = &icmp_statistics[0].IcmpInEchos,
+ .output_off = offsetof(struct icmp_mib, IcmpOutEchos),
+ .input_off = offsetof(struct icmp_mib, IcmpInEchos),
.handler = icmp_echo,
.error = 0,
},
[9] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
[10] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].IcmpInErrors,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, IcmpInErrors),
.handler = icmp_discard,
.error = 1,
},
/* TIME EXCEEDED (11) */
[11] = {
- .output = &icmp_statistics[0].IcmpOutTimeExcds,
- .input = &icmp_statistics[0].IcmpInTimeExcds,
+ .output_off = offsetof(struct icmp_mib, IcmpOutTimeExcds),
+ .input_off = offsetof(struct icmp_mib,IcmpInTimeExcds),
.handler = icmp_unreach,
.error = 1,
},
/* PARAMETER PROBLEM (12) */
[12] = {
- .output = &icmp_statistics[0].IcmpOutParmProbs,
- .input = &icmp_statistics[0].IcmpInParmProbs,
+ .output_off = offsetof(struct icmp_mib, IcmpOutParmProbs),
+ .input_off = offsetof(struct icmp_mib, IcmpInParmProbs),
.handler = icmp_unreach,
.error = 1,
},
/* TIMESTAMP (13) */
[13] = {
- .output = &icmp_statistics[0].IcmpOutTimestamps,
- .input = &icmp_statistics[0].IcmpInTimestamps,
+ .output_off = offsetof(struct icmp_mib, IcmpOutTimestamps),
+ .input_off = offsetof(struct icmp_mib, IcmpInTimestamps),
.handler = icmp_timestamp,
},
/* TIMESTAMP REPLY (14) */
[14] = {
- .output = &icmp_statistics[0].IcmpOutTimestampReps,
- .input = &icmp_statistics[0].IcmpInTimestampReps,
+ .output_off = offsetof(struct icmp_mib, IcmpOutTimestampReps),
+ .input_off = offsetof(struct icmp_mib, IcmpInTimestampReps),
.handler = icmp_discard,
},
/* INFO (15) */
[15] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].dummy,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, dummy),
.handler = icmp_discard,
},
/* INFO REPLY (16) */
[16] = {
- .output = &icmp_statistics[0].dummy,
- .input = &icmp_statistics[0].dummy,
+ .output_off = offsetof(struct icmp_mib, dummy),
+ .input_off = offsetof(struct icmp_mib, dummy),
.handler = icmp_discard,
},
/* ADDR MASK (17) */
[17] = {
- .output = &icmp_statistics[0].IcmpOutAddrMasks,
- .input = &icmp_statistics[0].IcmpInAddrMasks,
+ .output_off = offsetof(struct icmp_mib, IcmpOutAddrMasks),
+ .input_off = offsetof(struct icmp_mib, IcmpInAddrMasks),
.handler = icmp_address,
},
/* ADDR MASK REPLY (18) */
[18] = {
- .output = &icmp_statistics[0].IcmpOutAddrMaskReps,
- .input = &icmp_statistics[0].IcmpInAddrMaskReps,
+ .output_off = offsetof(struct icmp_mib, IcmpOutAddrMaskReps),
+ .input_off = offsetof(struct icmp_mib, IcmpInAddrMaskReps),
.handler = icmp_address_reply,
}
};
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 6c67950d4b4b..092f0a2e52fd 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -149,7 +149,7 @@
* SNMP management statistics
*/
-struct ip_mib ip_statistics[NR_CPUS*2];
+DEFINE_SNMP_STAT(struct ip_mib, ip_statistics);
/*
* Process Router Attention IP option
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 8869781ad6d6..2971828644e4 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -86,16 +86,21 @@ static struct file_operations sockstat_seq_fops = {
.release = single_release,
};
-static unsigned long fold_field(unsigned long *begin, int sz, int nr)
+static unsigned long
+fold_field(void *mib[], int nr)
{
unsigned long res = 0;
int i;
- sz /= sizeof(unsigned long);
-
for (i = 0; i < NR_CPUS; i++) {
- res += begin[2 * i * sz + nr];
- res += begin[(2 * i + 1) * sz + nr];
+ if (!cpu_possible(i))
+ continue;
+ res +=
+ *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
+ sizeof (unsigned long) * nr));
+ res +=
+ *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
+ sizeof (unsigned long) * nr));
}
return res;
}
@@ -118,8 +123,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
for (i = 0;
i < offsetof(struct ip_mib, __pad) / sizeof(unsigned long); i++)
seq_printf(seq, " %lu",
- fold_field((unsigned long *)ip_statistics,
- sizeof(struct ip_mib), i));
+ fold_field((void **) ip_statistics, i));
seq_printf(seq, "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds "
"InParmProbs InSrcQuenchs InRedirects InEchos "
@@ -132,8 +136,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
for (i = 0;
i < offsetof(struct icmp_mib, dummy) / sizeof(unsigned long); i++)
seq_printf(seq, " %lu",
- fold_field((unsigned long *)icmp_statistics,
- sizeof(struct icmp_mib), i));
+ fold_field((void **) icmp_statistics, i));
seq_printf(seq, "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens "
"PassiveOpens AttemptFails EstabResets CurrEstab "
@@ -142,17 +145,15 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
for (i = 0;
i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++)
seq_printf(seq, " %lu",
- fold_field((unsigned long *)tcp_statistics,
- sizeof(struct tcp_mib), i));
+ fold_field((void **) tcp_statistics, i));
seq_printf(seq, "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
"Udp:");
for (i = 0;
i < offsetof(struct udp_mib, __pad) / sizeof(unsigned long); i++)
- seq_printf(seq, " %lu",
- fold_field((unsigned long *)udp_statistics,
- sizeof(struct udp_mib), i));
+ seq_printf(seq, " %lu",
+ fold_field((void **) udp_statistics, i));
seq_putc(seq, '\n');
return 0;
@@ -206,10 +207,10 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
" TCPAbortFailed TCPMemoryPressures\n"
"TcpExt:");
for (i = 0;
- i < offsetof(struct linux_mib, __pad) / sizeof(unsigned long); i++)
- seq_printf(seq, " %lu",
- fold_field((unsigned long *)net_statistics,
- sizeof(struct linux_mib), i));
+ i < offsetof(struct linux_mib, __pad) / sizeof(unsigned long);
+ i++)
+ seq_printf(seq, " %lu",
+ fold_field((void **) net_statistics, i));
seq_putc(seq, '\n');
return 0;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9ca1db5863ad..eefd475dad53 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -196,7 +196,7 @@ static struct rt_hash_bucket *rt_hash_table;
static unsigned rt_hash_mask;
static int rt_hash_log;
-struct rt_cache_stat rt_cache_stat[NR_CPUS];
+struct rt_cache_stat *rt_cache_stat;
static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res);
@@ -318,24 +318,26 @@ static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int
int len = 0;
for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_possible(i))
+ continue;
len += sprintf(buffer+len, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
dst_entries,
- rt_cache_stat[i].in_hit,
- rt_cache_stat[i].in_slow_tot,
- rt_cache_stat[i].in_slow_mc,
- rt_cache_stat[i].in_no_route,
- rt_cache_stat[i].in_brd,
- rt_cache_stat[i].in_martian_dst,
- rt_cache_stat[i].in_martian_src,
-
- rt_cache_stat[i].out_hit,
- rt_cache_stat[i].out_slow_tot,
- rt_cache_stat[i].out_slow_mc,
-
- rt_cache_stat[i].gc_total,
- rt_cache_stat[i].gc_ignored,
- rt_cache_stat[i].gc_goal_miss,
- rt_cache_stat[i].gc_dst_overflow
+ per_cpu_ptr(rt_cache_stat, i)->in_hit,
+ per_cpu_ptr(rt_cache_stat, i)->in_slow_tot,
+ per_cpu_ptr(rt_cache_stat, i)->in_slow_mc,
+ per_cpu_ptr(rt_cache_stat, i)->in_no_route,
+ per_cpu_ptr(rt_cache_stat, i)->in_brd,
+ per_cpu_ptr(rt_cache_stat, i)->in_martian_dst,
+ per_cpu_ptr(rt_cache_stat, i)->in_martian_src,
+
+ per_cpu_ptr(rt_cache_stat, i)->out_hit,
+ per_cpu_ptr(rt_cache_stat, i)->out_slow_tot,
+ per_cpu_ptr(rt_cache_stat, i)->out_slow_mc,
+
+ per_cpu_ptr(rt_cache_stat, i)->gc_total,
+ per_cpu_ptr(rt_cache_stat, i)->gc_ignored,
+ per_cpu_ptr(rt_cache_stat, i)->gc_goal_miss,
+ per_cpu_ptr(rt_cache_stat, i)->gc_dst_overflow
);
}
@@ -591,11 +593,11 @@ static int rt_garbage_collect(void)
* do not make it too frequently.
*/
- rt_cache_stat[smp_processor_id()].gc_total++;
+ RT_CACHE_STAT_INC(gc_total);
if (now - last_gc < ip_rt_gc_min_interval &&
atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size) {
- rt_cache_stat[smp_processor_id()].gc_ignored++;
+ RT_CACHE_STAT_INC(gc_ignored);
goto out;
}
@@ -663,7 +665,7 @@ static int rt_garbage_collect(void)
We will not spin here for long time in any case.
*/
- rt_cache_stat[smp_processor_id()].gc_goal_miss++;
+ RT_CACHE_STAT_INC(gc_goal_miss);
if (expire == 0)
break;
@@ -682,7 +684,7 @@ static int rt_garbage_collect(void)
goto out;
if (net_ratelimit())
printk(KERN_WARNING "dst cache overflow\n");
- rt_cache_stat[smp_processor_id()].gc_dst_overflow++;
+ RT_CACHE_STAT_INC(gc_dst_overflow);
return 1;
work_done:
@@ -1400,7 +1402,7 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
if (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
rth->u.dst.input = ip_mr_input;
#endif
- rt_cache_stat[smp_processor_id()].in_slow_mc++;
+ RT_CACHE_STAT_INC(in_slow_mc);
in_dev_put(in_dev);
hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
@@ -1485,7 +1487,7 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
}
free_res = 1;
- rt_cache_stat[smp_processor_id()].in_slow_tot++;
+ RT_CACHE_STAT_INC(in_slow_tot);
#ifdef CONFIG_IP_ROUTE_NAT
/* Policy is applied before mapping destination,
@@ -1642,7 +1644,7 @@ brd_input:
}
flags |= RTCF_BROADCAST;
res.type = RTN_BROADCAST;
- rt_cache_stat[smp_processor_id()].in_brd++;
+ RT_CACHE_STAT_INC(in_brd);
local_input:
rth = dst_alloc(&ipv4_dst_ops);
@@ -1687,7 +1689,7 @@ local_input:
goto intern;
no_route:
- rt_cache_stat[smp_processor_id()].in_no_route++;
+ RT_CACHE_STAT_INC(in_no_route);
spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
res.type = RTN_UNREACHABLE;
goto local_input;
@@ -1696,7 +1698,7 @@ no_route:
* Do not cache martian addresses: they should be logged (RFC1812)
*/
martian_destination:
- rt_cache_stat[smp_processor_id()].in_martian_dst++;
+ RT_CACHE_STAT_INC(in_martian_dst);
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
printk(KERN_WARNING "martian destination %u.%u.%u.%u from "
@@ -1713,7 +1715,7 @@ e_nobufs:
martian_source:
- rt_cache_stat[smp_processor_id()].in_martian_src++;
+ RT_CACHE_STAT_INC(in_martian_src);
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
/*
@@ -1763,7 +1765,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
- rt_cache_stat[smp_processor_id()].in_hit++;
+ RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb->dst = (struct dst_entry*)rth;
return 0;
@@ -2060,7 +2062,7 @@ make_route:
rth->u.dst.output=ip_output;
- rt_cache_stat[smp_processor_id()].out_slow_tot++;
+ RT_CACHE_STAT_INC(out_slow_tot);
if (flags & RTCF_LOCAL) {
rth->u.dst.input = ip_local_deliver;
@@ -2070,7 +2072,7 @@ make_route:
rth->rt_spec_dst = fl.fl4_src;
if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) {
rth->u.dst.output = ip_mc_output;
- rt_cache_stat[smp_processor_id()].out_slow_mc++;
+ RT_CACHE_STAT_INC(out_slow_mc);
}
#ifdef CONFIG_IP_MROUTE
if (res.type == RTN_MULTICAST) {
@@ -2129,7 +2131,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
- rt_cache_stat[smp_processor_id()].out_hit++;
+ RT_CACHE_STAT_INC(out_hit);
rcu_read_unlock();
*rp = rth;
return 0;
@@ -2650,6 +2652,11 @@ int __init ip_rt_init(void)
ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
ip_rt_max_size = (rt_hash_mask + 1) * 16;
+ rt_cache_stat = kmalloc_percpu(sizeof (struct rt_cache_stat),
+ GFP_KERNEL);
+ if (!rt_cache_stat)
+ goto out_enomem1;
+
devinet_init();
ip_fib_init();
@@ -2675,6 +2682,8 @@ int __init ip_rt_init(void)
out:
return rc;
out_enomem:
+ kfree_percpu(rt_cache_stat);
+out_enomem1:
rc = -ENOMEM;
goto out;
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 82e9529c1a57..2351b2faf180 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -258,13 +258,15 @@
#include <net/icmp.h>
#include <net/tcp.h>
#include <net/xfrm.h>
+#include <net/ip.h>
+
#include <asm/uaccess.h>
#include <asm/ioctls.h>
int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
-struct tcp_mib tcp_statistics[NR_CPUS * 2];
+DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
kmem_cache_t *tcp_openreq_cachep;
kmem_cache_t *tcp_bucket_cachep;
@@ -1395,8 +1397,7 @@ static void tcp_prequeue_process(struct sock *sk)
struct sk_buff *skb;
struct tcp_opt *tp = tcp_sk(sk);
- net_statistics[smp_processor_id() * 2 + 1].TCPPrequeued +=
- skb_queue_len(&tp->ucopy.prequeue);
+ NET_ADD_STATS_USER(TCPPrequeued, skb_queue_len(&tp->ucopy.prequeue));
/* RX process wants to run with disabled BHs, though it is not
* necessary */
@@ -1676,7 +1677,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
/* __ Restore normal policy in scheduler __ */
if ((chunk = len - tp->ucopy.len) != 0) {
- net_statistics[smp_processor_id() * 2 + 1].TCPDirectCopyFromBacklog += chunk;
+ NET_ADD_STATS_USER(TCPDirectCopyFromBacklog, chunk);
len -= chunk;
copied += chunk;
}
@@ -1687,7 +1688,7 @@ do_prequeue:
tcp_prequeue_process(sk);
if ((chunk = len - tp->ucopy.len) != 0) {
- net_statistics[smp_processor_id() * 2 + 1].TCPDirectCopyFromPrequeue += chunk;
+ NET_ADD_STATS_USER(TCPDirectCopyFromPrequeue, chunk);
len -= chunk;
copied += chunk;
}
@@ -1770,7 +1771,7 @@ skip_copy:
tcp_prequeue_process(sk);
if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {
- net_statistics[smp_processor_id() * 2 + 1].TCPDirectCopyFromPrequeue += chunk;
+ NET_ADD_STATS_USER(TCPDirectCopyFromPrequeue, chunk);
len -= chunk;
copied += chunk;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3d3b0f518995..fad2dc973a6b 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3043,8 +3043,8 @@ static int tcp_prune_queue(struct sock *sk)
/* First, purge the out_of_order queue. */
if (skb_queue_len(&tp->out_of_order_queue)) {
- net_statistics[smp_processor_id() * 2].OfoPruned +=
- skb_queue_len(&tp->out_of_order_queue);
+ NET_ADD_STATS_BH(OfoPruned,
+ skb_queue_len(&tp->out_of_order_queue));
__skb_queue_purge(&tp->out_of_order_queue);
/* Reset SACK state. A conforming SACK implementation will
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b660f78ab2fa..aaa16eb403dc 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -464,7 +464,7 @@ static void SMP_TIMER_NAME(tcp_twkill)(unsigned long dummy)
if ((tcp_tw_count -= killed) != 0)
mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD);
- net_statistics[smp_processor_id()*2].TimeWaited += killed;
+ NET_ADD_STATS_BH(TimeWaited, killed);
out:
spin_unlock(&tw_death_lock);
}
@@ -628,7 +628,7 @@ void SMP_TIMER_NAME(tcp_twcal_tick)(unsigned long dummy)
out:
if ((tcp_tw_count -= killed) == 0)
del_timer(&tcp_tw_timer);
- net_statistics[smp_processor_id()*2].TimeWaitKilled += killed;
+ NET_ADD_STATS_BH(TimeWaitKilled, killed);
spin_unlock(&tw_death_lock);
}
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 619e89ea2c49..fc2102496536 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -237,7 +237,8 @@ static void tcp_delack_timer(unsigned long data)
if (skb_queue_len(&tp->ucopy.prequeue)) {
struct sk_buff *skb;
- net_statistics[smp_processor_id()*2].TCPSchedulerFailed += skb_queue_len(&tp->ucopy.prequeue);
+ NET_ADD_STATS_BH(TCPSchedulerFailed,
+ skb_queue_len(&tp->ucopy.prequeue));
while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
sk->backlog_rcv(sk, skb);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ca07a67c2bc0..02d04030d901 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -110,7 +110,7 @@
* Snmp MIB for the UDP layer
*/
-struct udp_mib udp_statistics[NR_CPUS*2];
+DEFINE_SNMP_STAT(struct udp_mib, udp_statistics);
struct sock *udp_hash[UDP_HTABLE_SIZE];
rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 86cbad545ca8..309be737569f 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -619,6 +619,81 @@ inet6_unregister_protosw(struct inet_protosw *p)
inet_unregister_protosw(p);
}
+static int __init init_ipv6_mibs(void)
+{
+ int i;
+
+ ipv6_statistics[0] = kmalloc_percpu(sizeof (struct ipv6_mib),
+ GFP_KERNEL);
+ if (!ipv6_statistics[0])
+ goto err_ip_mib0;
+ ipv6_statistics[1] = kmalloc_percpu(sizeof (struct ipv6_mib),
+ GFP_KERNEL);
+ if (!ipv6_statistics[1])
+ goto err_ip_mib1;
+
+ icmpv6_statistics[0] = kmalloc_percpu(sizeof (struct icmpv6_mib),
+ GFP_KERNEL);
+ if (!icmpv6_statistics[0])
+ goto err_icmp_mib0;
+ icmpv6_statistics[1] = kmalloc_percpu(sizeof (struct icmpv6_mib),
+ GFP_KERNEL);
+ if (!icmpv6_statistics[1])
+ goto err_icmp_mib1;
+
+ udp_stats_in6[0] = kmalloc_percpu(sizeof (struct udp_mib),
+ GFP_KERNEL);
+ if (!udp_stats_in6[0])
+ goto err_udp_mib0;
+ udp_stats_in6[1] = kmalloc_percpu(sizeof (struct udp_mib),
+ GFP_KERNEL);
+ if (!udp_stats_in6[1])
+ goto err_udp_mib1;
+
+ /* Zero all percpu versions of the mibs */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_possible(i)) {
+ memset(per_cpu_ptr(ipv6_statistics[0], i), 0,
+ sizeof (struct ipv6_mib));
+ memset(per_cpu_ptr(ipv6_statistics[1], i), 0,
+ sizeof (struct ipv6_mib));
+ memset(per_cpu_ptr(icmpv6_statistics[0], i), 0,
+ sizeof (struct icmpv6_mib));
+ memset(per_cpu_ptr(icmpv6_statistics[1], i), 0,
+ sizeof (struct icmpv6_mib));
+ memset(per_cpu_ptr(udp_stats_in6[0], i), 0,
+ sizeof (struct udp_mib));
+ memset(per_cpu_ptr(udp_stats_in6[1], i), 0,
+ sizeof (struct udp_mib));
+ }
+ }
+ return 0;
+
+err_udp_mib1:
+ kfree_percpu(udp_stats_in6[0]);
+err_udp_mib0:
+ kfree_percpu(icmpv6_statistics[1]);
+err_icmp_mib1:
+ kfree_percpu(icmpv6_statistics[0]);
+err_icmp_mib0:
+ kfree_percpu(ipv6_statistics[1]);
+err_ip_mib1:
+ kfree_percpu(ipv6_statistics[0]);
+err_ip_mib0:
+ return -ENOMEM;
+
+}
+
+static void __exit cleanup_ipv6_mibs(void)
+{
+ kfree_percpu(ipv6_statistics[0]);
+ kfree_percpu(ipv6_statistics[1]);
+ kfree_percpu(icmpv6_statistics[0]);
+ kfree_percpu(icmpv6_statistics[1]);
+ kfree_percpu(udp_stats_in6[0]);
+ kfree_percpu(udp_stats_in6[1]);
+}
+
static int __init inet6_init(void)
{
struct sk_buff *dummy_skb;
@@ -668,6 +743,11 @@ static int __init inet6_init(void)
* be able to create sockets. (?? is this dangerous ??)
*/
(void) sock_register(&inet6_family_ops);
+
+ /* Initialise ipv6 mibs */
+ err = init_ipv6_mibs();
+ if (err)
+ goto init_mib_fail;
/*
* ipngwg API draft makes clear that the correct semantics
@@ -735,6 +815,8 @@ icmp_fail:
#if defined(MODULE) && defined(CONFIG_SYSCTL)
ipv6_sysctl_unregister();
#endif
+ cleanup_ipv6_mibs();
+init_mib_fail:
return err;
}
module_init(inet6_init);
@@ -765,6 +847,7 @@ static void inet6_exit(void)
#ifdef CONFIG_SYSCTL
ipv6_sysctl_unregister();
#endif
+ cleanup_ipv6_mibs();
}
module_exit(inet6_exit);
#endif /* MODULE */
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index db535ea0801f..b5f53a7ce839 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -65,7 +65,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];
+DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
/*
* ICMP socket for flow control.
@@ -377,7 +377,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
MSG_DONTWAIT);
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
- (&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++;
+ ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-1]++;
ICMP6_INC_STATS_BH(Icmp6OutMsgs);
out:
icmpv6_xmit_unlock();
@@ -539,9 +539,9 @@ static int icmpv6_rcv(struct sk_buff *skb)
type = hdr->icmp6_type;
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
- (&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
+ ICMP6_STATS_PTR_BH(Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
- (&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
+ ICMP6_STATS_PTR_BH(Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
switch (type) {
case ICMPV6_ECHO_REQUEST:
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 0587ca8f80fd..a62a73c9fa14 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -51,7 +51,7 @@
#include <asm/uaccess.h>
-struct ipv6_mib ipv6_statistics[NR_CPUS*2];
+DEFINE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
static struct packet_type ipv6_packet_type =
{
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index ae5f80dd9aa7..9ce2c1d8857b 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -59,11 +59,11 @@ int afinet6_get_info(char *buffer, char **start, off_t offset, int length)
static struct snmp6_item
{
char *name;
- unsigned long *ptr;
- int mibsize;
+ void **mib;
+ int offset;
} snmp6_list[] = {
/* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */
-#define SNMP6_GEN(x) { #x , &ipv6_statistics[0].x, sizeof(struct ipv6_mib)/sizeof(unsigned long) }
+#define SNMP6_GEN(x) { #x , (void **)ipv6_statistics, offsetof(struct ipv6_mib, x) }
SNMP6_GEN(Ip6InReceives),
SNMP6_GEN(Ip6InHdrErrors),
SNMP6_GEN(Ip6InTooBigErrors),
@@ -97,7 +97,7 @@ static struct snmp6_item
OutRouterAdvertisements too.
OutGroupMembQueries too.
*/
-#define SNMP6_GEN(x) { #x , &icmpv6_statistics[0].x, sizeof(struct icmpv6_mib)/sizeof(unsigned long) }
+#define SNMP6_GEN(x) { #x , (void **)icmpv6_statistics, offsetof(struct icmpv6_mib, x) }
SNMP6_GEN(Icmp6InMsgs),
SNMP6_GEN(Icmp6InErrors),
SNMP6_GEN(Icmp6InDestUnreachs),
@@ -127,7 +127,7 @@ static struct snmp6_item
SNMP6_GEN(Icmp6OutGroupMembResponses),
SNMP6_GEN(Icmp6OutGroupMembReductions),
#undef SNMP6_GEN
-#define SNMP6_GEN(x) { "Udp6" #x , &udp_stats_in6[0].Udp##x, sizeof(struct udp_mib)/sizeof(unsigned long) }
+#define SNMP6_GEN(x) { "Udp6" #x , (void **)udp_stats_in6, offsetof(struct udp_mib, Udp##x) }
SNMP6_GEN(InDatagrams),
SNMP6_GEN(NoPorts),
SNMP6_GEN(InErrors),
@@ -135,17 +135,23 @@ static struct snmp6_item
#undef SNMP6_GEN
};
-static unsigned long fold_field(unsigned long *ptr, int size)
+static unsigned long
+fold_field(void *mib[], int offt)
{
- unsigned long res = 0;
- int i;
-
- for (i=0; i<NR_CPUS; i++) {
- res += ptr[2*i*size];
- res += ptr[(2*i+1)*size];
- }
-
- return res;
+ unsigned long res = 0;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_possible(i))
+ continue;
+ res +=
+ *((unsigned long *) (((void *)per_cpu_ptr(mib[0], i)) +
+ offt));
+ res +=
+ *((unsigned long *) (((void *)per_cpu_ptr(mib[1], i)) +
+ offt));
+ }
+ return res;
}
int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length)
@@ -155,7 +161,7 @@ int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length)
for (i=0; i<sizeof(snmp6_list)/sizeof(snmp6_list[0]); i++)
len += sprintf(buffer+len, "%-32s\t%ld\n", snmp6_list[i].name,
- fold_field(snmp6_list[i].ptr, snmp6_list[i].mibsize));
+ fold_field(snmp6_list[i].mib, snmp6_list[i].offset));
len -= offset;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index df8e90da19c4..bfb16cd89a0b 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -51,7 +51,7 @@
#include <net/checksum.h>
-struct udp_mib udp_stats_in6[NR_CPUS*2];
+DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
/* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put
* XXX it somewhere common. -DaveM
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index fde475e70359..2a733bae42a3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -60,7 +60,7 @@
/* Global data structures. */
sctp_protocol_t sctp_proto;
struct proc_dir_entry *proc_net_sctp;
-struct sctp_mib sctp_statistics[NR_CPUS * 2];
+DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
/* This is the global socket data structure used for responding to
* the Out-of-the-blue (OOTB) packets. A control sock will be created
@@ -653,6 +653,40 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
return 1;
}
+static int __init init_sctp_mibs(void)
+{
+ int i;
+
+ sctp_statistics[0] = kmalloc_percpu(sizeof (struct sctp_mib),
+ GFP_KERNEL);
+ if (!sctp_statistics[0])
+ return -ENOMEM;
+ sctp_statistics[1] = kmalloc_percpu(sizeof (struct sctp_mib),
+ GFP_KERNEL);
+ if (!sctp_statistics[1]) {
+ kfree_percpu(sctp_statistics[0]);
+ return -ENOMEM;
+ }
+
+ /* Zero all percpu versions of the mibs */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_possible(i)) {
+ memset(per_cpu_ptr(sctp_statistics[0], i), 0,
+ sizeof (struct sctp_mib));
+ memset(per_cpu_ptr(sctp_statistics[1], i), 0,
+ sizeof (struct sctp_mib));
+ }
+ }
+ return 0;
+
+}
+
+static void cleanup_sctp_mibs(void)
+{
+ kfree_percpu(sctp_statistics[0]);
+ kfree_percpu(sctp_statistics[1]);
+}
+
/* Initialize the universe into something sensible. */
int sctp_init(void)
{
@@ -666,6 +700,11 @@ int sctp_init(void)
/* Add SCTP to inetsw linked list. */
inet_register_protosw(&sctp_protosw);
+ /* Allocate and initialise sctp mibs. */
+ status = init_sctp_mibs();
+ if (status)
+ goto err_init_mibs;
+
/* Initialize proc fs directory. */
sctp_proc_init();
@@ -805,6 +844,8 @@ err_ehash_alloc:
err_ahash_alloc:
sctp_dbg_objcnt_exit();
sctp_proc_exit();
+ cleanup_sctp_mibs();
+err_init_mibs:
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_protosw);
return status;
@@ -836,6 +877,7 @@ void sctp_exit(void)
sctp_dbg_objcnt_exit();
sctp_proc_exit();
+ cleanup_sctp_mibs();
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_protosw);
diff --git a/net/socket.c b/net/socket.c
index e8b80586132a..b17a1944444a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -75,7 +75,6 @@
#include <linux/cache.h>
#include <linux/module.h>
#include <linux/highmem.h>
-#include <linux/wireless.h>
#include <linux/divert.h>
#include <linux/mount.h>
@@ -189,10 +188,7 @@ static __inline__ void net_family_read_unlock(void)
* Statistics counters of the socket lists
*/
-static union {
- int counter;
- char __pad[SMP_CACHE_BYTES];
-} sockets_in_use[NR_CPUS] __cacheline_aligned = {{0}};
+static DEFINE_PER_CPU(int, sockets_in_use) = 0;
/*
* Support routines. Move socket addresses back and forth across the kernel/user
@@ -475,7 +471,8 @@ struct socket *sock_alloc(void)
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
- sockets_in_use[smp_processor_id()].counter++;
+ get_cpu_var(sockets_in_use)++;
+ put_cpu_var(sockets_in_use);
return sock;
}
@@ -511,7 +508,8 @@ void sock_release(struct socket *sock)
if (sock->fasync_list)
printk(KERN_ERR "sock_release: fasync list not empty!\n");
- sockets_in_use[smp_processor_id()].counter--;
+ get_cpu_var(sockets_in_use)--;
+ put_cpu_var(sockets_in_use);
if (!sock->file) {
iput(SOCK_INODE(sock));
return;
@@ -1851,7 +1849,7 @@ void socket_seq_show(struct seq_file *seq)
int counter = 0;
for (cpu = 0; cpu < NR_CPUS; cpu++)
- counter += sockets_in_use[cpu].counter;
+ counter += per_cpu(sockets_in_use, cpu);
/* It can be negative, by the way. 8) */
if (counter < 0)