From 2e5aa86609ec1cf37bcc204fd7ba6c24c2f49fec Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 23 Jul 2013 17:38:38 -0400 Subject: lsm: split the xfrm_state_alloc_security() hook implementation The xfrm_state_alloc_security() LSM hook implementation is really a multiplexed hook with two different behaviors depending on the arguments passed to it by the caller. This patch splits the LSM hook implementation into two new hook implementations, which match the LSM hooks in the rest of the kernel: * xfrm_state_alloc * xfrm_state_alloc_acquire Also included in this patch are the necessary changes to the SELinux code; no other LSMs are affected. Signed-off-by: Paul Moore Signed-off-by: Eric Paris --- include/linux/security.h | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/security.h b/include/linux/security.h index 4686491852a7..e5a5e8a41e55 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1039,17 +1039,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * @xfrm_policy_delete_security: * @ctx contains the xfrm_sec_ctx. * Authorize deletion of xp->security. - * @xfrm_state_alloc_security: + * @xfrm_state_alloc: * @x contains the xfrm_state being added to the Security Association * Database by the XFRM system. * @sec_ctx contains the security context information being provided by * the user-level SA generation program (e.g., setkey or racoon). - * @secid contains the secid from which to take the mls portion of the context. * Allocate a security structure to the x->security field; the security * field is initialized to NULL when the xfrm_state is allocated. Set the - * context to correspond to either sec_ctx or polsec, with the mls portion - * taken from secid in the latter case. - * Return 0 if operation was successful (memory to allocate, legal context). + * context to correspond to sec_ctx. Return 0 if operation was successful + * (memory to allocate, legal context). + * @xfrm_state_alloc_acquire: + * @x contains the xfrm_state being added to the Security Association + * Database by the XFRM system. + * @polsec contains the policy's security context. + * @secid contains the secid from which to take the mls portion of the + * context. + * Allocate a security structure to the x->security field; the security + * field is initialized to NULL when the xfrm_state is allocated. Set the + * context to correspond to secid. Return 0 if operation was successful + * (memory to allocate, legal context). * @xfrm_state_free_security: * @x contains the xfrm_state. * Deallocate x->security. @@ -1651,9 +1659,11 @@ struct security_operations { int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); - int (*xfrm_state_alloc_security) (struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx, - u32 secid); + int (*xfrm_state_alloc) (struct xfrm_state *x, + struct xfrm_user_sec_ctx *sec_ctx); + int (*xfrm_state_alloc_acquire) (struct xfrm_state *x, + struct xfrm_sec_ctx *polsec, + u32 secid); void (*xfrm_state_free_security) (struct xfrm_state *x); int (*xfrm_state_delete_security) (struct xfrm_state *x); int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); -- cgit From 1a6b69b6548cd0dd82549393f30dd982ceeb79d2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 12 Apr 2012 01:40:31 -0400 Subject: ARM: gic: add CPU migration support This is required by the big.LITTLE switcher code. The gic_migrate_target() changes the CPU interface mapping for the current CPU to redirect SGIs to the specified interface, and it also updates the target CPU for each interrupts to that CPU interface if they were targeting the current interface. Finally, pending SGIs for the current CPU are forwarded to the new interface. Because Linux does not use it, the SGI source information for the forwarded SGIs is not preserved. Neither is the source information for the SGIs sent by the current CPU to other CPUs adjusted to match the new CPU interface mapping. The required registers are banked so only the target CPU could do it. Signed-off-by: Nicolas Pitre --- drivers/irqchip/irq-gic.c | 87 +++++++++++++++++++++++++++++++++++++++-- include/linux/irqchip/arm-gic.h | 4 ++ 2 files changed, 88 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index ee7c50312066..268874ac75e6 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -253,10 +253,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) return -EINVAL; + raw_spin_lock(&irq_controller_lock); mask = 0xff << shift; bit = gic_cpu_map[cpu] << shift; - - raw_spin_lock(&irq_controller_lock); val = readl_relaxed(reg) & ~mask; writel_relaxed(val | bit, reg); raw_spin_unlock(&irq_controller_lock); @@ -646,7 +645,9 @@ static void __init gic_pm_init(struct gic_chip_data *gic) void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { int cpu; - unsigned long map = 0; + unsigned long flags, map = 0; + + raw_spin_lock_irqsave(&irq_controller_lock, flags); /* Convert our logical CPU mask into a physical one. */ for_each_cpu(cpu, mask) @@ -660,6 +661,86 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) /* this always happens on GIC0 */ writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); + + raw_spin_unlock_irqrestore(&irq_controller_lock, flags); +} +#endif + +#ifdef CONFIG_BL_SWITCHER +/* + * gic_migrate_target - migrate IRQs to another CPU interface + * + * @new_cpu_id: the CPU target ID to migrate IRQs to + * + * Migrate all peripheral interrupts with a target matching the current CPU + * to the interface corresponding to @new_cpu_id. The CPU interface mapping + * is also updated. Targets to other CPU interfaces are unchanged. + * This must be called with IRQs locally disabled. + */ +void gic_migrate_target(unsigned int new_cpu_id) +{ + unsigned int cur_cpu_id, gic_irqs, gic_nr = 0; + void __iomem *dist_base; + int i, ror_val, cpu = smp_processor_id(); + u32 val, cur_target_mask, active_mask; + + if (gic_nr >= MAX_GIC_NR) + BUG(); + + dist_base = gic_data_dist_base(&gic_data[gic_nr]); + if (!dist_base) + return; + gic_irqs = gic_data[gic_nr].gic_irqs; + + cur_cpu_id = __ffs(gic_cpu_map[cpu]); + cur_target_mask = 0x01010101 << cur_cpu_id; + ror_val = (cur_cpu_id - new_cpu_id) & 31; + + raw_spin_lock(&irq_controller_lock); + + /* Update the target interface for this logical CPU */ + gic_cpu_map[cpu] = 1 << new_cpu_id; + + /* + * Find all the peripheral interrupts targetting the current + * CPU interface and migrate them to the new CPU interface. + * We skip DIST_TARGET 0 to 7 as they are read-only. + */ + for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) { + val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4); + active_mask = val & cur_target_mask; + if (active_mask) { + val &= ~active_mask; + val |= ror32(active_mask, ror_val); + writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4); + } + } + + raw_spin_unlock(&irq_controller_lock); + + /* + * Now let's migrate and clear any potential SGIs that might be + * pending for us (cur_cpu_id). Since GIC_DIST_SGI_PENDING_SET + * is a banked register, we can only forward the SGI using + * GIC_DIST_SOFTINT. The original SGI source is lost but Linux + * doesn't use that information anyway. + * + * For the same reason we do not adjust SGI source information + * for previously sent SGIs by us to other CPUs either. + */ + for (i = 0; i < 16; i += 4) { + int j; + val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i); + if (!val) + continue; + writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i); + for (j = i; j < i + 4; j++) { + if (val & 0xff) + writel_relaxed((1 << (new_cpu_id + 16)) | j, + dist_base + GIC_DIST_SOFTINT); + val >>= 8; + } + } } #endif diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 3e203eb23cc7..40bfcac95940 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -31,6 +31,8 @@ #define GIC_DIST_TARGET 0x800 #define GIC_DIST_CONFIG 0xc00 #define GIC_DIST_SOFTINT 0xf00 +#define GIC_DIST_SGI_PENDING_CLEAR 0xf10 +#define GIC_DIST_SGI_PENDING_SET 0xf20 #define GICH_HCR 0x0 #define GICH_VTR 0x4 @@ -73,6 +75,8 @@ static inline void gic_init(unsigned int nr, int start, gic_init_bases(nr, start, dist, cpu, 0, NULL); } +void gic_migrate_target(unsigned int new_cpu_id); + #endif /* __ASSEMBLY */ #endif -- cgit From ed96762e3241f57aa812977cf1920d3ee0363f4d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 5 Jul 2012 21:33:26 -0400 Subject: ARM: bL_switcher: do not hardcode GIC IDs in the code Currently, GIC IDs are hardcoded making the code dependent on the 4+4 b.L configuration. Let's allow for GIC IDs to be discovered upon switcher initialization to support other b.L configurations such as the 1+1 one, or 2+3 as on the VExpress TC2. Signed-off-by: Nicolas Pitre --- arch/arm/common/bL_switcher.c | 14 +++++++++++++- drivers/irqchip/irq-gic.c | 21 +++++++++++++++++++++ include/linux/irqchip/arm-gic.h | 1 + 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index 50e95d894e35..1c2e5bcfb1f7 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c @@ -110,6 +110,8 @@ static int bL_switchpoint(unsigned long _arg) * Generic switcher interface */ +static unsigned int bL_gic_id[MAX_CPUS_PER_CLUSTER][MAX_NR_CLUSTERS]; + /* * bL_switch_to - Switch to a specific cluster for the current CPU * @new_cluster_id: the ID of the cluster to switch to. @@ -159,7 +161,7 @@ static int bL_switch_to(unsigned int new_cluster_id) this_cpu = smp_processor_id(); /* redirect GIC's SGIs to our counterpart */ - gic_migrate_target(cpuid + ib_cluster*4); + gic_migrate_target(bL_gic_id[cpuid][ib_cluster]); /* * Raise a SGI on the inbound CPU to make sure it doesn't stall @@ -332,6 +334,16 @@ static int __init bL_switcher_halve_cpus(void) cluster = (cpu_logical_map(i) >> 8) & 0xff; if (cpumask_test_cpu(cpu, &common_mask)) { + /* Let's take note of the GIC ID for this CPU */ + int gic_id = gic_get_cpu_id(i); + if (gic_id < 0) { + pr_err("%s: bad GIC ID for CPU %d\n", __func__, i); + return -EINVAL; + } + bL_gic_id[cpu][cluster] = gic_id; + pr_info("GIC ID for CPU %u cluster %u is %u\n", + cpu, cluster, gic_id); + /* * We keep only those logical CPUs which number * is equal to their physical CPU number. This is diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 268874ac75e6..3862cb54c714 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -667,6 +667,27 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) #endif #ifdef CONFIG_BL_SWITCHER +/* + * gic_get_cpu_id - get the CPU interface ID for the specified CPU + * + * @cpu: the logical CPU number to get the GIC ID for. + * + * Return the CPU interface ID for the given logical CPU number, + * or -1 if the CPU number is too large or the interface ID is + * unknown (more than one bit set). + */ +int gic_get_cpu_id(unsigned int cpu) +{ + unsigned int cpu_bit; + + if (cpu >= NR_GIC_CPU_IF) + return -1; + cpu_bit = gic_cpu_map[cpu]; + if (cpu_bit & (cpu_bit - 1)) + return -1; + return __ffs(cpu_bit); +} + /* * gic_migrate_target - migrate IRQs to another CPU interface * diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 40bfcac95940..2d7d47e8dfaf 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -75,6 +75,7 @@ static inline void gic_init(unsigned int nr, int start, gic_init_bases(nr, start, dist, cpu, 0, NULL); } +int gic_get_cpu_id(unsigned int cpu); void gic_migrate_target(unsigned int new_cpu_id); #endif /* __ASSEMBLY */ -- cgit From 87d8b9eb7eb6669aad6435a51e9862362141ba76 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:21:14 -0700 Subject: clocksource: Extract max nsec calculation into separate function We need to calculate the same number in the clocksource code and the sched_clock code, so extract this code into its own function. We also drop the min_t and just use min() because the two types are the same. Signed-off-by: Stephen Boyd Signed-off-by: John Stultz --- include/linux/clocksource.h | 2 ++ kernel/time/clocksource.c | 45 ++++++++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index dbbf8aa7731b..67301a405712 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -292,6 +292,8 @@ extern void clocksource_resume(void); extern struct clocksource * __init __weak clocksource_default_clock(void); extern void clocksource_mark_unstable(struct clocksource *cs); +extern u64 +clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask); extern void clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 50a8736757f3..637a14af6c21 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -537,40 +537,55 @@ static u32 clocksource_max_adjustment(struct clocksource *cs) } /** - * clocksource_max_deferment - Returns max time the clocksource can be deferred - * @cs: Pointer to clocksource - * + * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) + * @maxadj: maximum adjustment value to mult (~11%) + * @mask: bitmask for two's complement subtraction of non 64 bit counters */ -static u64 clocksource_max_deferment(struct clocksource *cs) +u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask) { u64 max_nsecs, max_cycles; /* * Calculate the maximum number of cycles that we can pass to the * cyc2ns function without overflowing a 64-bit signed result. The - * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj) + * maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj) * which is equivalent to the below. - * max_cycles < (2^63)/(cs->mult + cs->maxadj) - * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj))) - * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj)) - * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj)) - * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj)) + * max_cycles < (2^63)/(mult + maxadj) + * max_cycles < 2^(log2((2^63)/(mult + maxadj))) + * max_cycles < 2^(log2(2^63) - log2(mult + maxadj)) + * max_cycles < 2^(63 - log2(mult + maxadj)) + * max_cycles < 1 << (63 - log2(mult + maxadj)) * Please note that we add 1 to the result of the log2 to account for * any rounding errors, ensure the above inequality is satisfied and * no overflow will occur. */ - max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1)); + max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1)); /* * The actual maximum number of cycles we can defer the clocksource is - * determined by the minimum of max_cycles and cs->mask. + * determined by the minimum of max_cycles and mask. * Note: Here we subtract the maxadj to make sure we don't sleep for * too long if there's a large negative adjustment. */ - max_cycles = min_t(u64, max_cycles, (u64) cs->mask); - max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj, - cs->shift); + max_cycles = min(max_cycles, mask); + max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift); + + return max_nsecs; +} + +/** + * clocksource_max_deferment - Returns max time the clocksource can be deferred + * @cs: Pointer to clocksource + * + */ +static u64 clocksource_max_deferment(struct clocksource *cs) +{ + u64 max_nsecs; + max_nsecs = clocks_calc_max_nsecs(cs->mult, cs->shift, cs->maxadj, + cs->mask); /* * To ensure that the clocksource does not wrap whilst we are idle, * limit the time the clocksource can be deferred by 12.5%. Please -- cgit From e7e3ff1bfe9c42ee31172e9afdc0383a9e595e29 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:21:17 -0700 Subject: sched_clock: Add support for >32 bit sched_clock The ARM architected system counter has at least 56 usable bits. Add support for counters with more than 32 bits to the generic sched_clock implementation so we can increase the time between wakeups due to dealing with wrap-around on these devices while benefiting from the irqtime accounting and suspend/resume handling that the generic sched_clock code already has. On my system using 56 bits over 32 bits changes the wraparound time from a few minutes to an hour. For faster running counters (GHz range) this is even more important because we may not be able to execute the timer in time to deal with the wraparound if only 32 bits are used. We choose a maxsec value of 3600 seconds because we assume no system will go idle for more than an hour. In the future we may need to increase this value. Note: All users should switch over to the 64-bit read function so we can remove setup_sched_clock() in favor of sched_clock_register(). Cc: Russell King Signed-off-by: Stephen Boyd Signed-off-by: John Stultz --- include/linux/sched_clock.h | 2 ++ kernel/time/sched_clock.c | 46 +++++++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h index fa7922c80a41..eca7abeb86fc 100644 --- a/include/linux/sched_clock.h +++ b/include/linux/sched_clock.h @@ -15,6 +15,8 @@ static inline void sched_clock_postinit(void) { } #endif extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); +extern void sched_clock_register(u64 (*read)(void), int bits, + unsigned long rate); extern unsigned long long (*sched_clock_func)(void); diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index c018ffc59937..f388baeaf2b6 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -16,11 +16,12 @@ #include #include #include +#include struct clock_data { ktime_t wrap_kt; u64 epoch_ns; - u32 epoch_cyc; + u64 epoch_cyc; seqcount_t seq; unsigned long rate; u32 mult; @@ -37,14 +38,25 @@ static struct clock_data cd = { .mult = NSEC_PER_SEC / HZ, }; -static u32 __read_mostly sched_clock_mask = 0xffffffff; +static u64 __read_mostly sched_clock_mask; -static u32 notrace jiffy_sched_clock_read(void) +static u64 notrace jiffy_sched_clock_read(void) { - return (u32)(jiffies - INITIAL_JIFFIES); + /* + * We don't need to use get_jiffies_64 on 32-bit arches here + * because we register with BITS_PER_LONG + */ + return (u64)(jiffies - INITIAL_JIFFIES); +} + +static u32 __read_mostly (*read_sched_clock_32)(void); + +static u64 notrace read_sched_clock_32_wrapper(void) +{ + return read_sched_clock_32(); } -static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read; +static u64 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read; static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift) { @@ -54,8 +66,8 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift) static unsigned long long notrace sched_clock_32(void) { u64 epoch_ns; - u32 epoch_cyc; - u32 cyc; + u64 epoch_cyc; + u64 cyc; unsigned long seq; if (cd.suspended) @@ -78,7 +90,7 @@ static unsigned long long notrace sched_clock_32(void) static void notrace update_sched_clock(void) { unsigned long flags; - u32 cyc; + u64 cyc; u64 ns; cyc = read_sched_clock(); @@ -101,7 +113,8 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt) return HRTIMER_RESTART; } -void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) +void __init sched_clock_register(u64 (*read)(void), int bits, + unsigned long rate) { unsigned long r; u64 res, wrap; @@ -110,14 +123,13 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) if (cd.rate > rate) return; - BUG_ON(bits > 32); WARN_ON(!irqs_disabled()); read_sched_clock = read; - sched_clock_mask = (1 << bits) - 1; + sched_clock_mask = CLOCKSOURCE_MASK(bits); cd.rate = rate; /* calculate the mult/shift to convert counter ticks to ns. */ - clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); + clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600); r = rate; if (r >= 4000000) { @@ -130,7 +142,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) r_unit = ' '; /* calculate how many ns until we wrap */ - wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift); + wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask); cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3)); /* calculate the ns resolution of this counter */ @@ -152,6 +164,12 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) pr_debug("Registered %pF as sched_clock source\n", read); } +void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) +{ + read_sched_clock_32 = read; + sched_clock_register(read_sched_clock_32_wrapper, bits, rate); +} + unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32; unsigned long long notrace sched_clock(void) @@ -166,7 +184,7 @@ void __init sched_clock_postinit(void) * make it the final one one. */ if (read_sched_clock == jiffy_sched_clock_read) - setup_sched_clock(jiffy_sched_clock_read, 32, HZ); + sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ); update_sched_clock(); -- cgit From aba8269588301f7778bea811d6f7ec74c2e37279 Mon Sep 17 00:00:00 2001 From: Fan Du Date: Wed, 28 Aug 2013 15:09:40 +0800 Subject: {ipv4,xfrm}: Introduce xfrm_tunnel_notifier for xfrm tunnel mode callback Some thoughts on IPv4 VTI implementation: The connection between VTI receiving part and xfrm tunnel mode input process is hardly a "xfrm_tunnel", xfrm_tunnel is used in places where, e.g ipip/sit and xfrm4_tunnel, acts like a true "tunnel" device. In addition, IMHO, VTI doesn't need vti_err to do something meaningful, as all VTI needs is just a notifier to be called whenever xfrm_input ingress a packet to update statistics. A IPsec protected packet is first handled by protocol handlers, e.g AH/ESP, to check packet authentication or encryption rightness. PMTU update is taken care of in this stage by protocol error handler. Then the packet is rearranged properly depending on whether it's transport mode or tunnel mode packed by mode "input" handler. The VTI handler code takes effects in this stage in tunnel mode only. So it neither need propagate PMTU, as it has already been done if necessary, nor the VTI handler is qualified as a xfrm_tunnel. So this patch introduces xfrm_tunnel_notifier and meanwhile wipe out vti_err code. Signed-off-by: Fan Du Cc: Steffen Klassert Cc: David S. Miller Reviewed-by: Saurabh Mohan Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 10 +++++-- net/ipv4/ip_vti.c | 67 +------------------------------------------- net/ipv4/xfrm4_mode_tunnel.c | 16 +++++------ 3 files changed, 17 insertions(+), 76 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 89d3d8ae204e..c7afa6e476c8 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1352,6 +1352,12 @@ struct xfrm_tunnel { int priority; }; +struct xfrm_tunnel_notifier { + int (*handler)(struct sk_buff *skb); + struct xfrm_tunnel_notifier __rcu *next; + int priority; +}; + struct xfrm6_tunnel { int (*handler)(struct sk_buff *skb); int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -1495,8 +1501,8 @@ extern int xfrm4_output(struct sk_buff *skb); extern int xfrm4_output_finish(struct sk_buff *skb); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); -extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); -extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); +extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler); +extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler); extern int xfrm6_extract_header(struct sk_buff *skb); extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index e805e7b3030e..91f69bc883fe 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -49,70 +49,6 @@ static struct rtnl_link_ops vti_link_ops __read_mostly; static int vti_net_id __read_mostly; static int vti_tunnel_init(struct net_device *dev); -static int vti_err(struct sk_buff *skb, u32 info) -{ - - /* All the routers (except for Linux) return only - * 8 bytes of packet payload. It means, that precise relaying of - * ICMP in the real Internet is absolutely infeasible. - */ - struct net *net = dev_net(skb->dev); - struct ip_tunnel_net *itn = net_generic(net, vti_net_id); - struct iphdr *iph = (struct iphdr *)skb->data; - const int type = icmp_hdr(skb)->type; - const int code = icmp_hdr(skb)->code; - struct ip_tunnel *t; - int err; - - switch (type) { - default: - case ICMP_PARAMETERPROB: - return 0; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return 0; - default: - /* All others are translated to HOST_UNREACH. */ - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return 0; - break; - } - - err = -ENOENT; - - t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, - iph->daddr, iph->saddr, 0); - if (t == NULL) - goto out; - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->parms.link, 0, IPPROTO_IPIP, 0); - err = 0; - goto out; - } - - err = 0; - if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) - goto out; - - if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) - t->err_count++; - else - t->err_count = 1; - t->err_time = jiffies; -out: - return err; -} - /* We dont digest the packet therefore let the packet pass */ static int vti_rcv(struct sk_buff *skb) { @@ -296,9 +232,8 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev) iph->ihl = 5; } -static struct xfrm_tunnel vti_handler __read_mostly = { +static struct xfrm_tunnel_notifier vti_handler __read_mostly = { .handler = vti_rcv, - .err_handler = vti_err, .priority = 1, }; diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index eb1dd4d643f2..b82cde1ea1b6 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -16,13 +16,13 @@ #include /* Informational hook. The decap is still done here. */ -static struct xfrm_tunnel __rcu *rcv_notify_handlers __read_mostly; +static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly; static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex); -int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler) +int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler) { - struct xfrm_tunnel __rcu **pprev; - struct xfrm_tunnel *t; + struct xfrm_tunnel_notifier __rcu **pprev; + struct xfrm_tunnel_notifier *t; int ret = -EEXIST; int priority = handler->priority; @@ -50,10 +50,10 @@ err: } EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register); -int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler) +int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler) { - struct xfrm_tunnel __rcu **pprev; - struct xfrm_tunnel *t; + struct xfrm_tunnel_notifier __rcu **pprev; + struct xfrm_tunnel_notifier *t; int ret = -ENOENT; mutex_lock(&xfrm4_mode_tunnel_input_mutex); @@ -134,7 +134,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) { - struct xfrm_tunnel *handler; + struct xfrm_tunnel_notifier *handler; int err = -EINVAL; if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) -- cgit From 6898eb89655a8ac7d098b2fada95c1c91870365c Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 21 Aug 2013 00:15:00 +0100 Subject: iio: Remove trailing ; from function definitions Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 2103cc32a5fb..8e7a8132b109 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -457,7 +457,7 @@ static inline void iio_device_put(struct iio_dev *indio_dev) { if (indio_dev) put_device(&indio_dev->dev); -}; +} /** * dev_to_iio_dev() - Get IIO device struct from a device struct @@ -593,7 +593,7 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) { return indio_dev->currentmode & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); -}; +} /** * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry @@ -603,12 +603,12 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) { return indio_dev->debugfs_dentry; -}; +} #else static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) { return NULL; -}; +} #endif int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, -- cgit From b89232732f642bfa24f9e252dd241ddfb40d3817 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 27 Aug 2013 15:12:13 +0300 Subject: drm: add MIPI DSI encoder and connector types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Shobhit Kumar Signed-off-by: Jani Nikula Acked-by: Dave Airlie Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 2 ++ include/uapi/drm/drm_mode.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index bff2fa941f60..e79577cb4665 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -202,6 +202,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_TV, "TV" }, { DRM_MODE_CONNECTOR_eDP, "eDP" }, { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, + { DRM_MODE_CONNECTOR_DSI, "DSI" }, }; static const struct drm_prop_enum_list drm_encoder_enum_list[] = @@ -211,6 +212,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = { DRM_MODE_ENCODER_LVDS, "LVDS" }, { DRM_MODE_ENCODER_TVDAC, "TV" }, { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, + { DRM_MODE_ENCODER_DSI, "DSI" }, }; void drm_connector_ida_init(void) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 550811712f78..113d32457fa4 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -165,6 +165,7 @@ struct drm_mode_get_plane_res { #define DRM_MODE_ENCODER_LVDS 3 #define DRM_MODE_ENCODER_TVDAC 4 #define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 struct drm_mode_get_encoder { __u32 encoder_id; @@ -203,6 +204,7 @@ struct drm_mode_get_encoder { #define DRM_MODE_CONNECTOR_TV 13 #define DRM_MODE_CONNECTOR_eDP 14 #define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 struct drm_mode_get_connector { -- cgit From c1d454246c1339388ed0788f34f88ee12ad58ef3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 14 Aug 2013 15:31:52 +0000 Subject: libfc: Source code comment spelling fixes Change 'initiaive' into 'initiative', 'remainig' into 'remaining' and change 'exected' into 'expected'. Signed-off-by: Bart Van Assche Signed-off-by: Robert Love --- drivers/scsi/libfc/fc_exch.c | 5 +---- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 6 +++--- include/scsi/fc/fc_fc2.h | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 587992952b3c..b233a2dea122 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -303,10 +303,7 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, fr_eof(fp) = FC_EOF_N; } - /* - * Initialize remainig fh fields - * from fc_fill_fc_hdr - */ + /* Initialize remaining fh fields from fc_fill_fc_hdr */ fh->fh_ox_id = htons(ep->oxid); fh->fh_rx_id = htons(ep->rxid); fh->fh_seq_id = ep->seq.id; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index f04d15c67df3..a32f3141f3f9 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -516,7 +516,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, * @lport: The local port receiving the LOGO * @fp: The LOGO request frame * - * Locking Note: The lport lock is exected to be held before calling + * Locking Note: The lport lock is expected to be held before calling * this function. */ static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c710d908fda6..589ff9aedd31 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1705,7 +1705,7 @@ reject: * @rdata: The remote port that sent the PRLI request * @rx_fp: The PRLI request frame * - * Locking Note: The rport lock is exected to be held before calling + * Locking Note: The rport lock is expected to be held before calling * this function. */ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, @@ -1824,7 +1824,7 @@ drop: * @rdata: The remote port that sent the PRLO request * @rx_fp: The PRLO request frame * - * Locking Note: The rport lock is exected to be held before calling + * Locking Note: The rport lock is expected to be held before calling * this function. */ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, @@ -1895,7 +1895,7 @@ drop: * @lport: The local port that received the LOGO request * @fp: The LOGO request frame * - * Locking Note: The rport lock is exected to be held before calling + * Locking Note: The rport lock is expected to be held before calling * this function. */ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) diff --git a/include/scsi/fc/fc_fc2.h b/include/scsi/fc/fc_fc2.h index f87777d0d5bd..0b2671431305 100644 --- a/include/scsi/fc/fc_fc2.h +++ b/include/scsi/fc/fc_fc2.h @@ -104,7 +104,7 @@ struct fc_esb { * esb_e_stat - flags from FC-FS-2 T11/1619-D Rev 0.90. */ #define ESB_ST_RESP (1 << 31) /* responder to exchange */ -#define ESB_ST_SEQ_INIT (1 << 30) /* port holds sequence initiaive */ +#define ESB_ST_SEQ_INIT (1 << 30) /* port holds sequence initiative */ #define ESB_ST_COMPLETE (1 << 29) /* exchange is complete */ #define ESB_ST_ABNORMAL (1 << 28) /* abnormal ending condition */ #define ESB_ST_REC_QUAL (1 << 26) /* recovery qualifier active */ -- cgit From 7030fd626129ec4d616784516a462d317c251d39 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 17 Aug 2013 20:34:43 +0000 Subject: libfc: Do not invoke the response handler after fc_exch_done() While the FCoE initiator driver invokes fc_exch_done() from inside the libfc response handler, FCoE target drivers typically invoke fc_exch_done() from outside the libfc response handler. The object fc_exch.arg points at may disappear as soon as fc_exch_done() has finished. So it's important not to invoke the response handler function after fc_exch_done() has finished. Modify libfc such that this guarantee is provided if fc_exch_done() is invoked from outside a response handler. This patch fixes a sporadic crash in FCoE target implementations after a command has been aborted. Signed-off-by: Bart Van Assche Cc: Neil Horman Signed-off-by: Robert Love --- drivers/scsi/libfc/fc_exch.c | 131 ++++++++++++++++++++++++++++++------------- include/scsi/libfc.h | 9 +++ 2 files changed, 101 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 47ebc7b1e143..1b3a09473452 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -381,6 +381,8 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec) /** * fc_exch_done_locked() - Complete an exchange with the exchange lock held * @ep: The exchange that is complete + * + * Note: May sleep if invoked from outside a response handler. */ static int fc_exch_done_locked(struct fc_exch *ep) { @@ -392,7 +394,6 @@ static int fc_exch_done_locked(struct fc_exch *ep) * ep, and in that case we only clear the resp and set it as * complete, so it can be reused by the timer to send the rrq. */ - ep->resp = NULL; if (ep->state & FC_EX_DONE) return rc; ep->esb_stat |= ESB_ST_COMPLETE; @@ -589,6 +590,8 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) /* * Set the response handler for the exchange associated with a sequence. + * + * Note: May sleep if invoked from outside a response handler. */ static void fc_seq_set_resp(struct fc_seq *sp, void (*resp)(struct fc_seq *, struct fc_frame *, @@ -596,8 +599,18 @@ static void fc_seq_set_resp(struct fc_seq *sp, void *arg) { struct fc_exch *ep = fc_seq_exch(sp); + DEFINE_WAIT(wait); spin_lock_bh(&ep->ex_lock); + while (ep->resp_active && ep->resp_task != current) { + prepare_to_wait(&ep->resp_wq, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_bh(&ep->ex_lock); + + schedule(); + + spin_lock_bh(&ep->ex_lock); + } + finish_wait(&ep->resp_wq, &wait); ep->resp = resp; ep->arg = arg; spin_unlock_bh(&ep->ex_lock); @@ -680,6 +693,61 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp, return error; } +/** + * fc_invoke_resp() - invoke ep->resp() + * + * Notes: + * It is assumed that after initialization finished (this means the + * first unlock of ex_lock after fc_exch_alloc()) ep->resp and ep->arg are + * modified only via fc_seq_set_resp(). This guarantees that none of these + * two variables changes if ep->resp_active > 0. + * + * If an fc_seq_set_resp() call is busy modifying ep->resp and ep->arg when + * this function is invoked, the first spin_lock_bh() call in this function + * will wait until fc_seq_set_resp() has finished modifying these variables. + * + * Since fc_exch_done() invokes fc_seq_set_resp() it is guaranteed that that + * ep->resp() won't be invoked after fc_exch_done() has returned. + * + * The response handler itself may invoke fc_exch_done(), which will clear the + * ep->resp pointer. + * + * Return value: + * Returns true if and only if ep->resp has been invoked. + */ +static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp, + struct fc_frame *fp) +{ + void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); + void *arg; + bool res = false; + + spin_lock_bh(&ep->ex_lock); + ep->resp_active++; + if (ep->resp_task != current) + ep->resp_task = !ep->resp_task ? current : NULL; + resp = ep->resp; + arg = ep->arg; + spin_unlock_bh(&ep->ex_lock); + + if (resp) { + resp(sp, fp, arg); + res = true; + } else if (!IS_ERR(fp)) { + fc_frame_free(fp); + } + + spin_lock_bh(&ep->ex_lock); + if (--ep->resp_active == 0) + ep->resp_task = NULL; + spin_unlock_bh(&ep->ex_lock); + + if (ep->resp_active == 0) + wake_up(&ep->resp_wq); + + return res; +} + /** * fc_exch_timeout() - Handle exchange timer expiration * @work: The work_struct identifying the exchange that timed out @@ -689,8 +757,6 @@ static void fc_exch_timeout(struct work_struct *work) struct fc_exch *ep = container_of(work, struct fc_exch, timeout_work.work); struct fc_seq *sp = &ep->seq; - void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); - void *arg; u32 e_stat; int rc = 1; @@ -708,16 +774,13 @@ static void fc_exch_timeout(struct work_struct *work) fc_exch_rrq(ep); goto done; } else { - resp = ep->resp; - arg = ep->arg; - ep->resp = NULL; if (e_stat & ESB_ST_ABNORMAL) rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); if (!rc) fc_exch_delete(ep); - if (resp) - resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg); + fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_TIMEOUT)); + fc_seq_set_resp(sp, NULL, ep->arg); fc_seq_exch_abort(sp, 2 * ep->r_a_tov); goto done; } @@ -804,6 +867,8 @@ hit: ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */ ep->rxid = FC_XID_UNKNOWN; ep->class = mp->class; + ep->resp_active = 0; + init_waitqueue_head(&ep->resp_wq); INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout); out: return ep; @@ -864,6 +929,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and * the memory allocated for the related objects may be freed. * @sp: The sequence that has completed + * + * Note: May sleep if invoked from outside a response handler. */ static void fc_exch_done(struct fc_seq *sp) { @@ -873,6 +940,8 @@ static void fc_exch_done(struct fc_seq *sp) spin_lock_bh(&ep->ex_lock); rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); + + fc_seq_set_resp(sp, NULL, ep->arg); if (!rc) fc_exch_delete(ep); } @@ -1436,9 +1505,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, * If new exch resp handler is valid then call that * first. */ - if (ep->resp) - ep->resp(sp, fp, ep->arg); - else + if (!fc_invoke_resp(ep, sp, fp)) lport->tt.lport_recv(lport, fp); fc_exch_release(ep); /* release from lookup */ } else { @@ -1462,8 +1529,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) struct fc_exch *ep; enum fc_sof sof; u32 f_ctl; - void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); - void *ex_resp_arg; int rc; ep = fc_exch_find(mp, ntohs(fh->fh_ox_id)); @@ -1506,14 +1571,11 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if (fc_sof_needs_ack(sof)) fc_seq_send_ack(sp, fp); - resp = ep->resp; - ex_resp_arg = ep->arg; if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T && (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { spin_lock_bh(&ep->ex_lock); - resp = ep->resp; rc = fc_exch_done_locked(ep); WARN_ON(fc_seq_exch(sp) != ep); spin_unlock_bh(&ep->ex_lock); @@ -1534,10 +1596,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) * If new exch resp handler is valid then call that * first. */ - if (resp) - resp(sp, fp, ex_resp_arg); - else - fc_frame_free(fp); + fc_invoke_resp(ep, sp, fp); + fc_exch_release(ep); return; rel: @@ -1576,8 +1636,6 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) */ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) { - void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); - void *ex_resp_arg; struct fc_frame_header *fh; struct fc_ba_acc *ap; struct fc_seq *sp; @@ -1622,9 +1680,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) break; } - resp = ep->resp; - ex_resp_arg = ep->arg; - /* do we need to do some other checks here. Can we reuse more of * fc_exch_recv_seq_resp */ @@ -1636,17 +1691,14 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ) rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); + + fc_exch_hold(ep); if (!rc) fc_exch_delete(ep); - - if (resp) - resp(sp, fp, ex_resp_arg); - else - fc_frame_free(fp); - + fc_invoke_resp(ep, sp, fp); if (has_rec) fc_exch_timer_set(ep, ep->r_a_tov); - + fc_exch_release(ep); } /** @@ -1768,32 +1820,33 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, /** * fc_exch_reset() - Reset an exchange * @ep: The exchange to be reset + * + * Note: May sleep if invoked from outside a response handler. */ static void fc_exch_reset(struct fc_exch *ep) { struct fc_seq *sp; - void (*resp)(struct fc_seq *, struct fc_frame *, void *); - void *arg; int rc = 1; spin_lock_bh(&ep->ex_lock); fc_exch_abort_locked(ep, 0); ep->state |= FC_EX_RST_CLEANUP; fc_exch_timer_cancel(ep); - resp = ep->resp; - ep->resp = NULL; if (ep->esb_stat & ESB_ST_REC_QUAL) atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */ ep->esb_stat &= ~ESB_ST_REC_QUAL; - arg = ep->arg; sp = &ep->seq; rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); + + fc_exch_hold(ep); + if (!rc) fc_exch_delete(ep); - if (resp) - resp(sp, ERR_PTR(-FC_EX_CLOSED), arg); + fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED)); + fc_seq_set_resp(sp, NULL, ep->arg); + fc_exch_release(ep); } /** diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index e1379b4e8faf..52beadf9a29b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -410,6 +410,12 @@ struct fc_seq { * @fh_type: The frame type * @class: The class of service * @seq: The sequence in use on this exchange + * @resp_active: Number of tasks that are concurrently executing @resp(). + * @resp_task: If @resp_active > 0, either the task executing @resp(), the + * task that has been interrupted to execute the soft-IRQ + * executing @resp() or NULL if more than one task is executing + * @resp concurrently. + * @resp_wq: Waitqueue for the tasks waiting on @resp_active. * @resp: Callback for responses on this exchange * @destructor: Called when destroying the exchange * @arg: Passed as a void pointer to the resp() callback @@ -441,6 +447,9 @@ struct fc_exch { u32 r_a_tov; u32 f_ctl; struct fc_seq seq; + int resp_active; + struct task_struct *resp_task; + wait_queue_head_t resp_wq; void (*resp)(struct fc_seq *, struct fc_frame *, void *); void *arg; void (*destructor)(struct fc_seq *, void *); -- cgit From 272686bf46a34f86d270cf192f68769667792026 Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 5 Sep 2013 11:34:54 +0100 Subject: efi: x86: ia64: provide a generic efi_config_init() Common to (U)EFI support on all platforms is the global "efi" data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code and removes the local definition of the global "efi" data structure from the x86 and ia64 code. Squashed into one big patch to avoid breaking bisection. Signed-off-by: Leif Lindholm Acked-by: Tony Luck Signed-off-by: Matt Fleming --- arch/ia64/kernel/efi.c | 54 +++++----------------- arch/x86/platform/efi/efi.c | 96 ++++----------------------------------- drivers/firmware/efi/efi.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 7 +++ 4 files changed, 134 insertions(+), 131 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51bce594eb83..da5b462e6de6 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -44,10 +44,15 @@ #define EFI_DEBUG 0 +static __initdata unsigned long palo_phys; + +static __initdata efi_config_table_type_t arch_tables[] = { + {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys}, + {NULL_GUID, NULL, 0}, +}; + extern efi_status_t efi_call_phys (void *, ...); -struct efi efi; -EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; @@ -423,9 +428,9 @@ static u8 __init palo_checksum(u8 *buffer, u32 length) * Parse and handle PALO table which is published at: * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf */ -static void __init handle_palo(unsigned long palo_phys) +static void __init handle_palo(unsigned long phys_addr) { - struct palo_table *palo = __va(palo_phys); + struct palo_table *palo = __va(phys_addr); u8 checksum; if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) { @@ -467,12 +472,10 @@ void __init efi_init (void) { void *efi_map_start, *efi_map_end; - efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; char *cp, vendor[100] = "unknown"; int i; - unsigned long palo_phys; /* * It's too early to be able to use the standard kernel command line @@ -514,8 +517,6 @@ efi_init (void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff); - config_tables = __va(efi.systab->tables); - /* Show what we know for posterity */ c16 = __va(efi.systab->fw_vendor); if (c16) { @@ -528,43 +529,10 @@ efi_init (void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - efi.mps = EFI_INVALID_TABLE_ADDR; - efi.acpi = EFI_INVALID_TABLE_ADDR; - efi.acpi20 = EFI_INVALID_TABLE_ADDR; - efi.smbios = EFI_INVALID_TABLE_ADDR; - efi.sal_systab = EFI_INVALID_TABLE_ADDR; - efi.boot_info = EFI_INVALID_TABLE_ADDR; - efi.hcdp = EFI_INVALID_TABLE_ADDR; - efi.uga = EFI_INVALID_TABLE_ADDR; - palo_phys = EFI_INVALID_TABLE_ADDR; - for (i = 0; i < (int) efi.systab->nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = config_tables[i].table; - printk(" MPS=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = config_tables[i].table; - printk(" ACPI 2.0=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = config_tables[i].table; - printk(" ACPI=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = config_tables[i].table; - printk(" SMBIOS=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = config_tables[i].table; - printk(" SALsystab=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = config_tables[i].table; - printk(" HCDP=0x%lx", config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, - PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) { - palo_phys = config_tables[i].table; - printk(" PALO=0x%lx", config_tables[i].table); - } - } - printk("\n"); + if (efi_config_init(arch_tables) != 0) + return; if (palo_phys != EFI_INVALID_TABLE_ADDR) handle_palo(palo_phys); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed127096..ed2be58ea3f1 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -60,19 +60,6 @@ static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; -struct efi __read_mostly efi = { - .mps = EFI_INVALID_TABLE_ADDR, - .acpi = EFI_INVALID_TABLE_ADDR, - .acpi20 = EFI_INVALID_TABLE_ADDR, - .smbios = EFI_INVALID_TABLE_ADDR, - .sal_systab = EFI_INVALID_TABLE_ADDR, - .boot_info = EFI_INVALID_TABLE_ADDR, - .hcdp = EFI_INVALID_TABLE_ADDR, - .uga = EFI_INVALID_TABLE_ADDR, - .uv_systab = EFI_INVALID_TABLE_ADDR, -}; -EXPORT_SYMBOL(efi); - struct efi_memory_map memmap; static struct efi efi_phys __initdata; @@ -80,6 +67,13 @@ static efi_system_table_t efi_systab __initdata; unsigned long x86_efi_facility; +static __initdata efi_config_table_type_t arch_tables[] = { +#ifdef CONFIG_X86_UV + {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab}, +#endif + {NULL_GUID, NULL, 0}, +}; + /* * Returns 1 if 'facility' is enabled, 0 otherwise. */ @@ -578,80 +572,6 @@ static int __init efi_systab_init(void *phys) return 0; } -static int __init efi_config_init(u64 tables, int nr_tables) -{ - void *config_tables, *tablep; - int i, sz; - - if (efi_enabled(EFI_64BIT)) - sz = sizeof(efi_config_table_64_t); - else - sz = sizeof(efi_config_table_32_t); - - /* - * Let's see what config tables the firmware passed to us. - */ - config_tables = early_ioremap(tables, nr_tables * sz); - if (config_tables == NULL) { - pr_err("Could not map Configuration table!\n"); - return -ENOMEM; - } - - tablep = config_tables; - pr_info(""); - for (i = 0; i < efi.systab->nr_tables; i++) { - efi_guid_t guid; - unsigned long table; - - if (efi_enabled(EFI_64BIT)) { - u64 table64; - guid = ((efi_config_table_64_t *)tablep)->guid; - table64 = ((efi_config_table_64_t *)tablep)->table; - table = table64; -#ifdef CONFIG_X86_32 - if (table64 >> 32) { - pr_cont("\n"); - pr_err("Table located above 4GB, disabling EFI.\n"); - early_iounmap(config_tables, - efi.systab->nr_tables * sz); - return -EINVAL; - } -#endif - } else { - guid = ((efi_config_table_32_t *)tablep)->guid; - table = ((efi_config_table_32_t *)tablep)->table; - } - if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { - efi.mps = table; - pr_cont(" MPS=0x%lx ", table); - } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { - efi.acpi20 = table; - pr_cont(" ACPI 2.0=0x%lx ", table); - } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { - efi.acpi = table; - pr_cont(" ACPI=0x%lx ", table); - } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { - efi.smbios = table; - pr_cont(" SMBIOS=0x%lx ", table); -#ifdef CONFIG_X86_UV - } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { - efi.uv_systab = table; - pr_cont(" UVsystab=0x%lx ", table); -#endif - } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { - efi.hcdp = table; - pr_cont(" HCDP=0x%lx ", table); - } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { - efi.uga = table; - pr_cont(" UGA=0x%lx ", table); - } - tablep += sz; - } - pr_cont("\n"); - early_iounmap(config_tables, efi.systab->nr_tables * sz); - return 0; -} - static int __init efi_runtime_init(void) { efi_runtime_services_t *runtime; @@ -745,7 +665,7 @@ void __init efi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) + if (efi_config_init(arch_tables)) return; set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 5145fa344ad5..e1010d450b65 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -13,11 +13,27 @@ * This file is released under the GPLv2. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include #include #include +#include + +struct efi __read_mostly efi = { + .mps = EFI_INVALID_TABLE_ADDR, + .acpi = EFI_INVALID_TABLE_ADDR, + .acpi20 = EFI_INVALID_TABLE_ADDR, + .smbios = EFI_INVALID_TABLE_ADDR, + .sal_systab = EFI_INVALID_TABLE_ADDR, + .boot_info = EFI_INVALID_TABLE_ADDR, + .hcdp = EFI_INVALID_TABLE_ADDR, + .uga = EFI_INVALID_TABLE_ADDR, + .uv_systab = EFI_INVALID_TABLE_ADDR, +}; +EXPORT_SYMBOL(efi); static struct kobject *efi_kobj; static struct kobject *efivars_kobj; @@ -132,3 +148,95 @@ err_put: } subsys_initcall(efisubsys_init); + + +static __initdata efi_config_table_type_t common_tables[] = { + {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20}, + {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, + {HCDP_TABLE_GUID, "HCDP", &efi.hcdp}, + {MPS_TABLE_GUID, "MPS", &efi.mps}, + {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab}, + {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, + {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, + {NULL_GUID, NULL, 0}, +}; + +static __init int match_config_table(efi_guid_t *guid, + unsigned long table, + efi_config_table_type_t *table_types) +{ + u8 str[EFI_VARIABLE_GUID_LEN + 1]; + int i; + + if (table_types) { + efi_guid_unparse(guid, str); + + for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { + efi_guid_unparse(&table_types[i].guid, str); + + if (!efi_guidcmp(*guid, table_types[i].guid)) { + *(table_types[i].ptr) = table; + pr_cont(" %s=0x%lx ", + table_types[i].name, table); + return 1; + } + } + } + + return 0; +} + +int __init efi_config_init(efi_config_table_type_t *arch_tables) +{ + void *config_tables, *tablep; + int i, sz; + + if (efi_enabled(EFI_64BIT)) + sz = sizeof(efi_config_table_64_t); + else + sz = sizeof(efi_config_table_32_t); + + /* + * Let's see what config tables the firmware passed to us. + */ + config_tables = early_memremap(efi.systab->tables, + efi.systab->nr_tables * sz); + if (config_tables == NULL) { + pr_err("Could not map Configuration table!\n"); + return -ENOMEM; + } + + tablep = config_tables; + pr_info(""); + for (i = 0; i < efi.systab->nr_tables; i++) { + efi_guid_t guid; + unsigned long table; + + if (efi_enabled(EFI_64BIT)) { + u64 table64; + guid = ((efi_config_table_64_t *)tablep)->guid; + table64 = ((efi_config_table_64_t *)tablep)->table; + table = table64; +#ifndef CONFIG_64BIT + if (table64 >> 32) { + pr_cont("\n"); + pr_err("Table located above 4GB, disabling EFI.\n"); + early_iounmap(config_tables, + efi.systab->nr_tables * sz); + return -EINVAL; + } +#endif + } else { + guid = ((efi_config_table_32_t *)tablep)->guid; + table = ((efi_config_table_32_t *)tablep)->table; + } + + if (!match_config_table(&guid, table, common_tables)) + match_config_table(&guid, table, arch_tables); + + tablep += sz; + } + pr_cont("\n"); + early_iounmap(config_tables, efi.systab->nr_tables * sz); + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 5f8f176154f7..09d9e4212799 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -404,6 +404,12 @@ typedef struct { unsigned long table; } efi_config_table_t; +typedef struct { + efi_guid_t guid; + const char *name; + unsigned long *ptr; +} efi_config_table_type_t; + #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) #define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) @@ -587,6 +593,7 @@ static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned lon } #endif extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); +extern int efi_config_init(efi_config_table_type_t *arch_tables); extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); -- cgit From 258f6fd738221766b512cd8c7120563b78d62829 Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 5 Sep 2013 11:34:55 +0100 Subject: efi: x86: make efi_lookup_mapped_addr() a common function efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware. Add memmap pointer to global efi structure, and initialise it on x86. Signed-off-by: Leif Lindholm Signed-off-by: Matt Fleming --- arch/x86/platform/efi/efi.c | 30 ++---------------------------- drivers/firmware/efi/efi.c | 32 ++++++++++++++++++++++++++++++++ include/linux/efi.h | 1 + 3 files changed, 35 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ed2be58ea3f1..fbc1d70188f8 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -393,6 +393,8 @@ int __init efi_memblock_x86_reserve_range(void) memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); + efi.memmap = &memmap; + return 0; } @@ -736,34 +738,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md->num_pages << EFI_PAGE_SHIFT; - u64 end = md->phys_addr + size; - if (!(md->attribute & EFI_MEMORY_RUNTIME) && - md->type != EFI_BOOT_SERVICES_CODE && - md->type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md->virt_addr) - continue; - if (phys_addr >= md->phys_addr && phys_addr < end) { - phys_addr += md->virt_addr - md->phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index e1010d450b65..2e2fbdec0845 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -150,6 +150,38 @@ err_put: subsys_initcall(efisubsys_init); +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + struct efi_memory_map *map; + void *p; + map = efi.memmap; + if (!map) + return NULL; + if (WARN_ON(!map->map)) + return NULL; + for (p = map->map; p < map->map_end; p += map->desc_size) { + efi_memory_desc_t *md = p; + u64 size = md->num_pages << EFI_PAGE_SHIFT; + u64 end = md->phys_addr + size; + if (!(md->attribute & EFI_MEMORY_RUNTIME) && + md->type != EFI_BOOT_SERVICES_CODE && + md->type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md->virt_addr) + continue; + if (phys_addr >= md->phys_addr && phys_addr < end) { + phys_addr += md->virt_addr - md->phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20}, {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, diff --git a/include/linux/efi.h b/include/linux/efi.h index 09d9e4212799..c084b6d942c3 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -558,6 +558,7 @@ extern struct efi { efi_get_next_high_mono_count_t *get_next_high_mono_count; efi_reset_system_t *reset_system; efi_set_virtual_address_map_t *set_virtual_address_map; + struct efi_memory_map *memmap; } efi; static inline int -- cgit From 5a523605afa7d3b54b2e7041f8c9e6bc39872a7e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 10 Sep 2013 15:45:05 +0530 Subject: regulator: core: provide fixed voltage in desc for single voltage rail If given rail has the single voltage (n_voltages = 1) then provide the rail voltage through regulator descriptor so that core can use this value for finding voltage. This will avoid the implementation of the callback for get_voltage() or list_voltage() callback on regulator driver. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++++- include/linux/regulator/driver.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a01b8b3b70ca..abc899ed1ebf 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2489,6 +2489,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) ret = rdev->desc->ops->get_voltage(rdev); } else if (rdev->desc->ops->list_voltage) { ret = rdev->desc->ops->list_voltage(rdev, 0); + } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { + ret = rdev->desc->fixed_uV; } else { return -EINVAL; } @@ -3170,7 +3172,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev) /* some attributes need specific methods to be displayed */ if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || - (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { + (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || + (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) { status = device_create_file(dev, &dev_attr_microvolts); if (status < 0) return status; diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 67e13aa5a478..9e8241a9f28f 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -207,6 +207,7 @@ enum regulator_type { * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) * @linear_min_sel: Minimal selector for starting linear mapping + * @fixed_uV: Fixed voltage of rails. * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @volt_table: Voltage mapping table (if table based mapping) * @@ -239,6 +240,7 @@ struct regulator_desc { unsigned int min_uV; unsigned int uV_step; unsigned int linear_min_sel; + int fixed_uV; unsigned int ramp_delay; const struct regulator_linear_range *linear_ranges; -- cgit From 899d90bdf4d4ef4c3ac0b33cd337c9b3e999ec2d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 8 Sep 2013 16:20:00 +0100 Subject: iio: Add INT_TIME (integration time) channel info attribute Integration time is in seconds; it controls the measurement time and influences the gain of a sensor. There are two typical ways that scaling is implemented in a device: 1) input amplifier, 2) reference to the ADC is changed. These both result in the accuracy of the ADC varying (by applying its sampling over a more relevant range). Integration time is a way of dealing with noise inherent in the analog sensor itself. In the case of a light sensor, a mixture of photon noise and device specific noise. Photon noise is dealt with by either improving the efficiency of the sensor, (more photons actually captured) which is not easily varied dynamically, or by integrating the measurement over a longer time period. Note that this can also be thought of as an averaging of a number of individual samples and is infact sometimes implemented this way. Altering integration time implies that the duration of a measurement changes, a fact the device's user may be interested in. Hence it makes sense to distinguish between integration time and simple scale. In some devices both types of control are present and whilst they will have similar effects on the amplitude of the reading, their effect on the noise of the measurements will differ considerably. Used by adjd_s311, tsl4531, tcs3472 The following drivers have similar controls (and could be adapted): * tsl2563 (integration time is controlled via CALIBSCALE among other things) * tsl2583 (has integration_time device_attr, but driver doesn't use channels yet) * tsl2x7x (has integration_time attr) Signed-off-by: Peter Meerwald Cc: Jon Brenner Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 11 +++++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/iio.h | 1 + include/linux/iio/sysfs.h | 15 +++++++++++++++ 4 files changed, 28 insertions(+) (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 39c8de0e53d0..ab1047c20495 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -811,3 +811,14 @@ Description: Writing '1' stores the current device configuration into on-chip EEPROM. After power-up or chip reset the device will automatically load the saved configuration. + +What: /sys/.../iio:deviceX/in_intensity_red_integration_time +What: /sys/.../iio:deviceX/in_intensity_green_integration_time +What: /sys/.../iio:deviceX/in_intensity_blue_integration_time +What: /sys/.../iio:deviceX/in_intensity_clear_integration_time +What: /sys/.../iio:deviceX/in_illuminance_integration_time +KernelVersion: 3.12 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to get/set the integration time in + seconds. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 97f0297b120f..2cb4841d5357 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -101,6 +101,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_PHASE] = "phase", [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", + [IIO_CHAN_INFO_INT_TIME] = "integration_time", }; const struct iio_chan_spec diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 8e7a8132b109..01edd6795550 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -36,6 +36,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_PHASE, IIO_CHAN_INFO_HARDWAREGAIN, IIO_CHAN_INFO_HYSTERESIS, + IIO_CHAN_INFO_INT_TIME, }; enum iio_endian { diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h index 2958c960003a..8a1d18640ab9 100644 --- a/include/linux/iio/sysfs.h +++ b/include/linux/iio/sysfs.h @@ -100,6 +100,21 @@ struct iio_const_attr { #define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ IIO_CONST_ATTR(sampling_frequency_available, _string) +/** + * IIO_DEV_ATTR_INT_TIME_AVAIL - list available integration times + * @_show: output method for the attribute + **/ +#define IIO_DEV_ATTR_INT_TIME_AVAIL(_show) \ + IIO_DEVICE_ATTR(integration_time_available, S_IRUGO, _show, NULL, 0) +/** + * IIO_CONST_ATTR_INT_TIME_AVAIL - list available integration times + * @_string: frequency string for the attribute + * + * Constant version + **/ +#define IIO_CONST_ATTR_INT_TIME_AVAIL(_string) \ + IIO_CONST_ATTR(integration_time_available, _string) + #define IIO_DEV_ATTR_TEMP_RAW(_show) \ IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) -- cgit From ea01f2c18a22a2a8385909d64662afc92da6b13f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 10 Sep 2013 13:49:00 +0100 Subject: iio: pressure-core: st: Allow for number of channels to vary At the moment the number of channels specified is dictated by the first sensor supported by the driver. As we add support for more sensors this is likely to vary. Instead of using the ARRAY_SIZE() of the LPS331AP's channel specifier we'll use a new adaptable 'struct st_sensors' element instead. Signed-off-by: Lee Jones Acked-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_core.c | 3 ++- include/linux/iio/common/st_sensors.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 506b02d27b0a..93bff9ba05d6 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -107,6 +107,7 @@ static const struct st_sensors st_press_sensors[] = { [0] = LPS331AP_PRESS_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_press_lps331ap_channels, + .num_ch = ARRAY_SIZE(st_press_lps331ap_channels), .odr = { .addr = ST_PRESS_LPS331AP_ODR_ADDR, .mask = ST_PRESS_LPS331AP_ODR_MASK, @@ -245,7 +246,7 @@ int st_press_common_probe(struct iio_dev *indio_dev, pdata->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; pdata->multiread_bit = pdata->sensor->multi_read_bit; indio_dev->channels = pdata->sensor->ch; - indio_dev->num_channels = ARRAY_SIZE(st_press_lps331ap_channels); + indio_dev->num_channels = pdata->sensor->num_ch; if (pdata->sensor->fs.addr != 0) pdata->current_fullscale = (struct st_sensor_fullscale_avl *) diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index e51f65480ea5..e732fda6c8e6 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -184,6 +184,7 @@ struct st_sensors { u8 wai; char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME]; struct iio_chan_spec *ch; + int num_ch; struct st_sensor_odr odr; struct st_sensor_power pw; struct st_sensor_axis enable_axis; -- cgit From 9761696f2be276b169b77bcf359bc50a251c9280 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 8 Sep 2013 14:57:00 +0100 Subject: iio: drop info_mask from struct iio_dev Somehow this got missed when dropping all the code that used it prior to the split. Remove it now, there are no users. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- include/linux/iio/iio.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 01edd6795550..bc408e2def40 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -147,12 +147,10 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * shift: Shift right by this before masking out * realbits. * endianness: little or big endian - * @info_mask: What information is to be exported about this channel. - * This includes calibbias, scale etc. * @info_mask_separate: What information is to be exported that is specific to * this channel. * @info_mask_shared_by_type: What information is to be exported that is shared -* by all channels of the same type. + * by all channels of the same type. * @event_mask: What events can this channel produce. * @ext_info: Array of extended info attributes for this channel. * The array is NULL terminated, the last element should @@ -187,7 +185,6 @@ struct iio_chan_spec { u8 shift; enum iio_endian endianness; } scan_type; - long info_mask; long info_mask_separate; long info_mask_shared_by_type; long event_mask; -- cgit From 3704432fb1fd8ab2df114bad6df752381246b609 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 8 Sep 2013 14:57:00 +0100 Subject: iio: refactor info mask and ext_info attribute creation. Introduce an enum to specify whether the attribute is separate or shared. Factor out the bitmap handling for loop into a separate function. Tidy up error handling and add a NULL assignment to squish a false positive warning from GCC. Change ext_info shared type from boolean to enum and update in all drivers. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/iio/dac/ad5064.c | 3 +- drivers/iio/dac/ad5380.c | 4 +- drivers/iio/dac/ad5446.c | 3 +- drivers/iio/dac/ad5504.c | 4 +- drivers/iio/dac/ad5624r_spi.c | 4 +- drivers/iio/dac/ad5686.c | 3 +- drivers/iio/dac/ad5755.c | 1 + drivers/iio/dac/ad5791.c | 5 +- drivers/iio/dac/ad7303.c | 1 + drivers/iio/dac/mcp4725.c | 3 +- drivers/iio/frequency/adf4350.c | 1 + drivers/iio/iio_core.h | 2 +- drivers/iio/industrialio-buffer.c | 2 +- drivers/iio/industrialio-core.c | 149 ++++++++++++++++++++------------------ include/linux/iio/iio.h | 9 ++- 15 files changed, 112 insertions(+), 82 deletions(-) (limited to 'include') diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index a3a52be4852c..b18e8c4347c2 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -285,8 +285,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { .name = "powerdown", .read = ad5064_read_dac_powerdown, .write = ad5064_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 1c44ae3920e2..4c791e66e0d7 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -247,8 +247,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = { .name = "powerdown", .read = ad5380_read_dac_powerdown, .write = ad5380_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, + &ad5380_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 96e9ed4c2d01..6dcb6d93f0e4 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -132,8 +132,9 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = { .name = "powerdown", .read = ad5446_read_dac_powerdown, .write = ad5446_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index caffb16bc05c..31f4ff29f914 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -248,8 +248,10 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { .name = "powerdown", .read = ad5504_read_dac_powerdown, .write = ad5504_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, + &ad5504_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 714af757cd56..dbb1289cc7a6 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -163,8 +163,10 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { .name = "powerdown", .read = ad5624r_read_dac_powerdown, .write = ad5624r_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, + &ad5624r_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 3e1080feedbf..f472b48445f6 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -264,8 +264,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { .name = "powerdown", .read = ad5686_read_dac_powerdown, .write = ad5686_write_dac_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 36a4361aece1..f305a0c83418 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -386,6 +386,7 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { .name = "powerdown", .read = ad5755_read_powerdown, .write = ad5755_write_powerdown, + .shared = IIO_SEPARATE, }, { }, }; diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index ce7458963309..3cee89be68c3 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -287,11 +287,12 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { { .name = "powerdown", - .shared = true, + .shared = IIO_SHARED_BY_TYPE, .read = ad5791_read_dac_powerdown, .write = ad5791_write_dac_powerdown, }, - IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, + &ad5791_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index ed2d276477bd..d0505fd22ef4 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -169,6 +169,7 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { .name = "powerdown", .read = ad7303_read_dac_powerdown, .write = ad7303_write_dac_powerdown, + .shared = IIO_SEPARATE, }, { }, }; diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 1f4a48e6a82c..6711a33b16ba 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -195,8 +195,9 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { .name = "powerdown", .read = mcp4725_read_powerdown, .write = mcp4725_write_powerdown, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum), { }, }; diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index a7b30be86ae0..85152547aa8b 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -351,6 +351,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, .read = adf4350_read, \ .write = adf4350_write, \ .private = _ident, \ + .shared = IIO_SEPARATE, \ } static const struct iio_chan_spec_ext_info adf4350_ext_info[] = { diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 05c1b74502a3..6be5ab864b1a 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -30,7 +30,7 @@ int __iio_add_chan_devattr(const char *postfix, const char *buf, size_t len), u64 mask, - bool generic, + enum iio_shared_by shared_by, struct device *dev, struct list_head *attr_list); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 96e97ad2538c..7ea2edbf7614 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -208,7 +208,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, &iio_show_scan_index, NULL, 0, - 0, + IIO_SEPARATE, &indio_dev->dev, &buffer->scan_el_dev_attr_list); if (ret) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2cb4841d5357..d380c7278a26 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -517,14 +517,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, struct device_attribute *attr, const char *buf, size_t len), - bool generic) + enum iio_shared_by shared_by) { - int ret; - char *name_format, *full_postfix; + int ret = 0; + char *name_format = NULL; + char *full_postfix; sysfs_attr_init(&dev_attr->attr); /* Build up postfix of __postfix */ - if (chan->modified && !generic) { + if (chan->modified && (shared_by == IIO_SEPARATE)) { if (chan->extend_name) full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", iio_modifier_names[chan @@ -545,53 +546,62 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, chan->extend_name, postfix); } - if (full_postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } + if (full_postfix == NULL) + return -ENOMEM; if (chan->differential) { /* Differential can not have modifier */ - if (generic) + switch (shared_by) { + case IIO_SHARED_BY_TYPE: name_format = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", iio_direction[chan->output], iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type], full_postfix); - else if (chan->indexed) + break; + case IIO_SEPARATE: + if (!chan->indexed) { + WARN_ON("Differential channels must be indexed\n"); + ret = -EINVAL; + goto error_free_full_postfix; + } name_format - = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", + = kasprintf(GFP_KERNEL, + "%s_%s%d-%s%d_%s", iio_direction[chan->output], iio_chan_type_name_spec[chan->type], chan->channel, iio_chan_type_name_spec[chan->type], chan->channel2, full_postfix); - else { - WARN_ON("Differential channels must be indexed\n"); - ret = -EINVAL; - goto error_free_full_postfix; + break; } } else { /* Single ended */ - if (generic) - name_format - = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - full_postfix); - else if (chan->indexed) - name_format - = kasprintf(GFP_KERNEL, "%s_%s%d_%s", - iio_direction[chan->output], - iio_chan_type_name_spec[chan->type], - chan->channel, - full_postfix); - else + switch (shared_by) { + case IIO_SHARED_BY_TYPE: name_format = kasprintf(GFP_KERNEL, "%s_%s_%s", iio_direction[chan->output], iio_chan_type_name_spec[chan->type], full_postfix); + break; + + case IIO_SEPARATE: + if (chan->indexed) + name_format + = kasprintf(GFP_KERNEL, "%s_%s%d_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + chan->channel, + full_postfix); + else + name_format + = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + full_postfix); + break; + } } if (name_format == NULL) { ret = -ENOMEM; @@ -615,16 +625,11 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, dev_attr->attr.mode |= S_IWUSR; dev_attr->store = writefunc; } - kfree(name_format); - kfree(full_postfix); - - return 0; - error_free_name_format: kfree(name_format); error_free_full_postfix: kfree(full_postfix); -error_ret: + return ret; } @@ -643,7 +648,7 @@ int __iio_add_chan_devattr(const char *postfix, const char *buf, size_t len), u64 mask, - bool generic, + enum iio_shared_by shared_by, struct device *dev, struct list_head *attr_list) { @@ -657,7 +662,7 @@ int __iio_add_chan_devattr(const char *postfix, } ret = __iio_device_attr_init(&iio_attr->dev_attr, postfix, chan, - readfunc, writefunc, generic); + readfunc, writefunc, shared_by); if (ret) goto error_iio_dev_attr_free; iio_attr->c = chan; @@ -665,7 +670,7 @@ int __iio_add_chan_devattr(const char *postfix, list_for_each_entry(t, attr_list, l) if (strcmp(t->dev_attr.attr.name, iio_attr->dev_attr.attr.name) == 0) { - if (!generic) + if (shared_by == IIO_SEPARATE) dev_err(dev, "tried to double register : %s\n", t->dev_attr.attr.name); ret = -EBUSY; @@ -683,46 +688,54 @@ error_ret: return ret; } -static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) +static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + enum iio_shared_by shared_by, + const long *infomask) { - int ret, attrcount = 0; - int i; - const struct iio_chan_spec_ext_info *ext_info; + int i, ret, attrcount = 0; - if (chan->channel < 0) - return 0; - for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) { + for_each_set_bit(i, infomask, sizeof(infomask)*8) { ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], chan, &iio_read_channel_info, &iio_write_channel_info, i, - 0, + shared_by, &indio_dev->dev, &indio_dev->channel_attr_list); - if (ret < 0) - goto error_ret; - attrcount++; - } - for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) { - ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], - chan, - &iio_read_channel_info, - &iio_write_channel_info, - i, - 1, - &indio_dev->dev, - &indio_dev->channel_attr_list); - if (ret == -EBUSY) { - ret = 0; + if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) continue; - } else if (ret < 0) { - goto error_ret; - } + else if (ret < 0) + return ret; attrcount++; } + return attrcount; +} + +static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + int ret, attrcount = 0; + const struct iio_chan_spec_ext_info *ext_info; + + if (chan->channel < 0) + return 0; + ret = iio_device_add_info_mask_type(indio_dev, chan, + IIO_SEPARATE, + &chan->info_mask_separate); + if (ret < 0) + return ret; + attrcount += ret; + + ret = iio_device_add_info_mask_type(indio_dev, chan, + IIO_SHARED_BY_TYPE, + &chan->info_mask_shared_by_type); + if (ret < 0) + return ret; + attrcount += ret; + if (chan->ext_info) { unsigned int i = 0; for (ext_info = chan->ext_info; ext_info->name; ext_info++) { @@ -741,15 +754,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, continue; if (ret) - goto error_ret; + return ret; attrcount++; } } - ret = attrcount; -error_ret: - return ret; + return attrcount; } static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index bc408e2def40..21de272f1eb6 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -39,6 +39,11 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_INT_TIME, }; +enum iio_shared_by { + IIO_SEPARATE, + IIO_SHARED_BY_TYPE +}; + enum iio_endian { IIO_CPU, IIO_BE, @@ -58,7 +63,7 @@ struct iio_dev; */ struct iio_chan_spec_ext_info { const char *name; - bool shared; + enum iio_shared_by shared; ssize_t (*read)(struct iio_dev *, uintptr_t private, struct iio_chan_spec const *, char *buf); ssize_t (*write)(struct iio_dev *, uintptr_t private, @@ -126,7 +131,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, #define IIO_ENUM_AVAILABLE(_name, _e) \ { \ .name = (_name "_available"), \ - .shared = true, \ + .shared = IIO_SHARED_BY_TYPE, \ .read = iio_enum_available_read, \ .private = (uintptr_t)(_e), \ } -- cgit From c006ec838414d910bdd63ba8d919e602425e194e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 8 Sep 2013 14:57:00 +0100 Subject: iio: add info_mask_[shared_by_dir/shared_by_all] These two additional info_mask bitmaps should allow all 'standard' numeric attributes to be handled using the read_raw and write_raw callbacks. Whilst this should reduce code, the more important element is that this makes these values easily accessible to in kernel users of IIO devices. Signed-off-by: Jonathan Cameron Reviewed-by: Lars-Peter Clausen --- drivers/iio/industrialio-core.c | 30 ++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 14 ++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index d380c7278a26..24db1855dbab 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -551,6 +551,14 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, if (chan->differential) { /* Differential can not have modifier */ switch (shared_by) { + case IIO_SHARED_BY_ALL: + name_format = kasprintf(GFP_KERNEL, "%s", full_postfix); + break; + case IIO_SHARED_BY_DIR: + name_format = kasprintf(GFP_KERNEL, "%s_%s", + iio_direction[chan->output], + full_postfix); + break; case IIO_SHARED_BY_TYPE: name_format = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", @@ -578,6 +586,14 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, } } else { /* Single ended */ switch (shared_by) { + case IIO_SHARED_BY_ALL: + name_format = kasprintf(GFP_KERNEL, "%s", full_postfix); + break; + case IIO_SHARED_BY_DIR: + name_format = kasprintf(GFP_KERNEL, "%s_%s", + iio_direction[chan->output], + full_postfix); + break; case IIO_SHARED_BY_TYPE: name_format = kasprintf(GFP_KERNEL, "%s_%s_%s", @@ -736,6 +752,20 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, return ret; attrcount += ret; + ret = iio_device_add_info_mask_type(indio_dev, chan, + IIO_SHARED_BY_DIR, + &chan->info_mask_shared_by_dir); + if (ret < 0) + return ret; + attrcount += ret; + + ret = iio_device_add_info_mask_type(indio_dev, chan, + IIO_SHARED_BY_ALL, + &chan->info_mask_shared_by_all); + if (ret < 0) + return ret; + attrcount += ret; + if (chan->ext_info) { unsigned int i = 0; for (ext_info = chan->ext_info; ext_info->name; ext_info++) { diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 21de272f1eb6..ac1cb8f1858c 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -41,7 +41,9 @@ enum iio_chan_info_enum { enum iio_shared_by { IIO_SEPARATE, - IIO_SHARED_BY_TYPE + IIO_SHARED_BY_TYPE, + IIO_SHARED_BY_DIR, + IIO_SHARED_BY_ALL }; enum iio_endian { @@ -156,6 +158,10 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, * this channel. * @info_mask_shared_by_type: What information is to be exported that is shared * by all channels of the same type. + * @info_mask_shared_by_dir: What information is to be exported that is shared + * by all channels of the same direction. + * @info_mask_shared_by_all: What information is to be exported that is shared + * by all channels. * @event_mask: What events can this channel produce. * @ext_info: Array of extended info attributes for this channel. * The array is NULL terminated, the last element should @@ -192,6 +198,8 @@ struct iio_chan_spec { } scan_type; long info_mask_separate; long info_mask_shared_by_type; + long info_mask_shared_by_dir; + long info_mask_shared_by_all; long event_mask; const struct iio_chan_spec_ext_info *ext_info; const char *extend_name; @@ -215,7 +223,9 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, enum iio_chan_info_enum type) { return (chan->info_mask_separate & BIT(type)) | - (chan->info_mask_shared_by_type & BIT(type)); + (chan->info_mask_shared_by_type & BIT(type)) | + (chan->info_mask_shared_by_dir & BIT(type)) | + (chan->info_mask_shared_by_all & BIT(type)); } #define IIO_ST(si, rb, sb, sh) \ -- cgit From 5d65d92045cb7d3b2c45020c0e62d6d1c1d34f37 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 15 Sep 2013 17:50:00 +0100 Subject: iio: iio_push_to_buffers(): Change type of 'data' to const void * Change the type of the 'data' parameter for iio_push_to_buffers() from 'u8 *' to 'const void *'. Drivers typically use the correct type (e.g. __be16 *) for their data buffer. When passing the buffer to iio_push_to_buffers() it needs to be cast to 'u8 *' for the compiler to not complain (and also having to add __force if we want to keep sparse happy as well). Since the buffer implementation should not care about the data layout (except the size of one sample) using a void pointer is the correct thing to do. Also make it const as the buffer implementations are not supposed to modify it. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/buffer_cb.c | 6 +++--- drivers/iio/industrialio-buffer.c | 10 +++++----- drivers/iio/kfifo_buf.c | 2 +- include/linux/iio/buffer.h | 6 +++--- include/linux/iio/consumer.h | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c index f406889248c8..578f7199ed51 100644 --- a/drivers/iio/buffer_cb.c +++ b/drivers/iio/buffer_cb.c @@ -7,12 +7,12 @@ struct iio_cb_buffer { struct iio_buffer buffer; - int (*cb)(u8 *data, void *private); + int (*cb)(const void *data, void *private); void *private; struct iio_channel *channels; }; -static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data) +static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data) { struct iio_cb_buffer *cb_buff = container_of(buffer, struct iio_cb_buffer, @@ -26,7 +26,7 @@ static const struct iio_buffer_access_funcs iio_cb_access = { }; struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, - int (*cb)(u8 *data, + int (*cb)(const void *data, void *private), void *private) { diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 7ea2edbf7614..a7ac4b5af03e 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -769,8 +769,8 @@ struct iio_demux_table { struct list_head l; }; -static unsigned char *iio_demux(struct iio_buffer *buffer, - unsigned char *datain) +static const void *iio_demux(struct iio_buffer *buffer, + const void *datain) { struct iio_demux_table *t; @@ -783,9 +783,9 @@ static unsigned char *iio_demux(struct iio_buffer *buffer, return buffer->demux_bounce; } -static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) +static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data) { - unsigned char *dataout = iio_demux(buffer, data); + const void *dataout = iio_demux(buffer, data); return buffer->access->store_to(buffer, dataout); } @@ -800,7 +800,7 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer) } -int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data) +int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) { int ret; struct iio_buffer *buf; diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 1bea41bcbdc6..538d4616e48f 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -95,7 +95,7 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length) } static int iio_store_to_kfifo(struct iio_buffer *r, - u8 *data) + const void *data) { int ret; struct iio_kfifo *kf = iio_to_kfifo(r); diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 2bac0eb8948d..e5507e999ed1 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -36,7 +36,7 @@ struct iio_buffer; * any of them not existing. **/ struct iio_buffer_access_funcs { - int (*store_to)(struct iio_buffer *buffer, u8 *data); + int (*store_to)(struct iio_buffer *buffer, const void *data); int (*read_first_n)(struct iio_buffer *buffer, size_t n, char __user *buf); @@ -81,7 +81,7 @@ struct iio_buffer { bool stufftoread; const struct attribute_group *attrs; struct list_head demux_list; - unsigned char *demux_bounce; + void *demux_bounce; struct list_head buffer_list; }; @@ -120,7 +120,7 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, * @indio_dev: iio_dev structure for device. * @data: Full scan. */ -int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data); +int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data); int iio_update_demux(struct iio_dev *indio_dev); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 833926c91aa8..2752b1fd12be 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -77,7 +77,7 @@ struct iio_cb_buffer; * fail. */ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, - int (*cb)(u8 *data, + int (*cb)(const void *data, void *private), void *private); /** -- cgit From 0736cfa8e5bb7ee1d7b7d28aabe634fd3f85cb92 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Aug 2013 21:40:51 -0700 Subject: Bluetooth: Introduce user channel flag for HCI devices This patch introduces a new user channel flag that allows to give full control of a HCI device to a user application. The kernel will stay away from the device and does not allow any further modifications of the device states. The existing raw flag is not used since it has a bit of unclear meaning due to its legacy. Using a new flag makes the code clearer. A device with the user channel flag set can still be enumerate using the legacy API, but it does not longer enumerate using the new management interface used by BlueZ 5 and beyond. This is intentional to not confuse users of modern systems. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_core.c | 39 ++++++++++++++++++++++++++++++++++++--- net/bluetooth/hci_sock.c | 15 +++++++++------ net/bluetooth/mgmt.c | 9 +++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index aaeaf0938ec0..128157db0680 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -109,6 +109,7 @@ enum { HCI_SERVICE_CACHE, HCI_DEBUG_KEYS, HCI_UNREGISTER, + HCI_USER_CHANNEL, HCI_LE_SCAN, HCI_SSP_ENABLED, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0976eabdafb0..0ee0f01d33df 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -984,6 +984,11 @@ int hci_inquiry(void __user *arg) if (!hdev) return -ENODEV; + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = -EBUSY; + goto done; + } + hci_dev_lock(hdev); if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { @@ -1177,7 +1182,8 @@ int hci_dev_open(__u16 dev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) set_bit(HCI_RAW, &hdev->flags); - if (!test_bit(HCI_RAW, &hdev->flags)) + if (!test_bit(HCI_RAW, &hdev->flags) && + !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) ret = __hci_init(hdev); } @@ -1188,6 +1194,7 @@ int hci_dev_open(__u16 dev) set_bit(HCI_UP, &hdev->flags); hci_notify(hdev, HCI_DEV_UP); if (!test_bit(HCI_SETUP, &hdev->dev_flags) && + !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 1); @@ -1324,11 +1331,17 @@ int hci_dev_close(__u16 dev) if (!hdev) return -ENODEV; + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = -EBUSY; + goto done; + } + if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) cancel_delayed_work(&hdev->power_off); err = hci_dev_do_close(hdev); +done: hci_dev_put(hdev); return err; } @@ -1349,6 +1362,11 @@ int hci_dev_reset(__u16 dev) goto done; } + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + ret = -EBUSY; + goto done; + } + /* Drop queues */ skb_queue_purge(&hdev->rx_q); skb_queue_purge(&hdev->cmd_q); @@ -1382,10 +1400,15 @@ int hci_dev_reset_stat(__u16 dev) if (!hdev) return -ENODEV; + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + ret = -EBUSY; + goto done; + } + memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); +done: hci_dev_put(hdev); - return ret; } @@ -1402,6 +1425,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) if (!hdev) return -ENODEV; + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = -EBUSY; + goto done; + } + switch (cmd) { case HCISETAUTH: err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, @@ -1460,6 +1488,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) break; } +done: hci_dev_put(hdev); return err; } @@ -1568,6 +1597,9 @@ static int hci_rfkill_set_block(void *data, bool blocked) BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) + return -EBUSY; + if (!blocked) return 0; @@ -3459,7 +3491,8 @@ static void hci_rx_work(struct work_struct *work) hci_send_to_sock(hdev, skb); } - if (test_bit(HCI_RAW, &hdev->flags)) { + if (test_bit(HCI_RAW, &hdev->flags) || + test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { kfree_skb(skb); continue; } diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index ab570387f505..59e68f199178 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -500,6 +500,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, if (!hdev) return -EBADFD; + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) + return -EBUSY; + switch (cmd) { case HCISETRAW: if (!capable(CAP_NET_ADMIN)) @@ -530,19 +533,19 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, if (!capable(CAP_NET_ADMIN)) return -EPERM; return hci_sock_blacklist_del(hdev, (void __user *) arg); - - default: - if (hdev->ioctl) - return hdev->ioctl(hdev, cmd, arg); - return -EINVAL; } + + if (hdev->ioctl) + return hdev->ioctl(hdev, cmd, arg); + + return -EINVAL; } static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct sock *sk = sock->sk; void __user *argp = (void __user *) arg; + struct sock *sk = sock->sk; int err; BT_DBG("cmd %x arg %lx", cmd, arg); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index fedc5399d465..3070e772db6b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -339,6 +339,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (test_bit(HCI_SETUP, &d->dev_flags)) continue; + if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) + continue; + if (!mgmt_valid_hdev(d)) continue; @@ -3320,6 +3323,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) MGMT_STATUS_INVALID_INDEX); goto done; } + + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = cmd_status(sk, index, opcode, + MGMT_STATUS_INVALID_INDEX); + goto done; + } } if (opcode >= ARRAY_SIZE(mgmt_handlers) || -- cgit From 23500189d7e03a071f0746f43f2cce875a62c91c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Aug 2013 21:40:52 -0700 Subject: Bluetooth: Introduce new HCI socket channel for user operation This patch introcuces a new HCI socket channel that allows user applications to take control over a specific HCI device. The application gains exclusive access to this device and forces the kernel to stay away and not manage it. In case of the management interface it will actually hide the device. Such operation is useful for security testing tools that need to operate underneath the Bluetooth stack and need full control over a device. The advantage here is that the kernel still provides the service of hardware abstraction and HCI level access. The use of Bluetooth drivers for hardware access also means that sniffing tools like btmon or hcidump are still working and the whole set of transaction can be traced with existing tools. With the new channel it is possible to send HCI commands, ACL and SCO data packets and receive HCI events, ACL and SCO packets from the device. The format follows the well established H:4 protocol. The new HCI user channel can only be established when a device has been through its setup routine and is currently powered down. This is enforced to not cause any problems with current operations. In addition only one user channel per HCI device is allowed. It is exclusive access for one user application. Access to this channel is limited to process with CAP_NET_RAW capability. Using this new facility does not require any external library or special ioctl or socket filters. Just create the socket and bind it. After that the file descriptor is ready to speak H:4 protocol. struct sockaddr_hci addr; int fd; fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); memset(&addr, 0, sizeof(addr)); addr.hci_family = AF_BLUETOOTH; addr.hci_dev = 0; addr.hci_channel = HCI_CHANNEL_USER; bind(fd, (struct sockaddr *) &addr, sizeof(addr)); The example shows on how to create a user channel for hci0 device. Error handling has been left out of the example. However with the limitations mentioned above it is advised to handle errors. Binding of the user cahnnel socket can fail for various reasons. Specifically if the device is currently activated by BlueZ or if the access permissions are not present. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_sock.c | 86 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 128157db0680..30c88b585c1b 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1571,6 +1571,7 @@ struct sockaddr_hci { #define HCI_DEV_NONE 0xffff #define HCI_CHANNEL_RAW 0 +#define HCI_CHANNEL_USER 1 #define HCI_CHANNEL_MONITOR 2 #define HCI_CHANNEL_CONTROL 3 diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 59e68f199178..c09e97638065 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -126,11 +126,20 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) if (skb->sk == sk) continue; - if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) - continue; - - if (is_filtered_packet(sk, skb)) + if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { + if (is_filtered_packet(sk, skb)) + continue; + } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { + if (!bt_cb(skb)->incoming) + continue; + if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT && + bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && + bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) + continue; + } else { + /* Don't send frame to other channel types */ continue; + } if (!skb_copy) { /* Create a private copy with headroom */ @@ -444,6 +453,12 @@ static int hci_sock_release(struct socket *sock) bt_sock_unlink(&hci_sk_list, sk); if (hdev) { + if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { + mgmt_index_added(hdev); + clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); + hci_dev_close(hdev->id); + } + atomic_dec(&hdev->promisc); hci_dev_put(hdev); } @@ -661,6 +676,56 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, hci_pi(sk)->hdev = hdev; break; + case HCI_CHANNEL_USER: + if (hci_pi(sk)->hdev) { + err = -EALREADY; + goto done; + } + + if (haddr.hci_dev == HCI_DEV_NONE) { + err = -EINVAL; + goto done; + } + + if (!capable(CAP_NET_RAW)) { + err = -EPERM; + goto done; + } + + hdev = hci_dev_get(haddr.hci_dev); + if (!hdev) { + err = -ENODEV; + goto done; + } + + if (test_bit(HCI_UP, &hdev->flags) || + test_bit(HCI_INIT, &hdev->flags) || + test_bit(HCI_SETUP, &hdev->dev_flags)) { + err = -EBUSY; + hci_dev_put(hdev); + goto done; + } + + if (test_and_set_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = -EUSERS; + hci_dev_put(hdev); + goto done; + } + + mgmt_index_removed(hdev); + + err = hci_dev_open(hdev->id); + if (err) { + clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); + hci_dev_put(hdev); + goto done; + } + + atomic_inc(&hdev->promisc); + + hci_pi(sk)->hdev = hdev; + break; + case HCI_CHANNEL_CONTROL: if (haddr.hci_dev != HCI_DEV_NONE) { err = -EINVAL; @@ -807,6 +872,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, case HCI_CHANNEL_RAW: hci_sock_cmsg(sk, msg, skb); break; + case HCI_CHANNEL_USER: case HCI_CHANNEL_CONTROL: case HCI_CHANNEL_MONITOR: sock_recv_timestamp(msg, sk, skb); @@ -841,6 +907,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, switch (hci_pi(sk)->channel) { case HCI_CHANNEL_RAW: + case HCI_CHANNEL_USER: break; case HCI_CHANNEL_CONTROL: err = mgmt_control(sk, msg, len); @@ -877,7 +944,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, skb_pull(skb, 1); skb->dev = (void *) hdev; - if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { + if (hci_pi(sk)->channel == HCI_CHANNEL_RAW && + bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { u16 opcode = get_unaligned_le16(skb->data); u16 ogf = hci_opcode_ogf(opcode); u16 ocf = hci_opcode_ocf(opcode); @@ -908,6 +976,14 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, goto drop; } + if (hci_pi(sk)->channel == HCI_CHANNEL_USER && + bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && + bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && + bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { + err = -EINVAL; + goto drop; + } + skb_queue_tail(&hdev->raw_q, skb); queue_work(hdev->workqueue, &hdev->tx_work); } -- cgit From 5ce0ba88650f2606244a761d92e2b725f4ab3583 Mon Sep 17 00:00:00 2001 From: Hiep Cao Minh Date: Tue, 3 Sep 2013 13:10:26 +0900 Subject: spi: rcar: add Renesas QSPI support on RSPI The R8A7790 has QSPI module which is very similar to RSPI. This patch adds into RSPI module together to supports QSPI module. Signed-off-by: Hiep Cao Minh Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- drivers/spi/spi-rspi.c | 183 ++++++++++++++++++++++++++++++++++++----------- include/linux/spi/rspi.h | 2 + 3 files changed, 145 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc40e1f..738facf90597 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -369,7 +369,7 @@ config SPI_PXA2XX_PCI config SPI_RSPI tristate "Renesas RSPI controller" - depends on SUPERH && SH_DMAE_BASE + depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE help SPI driver for Renesas RSPI blocks. diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8719206a03a0..4c8dbac11b42 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -59,6 +59,14 @@ #define RSPI_SPCMD6 0x1c #define RSPI_SPCMD7 0x1e +/*qspi only */ +#define QSPI_SPBFCR 0x18 +#define QSPI_SPBDCR 0x1a +#define QSPI_SPBMUL0 0x1c +#define QSPI_SPBMUL1 0x20 +#define QSPI_SPBMUL2 0x24 +#define QSPI_SPBMUL3 0x28 + /* SPCR */ #define SPCR_SPRIE 0x80 #define SPCR_SPE 0x40 @@ -126,6 +134,8 @@ #define SPCMD_LSBF 0x1000 #define SPCMD_SPB_MASK 0x0f00 #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) +#define SPCMD_SPB_8BIT 0x0000 /* qspi only */ +#define SPCMD_SPB_16BIT 0x0100 #define SPCMD_SPB_20BIT 0x0000 #define SPCMD_SPB_24BIT 0x0100 #define SPCMD_SPB_32BIT 0x0200 @@ -135,6 +145,10 @@ #define SPCMD_CPOL 0x0002 #define SPCMD_CPHA 0x0001 +/* SPBFCR */ +#define SPBFCR_TXRST 0x80 /* qspi only */ +#define SPBFCR_RXRST 0x40 /* qspi only */ + struct rspi_data { void __iomem *addr; u32 max_speed_hz; @@ -145,6 +159,7 @@ struct rspi_data { spinlock_t lock; struct clk *clk; unsigned char spsr; + const struct spi_ops *ops; /* for dmaengine */ struct dma_chan *chan_tx; @@ -165,6 +180,11 @@ static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset) iowrite16(data, rspi->addr + offset); } +static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset) +{ + iowrite32(data, rspi->addr + offset); +} + static u8 rspi_read8(struct rspi_data *rspi, u16 offset) { return ioread8(rspi->addr + offset); @@ -175,17 +195,98 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset) return ioread16(rspi->addr + offset); } -static unsigned char rspi_calc_spbr(struct rspi_data *rspi) +/* optional functions */ +struct spi_ops { + int (*set_config_register)(struct rspi_data *rspi, int access_size); +}; + +/* + * functions for RSPI + */ +static int rspi_set_config_register(struct rspi_data *rspi, int access_size) { - int tmp; - unsigned char spbr; + int spbr; + + /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ + rspi_write8(rspi, 0x00, RSPI_SPPCR); - tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; - spbr = clamp(tmp, 0, 255); + /* Sets transfer bit rate */ + spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; + rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); + + /* Sets number of frames to be used: 1 frame */ + rspi_write8(rspi, 0x00, RSPI_SPDCR); - return spbr; + /* Sets RSPCK, SSL, next-access delay value */ + rspi_write8(rspi, 0x00, RSPI_SPCKD); + rspi_write8(rspi, 0x00, RSPI_SSLND); + rspi_write8(rspi, 0x00, RSPI_SPND); + + /* Sets parity, interrupt mask */ + rspi_write8(rspi, 0x00, RSPI_SPCR2); + + /* Sets SPCMD */ + rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, + RSPI_SPCMD0); + + /* Sets RSPI mode */ + rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); + + return 0; } +/* + * functions for QSPI + */ +static int qspi_set_config_register(struct rspi_data *rspi, int access_size) +{ + u16 spcmd; + int spbr; + + /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ + rspi_write8(rspi, 0x00, RSPI_SPPCR); + + /* Sets transfer bit rate */ + spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); + rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); + + /* Sets number of frames to be used: 1 frame */ + rspi_write8(rspi, 0x00, RSPI_SPDCR); + + /* Sets RSPCK, SSL, next-access delay value */ + rspi_write8(rspi, 0x00, RSPI_SPCKD); + rspi_write8(rspi, 0x00, RSPI_SSLND); + rspi_write8(rspi, 0x00, RSPI_SPND); + + /* Data Length Setting */ + if (access_size == 8) + spcmd = SPCMD_SPB_8BIT; + else if (access_size == 16) + spcmd = SPCMD_SPB_16BIT; + else if (access_size == 32) + spcmd = SPCMD_SPB_32BIT; + + spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN; + + /* Resets transfer data length */ + rspi_write32(rspi, 0, QSPI_SPBMUL0); + + /* Resets transmit and receive buffer */ + rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); + /* Sets buffer to allow normal operation */ + rspi_write8(rspi, 0x00, QSPI_SPBFCR); + + /* Sets SPCMD */ + rspi_write16(rspi, spcmd, RSPI_SPCMD0); + + /* Enables SPI function in a master mode */ + rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); + + return 0; +} + +#define set_config_register(spi, n) spi->ops->set_config_register(spi, n) + static void rspi_enable_irq(struct rspi_data *rspi, u8 enable) { rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); @@ -220,35 +321,6 @@ static void rspi_negate_ssl(struct rspi_data *rspi) rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); } -static int rspi_set_config_register(struct rspi_data *rspi, int access_size) -{ - /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ - rspi_write8(rspi, 0x00, RSPI_SPPCR); - - /* Sets transfer bit rate */ - rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR); - - /* Sets number of frames to be used: 1 frame */ - rspi_write8(rspi, 0x00, RSPI_SPDCR); - - /* Sets RSPCK, SSL, next-access delay value */ - rspi_write8(rspi, 0x00, RSPI_SPCKD); - rspi_write8(rspi, 0x00, RSPI_SSLND); - rspi_write8(rspi, 0x00, RSPI_SPND); - - /* Sets parity, interrupt mask */ - rspi_write8(rspi, 0x00, RSPI_SPCR2); - - /* Sets SPCMD */ - rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, - RSPI_SPCMD0); - - /* Sets RSPI mode */ - rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); - - return 0; -} - static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, struct spi_transfer *t) { @@ -616,7 +688,7 @@ static int rspi_setup(struct spi_device *spi) spi->bits_per_word = 8; rspi->max_speed_hz = spi->max_speed_hz; - rspi_set_config_register(rspi, 8); + set_config_register(rspi, 8); return 0; } @@ -745,7 +817,16 @@ static int rspi_probe(struct platform_device *pdev) struct rspi_data *rspi; int ret, irq; char clk_name[16]; - + struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; + const struct spi_ops *ops; + const struct platform_device_id *id_entry = pdev->id_entry; + + ops = (struct spi_ops *)id_entry->driver_data; + /* ops parameter check */ + if (!ops->set_config_register) { + dev_err(&pdev->dev, "there is no set_config_register\n"); + return -ENODEV; + } /* get base addr */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(res == NULL)) { @@ -767,7 +848,7 @@ static int rspi_probe(struct platform_device *pdev) rspi = spi_master_get_devdata(master); platform_set_drvdata(pdev, rspi); - + rspi->ops = ops; rspi->master = master; rspi->addr = ioremap(res->start, resource_size(res)); if (rspi->addr == NULL) { @@ -776,7 +857,7 @@ static int rspi_probe(struct platform_device *pdev) goto error1; } - snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id); + snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id); rspi->clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(rspi->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); @@ -790,7 +871,10 @@ static int rspi_probe(struct platform_device *pdev) INIT_WORK(&rspi->ws, rspi_work); init_waitqueue_head(&rspi->wait); - master->num_chipselect = 2; + master->num_chipselect = rspi_pd->num_chipselect; + if (!master->num_chipselect) + master->num_chipselect = 2; /* default */ + master->bus_num = pdev->id; master->setup = rspi_setup; master->transfer = rspi_transfer; @@ -832,11 +916,28 @@ error1: return ret; } +static struct spi_ops rspi_ops = { + .set_config_register = rspi_set_config_register, +}; + +static struct spi_ops qspi_ops = { + .set_config_register = qspi_set_config_register, +}; + +static struct platform_device_id spi_driver_ids[] = { + { "rspi", (kernel_ulong_t)&rspi_ops }, + { "qspi", (kernel_ulong_t)&qspi_ops }, + {}, +}; + +MODULE_DEVICE_TABLE(platform, spi_driver_ids); + static struct platform_driver rspi_driver = { .probe = rspi_probe, .remove = rspi_remove, + .id_table = spi_driver_ids, .driver = { - .name = "rspi", + .name = "renesas_spi", .owner = THIS_MODULE, }, }; diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h index 900f0e328235..a25bd6f65e7f 100644 --- a/include/linux/spi/rspi.h +++ b/include/linux/spi/rspi.h @@ -26,6 +26,8 @@ struct rspi_plat_data { unsigned int dma_rx_id; unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */ + + u16 num_chipselect; }; #endif -- cgit From b33e46bcdc4e598d738ed12a5a7906be4e11d786 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 11:58:26 +0100 Subject: regulator: core: Provide managed regulator registration Many regulator drivers have a remove function that consists solely of calling regulator_unregister() so provide a devm_regulator_register() in order to allow this repeated code to be removed and help eliminate error handling code. Signed-off-by: Mark Brown --- Documentation/driver-model/devres.txt | 1 + drivers/regulator/core.c | 66 +++++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 5 +++ 3 files changed, 72 insertions(+) (limited to 'include') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index fcb34a5697ea..3d9c2a766230 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -283,6 +283,7 @@ REGULATOR devm_regulator_get() devm_regulator_put() devm_regulator_bulk_get() + devm_regulator_register() CLOCK devm_clk_get() diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a01b8b3b70ca..5f995d281672 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3492,6 +3492,44 @@ clean: } EXPORT_SYMBOL_GPL(regulator_register); +static void devm_rdev_release(struct device *dev, void *res) +{ + regulator_unregister(*(struct regulator_dev **)res); +} + +/** + * devm_regulator_register - Resource managed regulator_register() + * @regulator_desc: regulator to register + * @config: runtime configuration for regulator + * + * Called by regulator drivers to register a regulator. Returns a + * valid pointer to struct regulator_dev on success or an ERR_PTR() on + * error. The regulator will automaticall be released when the device + * is unbound. + */ +struct regulator_dev *devm_regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, + const struct regulator_config *config) +{ + struct regulator_dev **ptr, *rdev; + + ptr = devres_alloc(devm_rdev_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + rdev = regulator_register(regulator_desc, config); + if (!IS_ERR(rdev)) { + *ptr = rdev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return rdev; +} +EXPORT_SYMBOL_GPL(devm_regulator_register); + /** * regulator_unregister - unregister regulator * @rdev: regulator to unregister @@ -3521,6 +3559,34 @@ void regulator_unregister(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(regulator_unregister); +static int devm_rdev_match(struct device *dev, void *res, void *data) +{ + struct regulator_dev **r = res; + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + return *r == data; +} + +/** + * devm_regulator_unregister - Resource managed regulator_unregister() + * @regulator: regulator to free + * + * Unregister a regulator registered with devm_regulator_register(). + * Normally this function will not need to be called and the resource + * management code will ensure that the resource is freed. + */ +void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev) +{ + int rc; + + rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev); + if (rc != 0) + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_regulator_unregister); + /** * regulator_suspend_prepare - prepare regulators for system wide suspend * @state: system suspend state diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 67e13aa5a478..8474c7f88745 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -334,7 +334,12 @@ struct regulator_dev { struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, const struct regulator_config *config); +struct regulator_dev * +devm_regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, + const struct regulator_config *config); void regulator_unregister(struct regulator_dev *rdev); +void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev); int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); -- cgit From 4f0ac6dabf867095b31f851ba0d0ceaca2f87e2e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Sep 2013 19:51:47 +0100 Subject: regulator: core: Remove unused regulator_use_dummy_regulator() No boards have used this functionality and the new default of providing dummy regulators by default provides a better solution to the problem it was trying to solve. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 17 ----------------- include/linux/regulator/machine.h | 5 ----- 2 files changed, 22 deletions(-) (limited to 'include') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8fd170788c3e..ac3a864d3635 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -53,7 +53,6 @@ static LIST_HEAD(regulator_list); static LIST_HEAD(regulator_map_list); static LIST_HEAD(regulator_ena_gpio_list); static bool has_full_constraints; -static bool board_wants_dummy_regulator; static struct dentry *debugfs_root; @@ -3615,22 +3614,6 @@ void regulator_has_full_constraints(void) } EXPORT_SYMBOL_GPL(regulator_has_full_constraints); -/** - * regulator_use_dummy_regulator - Provide a dummy regulator when none is found - * - * Calling this function will cause the regulator API to provide a - * dummy regulator to consumers if no physical regulator is found, - * allowing most consumers to proceed as though a regulator were - * configured. This allows systems such as those with software - * controllable regulators for the CPU core only to be brought up more - * readily. - */ -void regulator_use_dummy_regulator(void) -{ - board_wants_dummy_regulator = true; -} -EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); - /** * rdev_get_drvdata - get rdev regulator driver data * @rdev: regulator diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 999b20ce06cf..a9f7c55a4d4d 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -193,15 +193,10 @@ int regulator_suspend_finish(void); #ifdef CONFIG_REGULATOR void regulator_has_full_constraints(void); -void regulator_use_dummy_regulator(void); #else static inline void regulator_has_full_constraints(void) { } - -static inline void regulator_use_dummy_regulator(void) -{ -} #endif #endif -- cgit From 666d5b4c742ba666eb68b467d777b7862f362ae5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 18:50:52 +0100 Subject: spi: core: Add devm_spi_register_master() Help simplify the cleanup code for SPI master drivers by providing a managed master registration function, ensuring that the master is automatically unregistered whenever the device is unbound. Signed-off-by: Mark Brown --- Documentation/driver-model/devres.txt | 3 +++ drivers/spi/spi.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 2 ++ 3 files changed, 40 insertions(+) (limited to 'include') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index fcb34a5697ea..84ea8216cc7d 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -302,3 +302,6 @@ PHY SLAVE DMA ENGINE devm_acpi_dma_controller_register() + +SPI + devm_spi_register_master() diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c60c068..a586ceb111fc 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1245,6 +1245,41 @@ done: } EXPORT_SYMBOL_GPL(spi_register_master); +static void devm_spi_unregister(struct device *dev, void *res) +{ + spi_unregister_master(*(struct spi_master **)res); +} + +/** + * dev_spi_register_master - register managed SPI master controller + * @dev: device managing SPI master + * @master: initialized master, originally from spi_alloc_master() + * Context: can sleep + * + * Register a SPI device as with spi_register_master() which will + * automatically be unregister + */ +int devm_spi_register_master(struct device *dev, struct spi_master *master) +{ + struct spi_master **ptr; + int ret; + + ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = spi_register_master(master); + if (ret != 0) { + *ptr = master; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_spi_register_master); + static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 887116dbce2c..4d634d66ba0b 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -434,6 +434,8 @@ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); extern int spi_register_master(struct spi_master *master); +extern int devm_spi_register_master(struct device *dev, + struct spi_master *master); extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); -- cgit From 4b08478422040ae8cb11acc15d51f1cdb0ac39c8 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 30 Aug 2013 06:01:49 -0700 Subject: Drop support for Renesas H8/300 (h8300) architecture H8/300 has been dead for several years, and the kernel for it has not compiled for ages. Drop support for it. Cc: Yoshinori Sato Acked-by: Greg Kroah-Hartman Signed-off-by: Guenter Roeck --- Documentation/scheduler/sched-arch.txt | 5 - arch/h8300/Kconfig | 108 ------ arch/h8300/Kconfig.cpu | 171 --------- arch/h8300/Kconfig.debug | 68 ---- arch/h8300/Kconfig.ide | 44 --- arch/h8300/Makefile | 71 ---- arch/h8300/README | 38 -- arch/h8300/boot/Makefile | 22 -- arch/h8300/boot/compressed/Makefile | 37 -- arch/h8300/boot/compressed/head.S | 47 --- arch/h8300/boot/compressed/misc.c | 180 --------- arch/h8300/boot/compressed/vmlinux.lds | 32 -- arch/h8300/boot/compressed/vmlinux.scr | 9 - arch/h8300/defconfig | 42 --- arch/h8300/include/asm/Kbuild | 8 - arch/h8300/include/asm/asm-offsets.h | 1 - arch/h8300/include/asm/atomic.h | 146 -------- arch/h8300/include/asm/barrier.h | 29 -- arch/h8300/include/asm/bitops.h | 211 ----------- arch/h8300/include/asm/bootinfo.h | 2 - arch/h8300/include/asm/bug.h | 12 - arch/h8300/include/asm/bugs.h | 16 - arch/h8300/include/asm/cache.h | 13 - arch/h8300/include/asm/cachectl.h | 14 - arch/h8300/include/asm/cacheflush.h | 40 -- arch/h8300/include/asm/checksum.h | 102 ------ arch/h8300/include/asm/cmpxchg.h | 60 --- arch/h8300/include/asm/cputime.h | 6 - arch/h8300/include/asm/current.h | 25 -- arch/h8300/include/asm/dbg.h | 2 - arch/h8300/include/asm/delay.h | 38 -- arch/h8300/include/asm/device.h | 7 - arch/h8300/include/asm/div64.h | 1 - arch/h8300/include/asm/dma.h | 15 - arch/h8300/include/asm/elf.h | 101 ------ arch/h8300/include/asm/emergency-restart.h | 6 - arch/h8300/include/asm/fb.h | 12 - arch/h8300/include/asm/flat.h | 26 -- arch/h8300/include/asm/fpu.h | 1 - arch/h8300/include/asm/ftrace.h | 1 - arch/h8300/include/asm/futex.h | 6 - arch/h8300/include/asm/gpio-internal.h | 52 --- arch/h8300/include/asm/hardirq.h | 19 - arch/h8300/include/asm/hw_irq.h | 1 - arch/h8300/include/asm/io.h | 358 ------------------ arch/h8300/include/asm/irq.h | 49 --- arch/h8300/include/asm/irq_regs.h | 1 - arch/h8300/include/asm/irqflags.h | 43 --- arch/h8300/include/asm/kdebug.h | 1 - arch/h8300/include/asm/kmap_types.h | 6 - arch/h8300/include/asm/local.h | 6 - arch/h8300/include/asm/local64.h | 1 - arch/h8300/include/asm/mc146818rtc.h | 9 - arch/h8300/include/asm/mmu_context.h | 32 -- arch/h8300/include/asm/mutex.h | 9 - arch/h8300/include/asm/page.h | 78 ---- arch/h8300/include/asm/page_offset.h | 3 - arch/h8300/include/asm/param.h | 9 - arch/h8300/include/asm/pci.h | 19 - arch/h8300/include/asm/percpu.h | 6 - arch/h8300/include/asm/pgalloc.h | 8 - arch/h8300/include/asm/pgtable.h | 73 ---- arch/h8300/include/asm/processor.h | 139 ------- arch/h8300/include/asm/ptrace.h | 33 -- arch/h8300/include/asm/regs267x.h | 336 ----------------- arch/h8300/include/asm/regs306x.h | 212 ----------- arch/h8300/include/asm/scatterlist.h | 6 - arch/h8300/include/asm/sections.h | 6 - arch/h8300/include/asm/segment.h | 49 --- arch/h8300/include/asm/sh_bios.h | 29 -- arch/h8300/include/asm/shm.h | 31 -- arch/h8300/include/asm/shmparam.h | 6 - arch/h8300/include/asm/signal.h | 24 -- arch/h8300/include/asm/smp.h | 1 - arch/h8300/include/asm/spinlock.h | 6 - arch/h8300/include/asm/string.h | 44 --- arch/h8300/include/asm/switch_to.h | 50 --- arch/h8300/include/asm/target_time.h | 4 - arch/h8300/include/asm/termios.h | 50 --- arch/h8300/include/asm/thread_info.h | 103 ------ arch/h8300/include/asm/timer.h | 25 -- arch/h8300/include/asm/timex.h | 19 - arch/h8300/include/asm/tlb.h | 8 - arch/h8300/include/asm/tlbflush.h | 55 --- arch/h8300/include/asm/topology.h | 6 - arch/h8300/include/asm/traps.h | 37 -- arch/h8300/include/asm/types.h | 9 - arch/h8300/include/asm/uaccess.h | 163 --------- arch/h8300/include/asm/ucontext.h | 12 - arch/h8300/include/asm/unaligned.h | 11 - arch/h8300/include/asm/unistd.h | 36 -- arch/h8300/include/asm/user.h | 75 ---- arch/h8300/include/asm/virtconvert.h | 20 - arch/h8300/include/uapi/asm/Kbuild | 34 -- arch/h8300/include/uapi/asm/auxvec.h | 4 - arch/h8300/include/uapi/asm/bitsperlong.h | 1 - arch/h8300/include/uapi/asm/byteorder.h | 6 - arch/h8300/include/uapi/asm/errno.h | 6 - arch/h8300/include/uapi/asm/fcntl.h | 11 - arch/h8300/include/uapi/asm/ioctl.h | 1 - arch/h8300/include/uapi/asm/ioctls.h | 8 - arch/h8300/include/uapi/asm/ipcbuf.h | 1 - arch/h8300/include/uapi/asm/kvm_para.h | 1 - arch/h8300/include/uapi/asm/mman.h | 1 - arch/h8300/include/uapi/asm/msgbuf.h | 31 -- arch/h8300/include/uapi/asm/param.h | 16 - arch/h8300/include/uapi/asm/poll.h | 11 - arch/h8300/include/uapi/asm/posix_types.h | 26 -- arch/h8300/include/uapi/asm/ptrace.h | 44 --- arch/h8300/include/uapi/asm/resource.h | 6 - arch/h8300/include/uapi/asm/sembuf.h | 25 -- arch/h8300/include/uapi/asm/setup.h | 6 - arch/h8300/include/uapi/asm/shmbuf.h | 42 --- arch/h8300/include/uapi/asm/sigcontext.h | 18 - arch/h8300/include/uapi/asm/siginfo.h | 6 - arch/h8300/include/uapi/asm/signal.h | 115 ------ arch/h8300/include/uapi/asm/socket.h | 79 ---- arch/h8300/include/uapi/asm/sockios.h | 13 - arch/h8300/include/uapi/asm/stat.h | 78 ---- arch/h8300/include/uapi/asm/statfs.h | 6 - arch/h8300/include/uapi/asm/swab.h | 10 - arch/h8300/include/uapi/asm/termbits.h | 201 ---------- arch/h8300/include/uapi/asm/termios.h | 44 --- arch/h8300/include/uapi/asm/types.h | 1 - arch/h8300/include/uapi/asm/unistd.h | 330 ----------------- arch/h8300/kernel/Makefile | 12 - arch/h8300/kernel/asm-offsets.c | 60 --- arch/h8300/kernel/entry.S | 402 -------------------- arch/h8300/kernel/gpio.c | 178 --------- arch/h8300/kernel/h8300_ksyms.c | 100 ----- arch/h8300/kernel/irq.c | 165 --------- arch/h8300/kernel/module.c | 75 ---- arch/h8300/kernel/process.c | 154 -------- arch/h8300/kernel/ptrace.c | 168 --------- arch/h8300/kernel/setup.c | 242 ------------ arch/h8300/kernel/signal.c | 444 ----------------------- arch/h8300/kernel/sys_h8300.c | 48 --- arch/h8300/kernel/syscalls.S | 338 ----------------- arch/h8300/kernel/time.c | 66 ---- arch/h8300/kernel/timer/Makefile | 6 - arch/h8300/kernel/timer/itu.c | 82 ----- arch/h8300/kernel/timer/timer16.c | 77 ---- arch/h8300/kernel/timer/timer8.c | 102 ------ arch/h8300/kernel/timer/tpu.c | 100 ----- arch/h8300/kernel/traps.c | 166 --------- arch/h8300/kernel/vmlinux.lds.S | 157 -------- arch/h8300/lib/Makefile | 5 - arch/h8300/lib/abs.S | 21 -- arch/h8300/lib/ashrdi3.c | 63 ---- arch/h8300/lib/checksum.c | 164 --------- arch/h8300/lib/memcpy.S | 84 ----- arch/h8300/lib/memset.S | 61 ---- arch/h8300/lib/romfs.S | 57 --- arch/h8300/mm/Makefile | 5 - arch/h8300/mm/fault.c | 56 --- arch/h8300/mm/init.c | 155 -------- arch/h8300/mm/kmap.c | 58 --- arch/h8300/mm/memory.c | 54 --- arch/h8300/platform/h8300h/Makefile | 7 - arch/h8300/platform/h8300h/aki3068net/Makefile | 5 - arch/h8300/platform/h8300h/aki3068net/crt0_ram.S | 110 ------ arch/h8300/platform/h8300h/generic/Makefile | 5 - arch/h8300/platform/h8300h/generic/crt0_ram.S | 107 ------ arch/h8300/platform/h8300h/generic/crt0_rom.S | 122 ------- arch/h8300/platform/h8300h/h8max/Makefile | 5 - arch/h8300/platform/h8300h/h8max/crt0_ram.S | 110 ------ arch/h8300/platform/h8300h/irq.c | 82 ----- arch/h8300/platform/h8300h/ptrace_h8300h.c | 284 --------------- arch/h8300/platform/h8s/Makefile | 7 - arch/h8300/platform/h8s/edosk2674/Makefile | 5 - arch/h8300/platform/h8s/edosk2674/crt0_ram.S | 130 ------- arch/h8300/platform/h8s/edosk2674/crt0_rom.S | 186 ---------- arch/h8300/platform/h8s/generic/Makefile | 5 - arch/h8300/platform/h8s/generic/crt0_ram.S | 127 ------- arch/h8300/platform/h8s/generic/crt0_rom.S | 128 ------- arch/h8300/platform/h8s/irq.c | 104 ------ arch/h8300/platform/h8s/ptrace_h8s.c | 84 ----- include/linux/serial_sci.h | 2 +- tools/testing/ktest/examples/crosstests.conf | 6 - 179 files changed, 1 insertion(+), 10890 deletions(-) delete mode 100644 arch/h8300/Kconfig delete mode 100644 arch/h8300/Kconfig.cpu delete mode 100644 arch/h8300/Kconfig.debug delete mode 100644 arch/h8300/Kconfig.ide delete mode 100644 arch/h8300/Makefile delete mode 100644 arch/h8300/README delete mode 100644 arch/h8300/boot/Makefile delete mode 100644 arch/h8300/boot/compressed/Makefile delete mode 100644 arch/h8300/boot/compressed/head.S delete mode 100644 arch/h8300/boot/compressed/misc.c delete mode 100644 arch/h8300/boot/compressed/vmlinux.lds delete mode 100644 arch/h8300/boot/compressed/vmlinux.scr delete mode 100644 arch/h8300/defconfig delete mode 100644 arch/h8300/include/asm/Kbuild delete mode 100644 arch/h8300/include/asm/asm-offsets.h delete mode 100644 arch/h8300/include/asm/atomic.h delete mode 100644 arch/h8300/include/asm/barrier.h delete mode 100644 arch/h8300/include/asm/bitops.h delete mode 100644 arch/h8300/include/asm/bootinfo.h delete mode 100644 arch/h8300/include/asm/bug.h delete mode 100644 arch/h8300/include/asm/bugs.h delete mode 100644 arch/h8300/include/asm/cache.h delete mode 100644 arch/h8300/include/asm/cachectl.h delete mode 100644 arch/h8300/include/asm/cacheflush.h delete mode 100644 arch/h8300/include/asm/checksum.h delete mode 100644 arch/h8300/include/asm/cmpxchg.h delete mode 100644 arch/h8300/include/asm/cputime.h delete mode 100644 arch/h8300/include/asm/current.h delete mode 100644 arch/h8300/include/asm/dbg.h delete mode 100644 arch/h8300/include/asm/delay.h delete mode 100644 arch/h8300/include/asm/device.h delete mode 100644 arch/h8300/include/asm/div64.h delete mode 100644 arch/h8300/include/asm/dma.h delete mode 100644 arch/h8300/include/asm/elf.h delete mode 100644 arch/h8300/include/asm/emergency-restart.h delete mode 100644 arch/h8300/include/asm/fb.h delete mode 100644 arch/h8300/include/asm/flat.h delete mode 100644 arch/h8300/include/asm/fpu.h delete mode 100644 arch/h8300/include/asm/ftrace.h delete mode 100644 arch/h8300/include/asm/futex.h delete mode 100644 arch/h8300/include/asm/gpio-internal.h delete mode 100644 arch/h8300/include/asm/hardirq.h delete mode 100644 arch/h8300/include/asm/hw_irq.h delete mode 100644 arch/h8300/include/asm/io.h delete mode 100644 arch/h8300/include/asm/irq.h delete mode 100644 arch/h8300/include/asm/irq_regs.h delete mode 100644 arch/h8300/include/asm/irqflags.h delete mode 100644 arch/h8300/include/asm/kdebug.h delete mode 100644 arch/h8300/include/asm/kmap_types.h delete mode 100644 arch/h8300/include/asm/local.h delete mode 100644 arch/h8300/include/asm/local64.h delete mode 100644 arch/h8300/include/asm/mc146818rtc.h delete mode 100644 arch/h8300/include/asm/mmu_context.h delete mode 100644 arch/h8300/include/asm/mutex.h delete mode 100644 arch/h8300/include/asm/page.h delete mode 100644 arch/h8300/include/asm/page_offset.h delete mode 100644 arch/h8300/include/asm/param.h delete mode 100644 arch/h8300/include/asm/pci.h delete mode 100644 arch/h8300/include/asm/percpu.h delete mode 100644 arch/h8300/include/asm/pgalloc.h delete mode 100644 arch/h8300/include/asm/pgtable.h delete mode 100644 arch/h8300/include/asm/processor.h delete mode 100644 arch/h8300/include/asm/ptrace.h delete mode 100644 arch/h8300/include/asm/regs267x.h delete mode 100644 arch/h8300/include/asm/regs306x.h delete mode 100644 arch/h8300/include/asm/scatterlist.h delete mode 100644 arch/h8300/include/asm/sections.h delete mode 100644 arch/h8300/include/asm/segment.h delete mode 100644 arch/h8300/include/asm/sh_bios.h delete mode 100644 arch/h8300/include/asm/shm.h delete mode 100644 arch/h8300/include/asm/shmparam.h delete mode 100644 arch/h8300/include/asm/signal.h delete mode 100644 arch/h8300/include/asm/smp.h delete mode 100644 arch/h8300/include/asm/spinlock.h delete mode 100644 arch/h8300/include/asm/string.h delete mode 100644 arch/h8300/include/asm/switch_to.h delete mode 100644 arch/h8300/include/asm/target_time.h delete mode 100644 arch/h8300/include/asm/termios.h delete mode 100644 arch/h8300/include/asm/thread_info.h delete mode 100644 arch/h8300/include/asm/timer.h delete mode 100644 arch/h8300/include/asm/timex.h delete mode 100644 arch/h8300/include/asm/tlb.h delete mode 100644 arch/h8300/include/asm/tlbflush.h delete mode 100644 arch/h8300/include/asm/topology.h delete mode 100644 arch/h8300/include/asm/traps.h delete mode 100644 arch/h8300/include/asm/types.h delete mode 100644 arch/h8300/include/asm/uaccess.h delete mode 100644 arch/h8300/include/asm/ucontext.h delete mode 100644 arch/h8300/include/asm/unaligned.h delete mode 100644 arch/h8300/include/asm/unistd.h delete mode 100644 arch/h8300/include/asm/user.h delete mode 100644 arch/h8300/include/asm/virtconvert.h delete mode 100644 arch/h8300/include/uapi/asm/Kbuild delete mode 100644 arch/h8300/include/uapi/asm/auxvec.h delete mode 100644 arch/h8300/include/uapi/asm/bitsperlong.h delete mode 100644 arch/h8300/include/uapi/asm/byteorder.h delete mode 100644 arch/h8300/include/uapi/asm/errno.h delete mode 100644 arch/h8300/include/uapi/asm/fcntl.h delete mode 100644 arch/h8300/include/uapi/asm/ioctl.h delete mode 100644 arch/h8300/include/uapi/asm/ioctls.h delete mode 100644 arch/h8300/include/uapi/asm/ipcbuf.h delete mode 100644 arch/h8300/include/uapi/asm/kvm_para.h delete mode 100644 arch/h8300/include/uapi/asm/mman.h delete mode 100644 arch/h8300/include/uapi/asm/msgbuf.h delete mode 100644 arch/h8300/include/uapi/asm/param.h delete mode 100644 arch/h8300/include/uapi/asm/poll.h delete mode 100644 arch/h8300/include/uapi/asm/posix_types.h delete mode 100644 arch/h8300/include/uapi/asm/ptrace.h delete mode 100644 arch/h8300/include/uapi/asm/resource.h delete mode 100644 arch/h8300/include/uapi/asm/sembuf.h delete mode 100644 arch/h8300/include/uapi/asm/setup.h delete mode 100644 arch/h8300/include/uapi/asm/shmbuf.h delete mode 100644 arch/h8300/include/uapi/asm/sigcontext.h delete mode 100644 arch/h8300/include/uapi/asm/siginfo.h delete mode 100644 arch/h8300/include/uapi/asm/signal.h delete mode 100644 arch/h8300/include/uapi/asm/socket.h delete mode 100644 arch/h8300/include/uapi/asm/sockios.h delete mode 100644 arch/h8300/include/uapi/asm/stat.h delete mode 100644 arch/h8300/include/uapi/asm/statfs.h delete mode 100644 arch/h8300/include/uapi/asm/swab.h delete mode 100644 arch/h8300/include/uapi/asm/termbits.h delete mode 100644 arch/h8300/include/uapi/asm/termios.h delete mode 100644 arch/h8300/include/uapi/asm/types.h delete mode 100644 arch/h8300/include/uapi/asm/unistd.h delete mode 100644 arch/h8300/kernel/Makefile delete mode 100644 arch/h8300/kernel/asm-offsets.c delete mode 100644 arch/h8300/kernel/entry.S delete mode 100644 arch/h8300/kernel/gpio.c delete mode 100644 arch/h8300/kernel/h8300_ksyms.c delete mode 100644 arch/h8300/kernel/irq.c delete mode 100644 arch/h8300/kernel/module.c delete mode 100644 arch/h8300/kernel/process.c delete mode 100644 arch/h8300/kernel/ptrace.c delete mode 100644 arch/h8300/kernel/setup.c delete mode 100644 arch/h8300/kernel/signal.c delete mode 100644 arch/h8300/kernel/sys_h8300.c delete mode 100644 arch/h8300/kernel/syscalls.S delete mode 100644 arch/h8300/kernel/time.c delete mode 100644 arch/h8300/kernel/timer/Makefile delete mode 100644 arch/h8300/kernel/timer/itu.c delete mode 100644 arch/h8300/kernel/timer/timer16.c delete mode 100644 arch/h8300/kernel/timer/timer8.c delete mode 100644 arch/h8300/kernel/timer/tpu.c delete mode 100644 arch/h8300/kernel/traps.c delete mode 100644 arch/h8300/kernel/vmlinux.lds.S delete mode 100644 arch/h8300/lib/Makefile delete mode 100644 arch/h8300/lib/abs.S delete mode 100644 arch/h8300/lib/ashrdi3.c delete mode 100644 arch/h8300/lib/checksum.c delete mode 100644 arch/h8300/lib/memcpy.S delete mode 100644 arch/h8300/lib/memset.S delete mode 100644 arch/h8300/lib/romfs.S delete mode 100644 arch/h8300/mm/Makefile delete mode 100644 arch/h8300/mm/fault.c delete mode 100644 arch/h8300/mm/init.c delete mode 100644 arch/h8300/mm/kmap.c delete mode 100644 arch/h8300/mm/memory.c delete mode 100644 arch/h8300/platform/h8300h/Makefile delete mode 100644 arch/h8300/platform/h8300h/aki3068net/Makefile delete mode 100644 arch/h8300/platform/h8300h/aki3068net/crt0_ram.S delete mode 100644 arch/h8300/platform/h8300h/generic/Makefile delete mode 100644 arch/h8300/platform/h8300h/generic/crt0_ram.S delete mode 100644 arch/h8300/platform/h8300h/generic/crt0_rom.S delete mode 100644 arch/h8300/platform/h8300h/h8max/Makefile delete mode 100644 arch/h8300/platform/h8300h/h8max/crt0_ram.S delete mode 100644 arch/h8300/platform/h8300h/irq.c delete mode 100644 arch/h8300/platform/h8300h/ptrace_h8300h.c delete mode 100644 arch/h8300/platform/h8s/Makefile delete mode 100644 arch/h8300/platform/h8s/edosk2674/Makefile delete mode 100644 arch/h8300/platform/h8s/edosk2674/crt0_ram.S delete mode 100644 arch/h8300/platform/h8s/edosk2674/crt0_rom.S delete mode 100644 arch/h8300/platform/h8s/generic/Makefile delete mode 100644 arch/h8300/platform/h8s/generic/crt0_ram.S delete mode 100644 arch/h8300/platform/h8s/generic/crt0_rom.S delete mode 100644 arch/h8300/platform/h8s/irq.c delete mode 100644 arch/h8300/platform/h8s/ptrace_h8s.c (limited to 'include') diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt index b1b8587b86f0..9290de703450 100644 --- a/Documentation/scheduler/sched-arch.txt +++ b/Documentation/scheduler/sched-arch.txt @@ -65,11 +65,6 @@ Possible arch/ problems Possible arch problems I found (and either tried to fix or didn't): -h8300 - Is such sleeping racy vs interrupts? (See #4a). - The H8/300 manual I found indicates yes, however disabling IRQs - over the sleep mean only NMIs can wake it up, so can't fix easily - without doing spin waiting. - ia64 - is safe_halt call racy vs interrupts? (does it sleep?) (See #4a) sh64 - Is sleeping racy vs interrupts? (See #4a) diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig deleted file mode 100644 index 24b1dc2564f1..000000000000 --- a/arch/h8300/Kconfig +++ /dev/null @@ -1,108 +0,0 @@ -config H8300 - bool - default y - select HAVE_IDE - select GENERIC_ATOMIC64 - select HAVE_UID16 - select VIRT_TO_BUS - select ARCH_WANT_IPC_PARSE_VERSION - select GENERIC_IRQ_SHOW - select GENERIC_CPU_DEVICES - select MODULES_USE_ELF_RELA - select OLD_SIGSUSPEND3 - select OLD_SIGACTION - select HAVE_UNDERSCORE_SYMBOL_PREFIX - -config MMU - bool - default n - -config SWAP - bool - default n - -config ZONE_DMA - bool - default y - -config FPU - bool - default n - -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - default n - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -config GENERIC_HWEIGHT - bool - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - -config GENERIC_BUG - bool - depends on BUG - -config TIME_LOW_RES - bool - default y - -config NO_IOPORT - def_bool y - -config NO_DMA - def_bool y - -config ISA - bool - default y - -config PCI - bool - default n - -config HZ - int - default 100 - -source "init/Kconfig" - -source "kernel/Kconfig.freezer" - -source "arch/h8300/Kconfig.cpu" - -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -endmenu - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "arch/h8300/Kconfig.ide" - -source "fs/Kconfig" - -source "arch/h8300/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu deleted file mode 100644 index cdee771460ed..000000000000 --- a/arch/h8300/Kconfig.cpu +++ /dev/null @@ -1,171 +0,0 @@ -menu "Processor type and features" - -choice - prompt "H8/300 platform" - default H8300H_GENERIC - -config H8300H_GENERIC - bool "H8/300H Generic" - help - H8/300H CPU Generic Hardware Support - -config H8300H_AKI3068NET - bool "AE-3068/69" - select H83068 - help - AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support - More Information. (Japanese Only) - - AE-3068/69 Evaluation Board Support - More Information. - - -config H8300H_H8MAX - bool "H8MAX" - select H83068 - help - H8MAX Evaluation Board Support - More Information. (Japanese Only) - - -config H8300H_SIM - bool "H8/300H Simulator" - select H83007 - help - GDB Simulator Support - More Information. - - -config H8S_GENERIC - bool "H8S Generic" - help - H8S CPU Generic Hardware Support - -config H8S_EDOSK2674 - bool "EDOSK-2674" - select H8S2678 - help - Renesas EDOSK-2674 Evaluation Board Support - More Information. - - - -config H8S_SIM - bool "H8S Simulator" - help - GDB Simulator Support - More Information. - - -endchoice - -choice - prompt "CPU Selection" - -config H83002 - bool "H8/3001,3002,3003" - depends on BROKEN - select CPU_H8300H - -config H83007 - bool "H8/3006,3007" - select CPU_H8300H - -config H83048 - bool "H8/3044,3045,3046,3047,3048,3052" - depends on BROKEN - select CPU_H8300H - -config H83068 - bool "H8/3065,3066,3067,3068,3069" - select CPU_H8300H - -config H8S2678 - bool "H8S/2670,2673,2674R,2675,2676" - select CPU_H8S - -endchoice - -config CPU_CLOCK - int "CPU Clock Frequency (/1KHz)" - default "20000" - help - CPU Clock Frequency divide to 1000 - -choice - prompt "Kernel executes from" - ---help--- - Choose the memory type that the kernel will be running in. - -config RAMKERNEL - bool "RAM" - help - The kernel will be resident in RAM when running. - -config ROMKERNEL - bool "ROM" - help - The kernel will be resident in FLASH/ROM when running. -endchoice - - -config CPU_H8300H - bool - depends on (H83002 || H83007 || H83048 || H83068) - default y - -config CPU_H8S - bool - depends on H8S2678 - default y - -choice - prompt "Timer" -config H8300_TIMER8 - bool "8bit timer (2ch cascade)" - depends on (H83007 || H83068 || H8S2678) - -config H8300_TIMER16 - bool "16bit timer" - depends on (H83007 || H83068) - -config H8300_ITU - bool "ITU" - depends on (H83002 || H83048) - -config H8300_TPU - bool "TPU" - depends on H8S2678 -endchoice - -if H8300_TIMER8 -choice - prompt "Timer Channel" -config H8300_TIMER8_CH0 - bool "Channel 0" -config H8300_TIMER8_CH2 - bool "Channel 2" - depends on CPU_H8300H -endchoice -endif - -config H8300_TIMER16_CH - int "16bit timer channel (0 - 2)" - depends on H8300_TIMER16 - range 0 2 - -config H8300_ITU_CH - int "ITU channel" - depends on H8300_ITU - range 0 4 - -config H8300_TPU_CH - int "TPU channel" - depends on H8300_TPU - range 0 4 - -source "kernel/Kconfig.preempt" - -source "mm/Kconfig" - -endmenu diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug deleted file mode 100644 index e8d1b236ad8c..000000000000 --- a/arch/h8300/Kconfig.debug +++ /dev/null @@ -1,68 +0,0 @@ -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config FULLDEBUG - bool "Full Symbolic/Source Debugging support" - help - Enable debugging symbols on kernel build. - -config HIGHPROFILE - bool "Use fast second timer for profiling" - help - Use a fast secondary clock to produce profiling information. - -config NO_KERNEL_MSG - bool "Suppress Kernel BUG Messages" - help - Do not output any debug BUG messages within the kernel. - -config GDB_MAGICPRINT - bool "Message Output for GDB MagicPrint service" - depends on (H8300H_SIM || H8S_SIM) - help - kernel messages output using MagicPrint service from GDB - -config SYSCALL_PRINT - bool "SystemCall trace print" - help - output history of systemcall - -config GDB_DEBUG - bool "Use gdb stub" - depends on (!H8300H_SIM && !H8S_SIM) - help - gdb stub exception support - -config SH_STANDARD_BIOS - bool "Use gdb protocol serial console" - depends on (!H8300H_SIM && !H8S_SIM) - help - serial console output using GDB protocol. - Require eCos/RedBoot - -config DEFAULT_CMDLINE - bool "Use builtin commandline" - default n - help - builtin kernel commandline enabled. - -config KERNEL_COMMAND - string "Buildin command string" - depends on DEFAULT_CMDLINE - help - builtin kernel commandline strings. - -config BLKDEV_RESERVE - bool "BLKDEV Reserved Memory" - default n - help - Reserved BLKDEV area. - -config BLKDEV_RESERVE_ADDRESS - hex 'start address' - depends on BLKDEV_RESERVE - help - BLKDEV start address. - -endmenu diff --git a/arch/h8300/Kconfig.ide b/arch/h8300/Kconfig.ide deleted file mode 100644 index a38a63054ac2..000000000000 --- a/arch/h8300/Kconfig.ide +++ /dev/null @@ -1,44 +0,0 @@ -# uClinux H8/300 Target Board Selection Menu (IDE) - -if (H8300H_AKI3068NET) -menu "IDE Extra configuration" - -config H8300_IDE_BASE - hex "IDE register base address" - depends on IDE - default 0 - help - IDE registers base address - -config H8300_IDE_ALT - hex "IDE register alternate address" - depends on IDE - default 0 - help - IDE alternate registers address - -config H8300_IDE_IRQ - int "IDE IRQ no" - depends on IDE - default 0 - help - IDE use IRQ no -endmenu -endif - -if (H8300H_H8MAX) -config H8300_IDE_BASE - hex - depends on IDE - default 0x200000 - -config H8300_IDE_ALT - hex - depends on IDE - default 0x60000c - -config H8300_IDE_IRQ - int - depends on IDE - default 5 -endif diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile deleted file mode 100644 index a556447877b4..000000000000 --- a/arch/h8300/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -# -# arch/h8300/Makefile -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# (C) Copyright 2002,2003 Yoshinori Sato -# - -platform-$(CONFIG_CPU_H8300H) := h8300h -platform-$(CONFIG_CPU_H8S) := h8s -PLATFORM := $(platform-y) - -board-$(CONFIG_H8300H_GENERIC) := generic -board-$(CONFIG_H8300H_AKI3068NET) := aki3068net -board-$(CONFIG_H8300H_H8MAX) := h8max -board-$(CONFIG_H8300H_SIM) := generic -board-$(CONFIG_H8S_GENERIC) := generic -board-$(CONFIG_H8S_EDOSK2674) := edosk2674 -board-$(CONFIG_H8S_SIM) := generic -BOARD := $(board-y) - -model-$(CONFIG_RAMKERNEL) := ram -model-$(CONFIG_ROMKERNEL) := rom -MODEL := $(model-y) - -cflags-$(CONFIG_CPU_H8300H) := -mh -ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf -cflags-$(CONFIG_CPU_H8S) := -ms -ldflags-$(CONFIG_CPU_H8S) := -mh8300self - -KBUILD_CFLAGS += $(cflags-y) -KBUILD_CFLAGS += -mint32 -fno-builtin -KBUILD_CFLAGS += -g -KBUILD_CFLAGS += -D__linux__ -KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" -KBUILD_AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y) -LDFLAGS += $(ldflags-y) - -CROSS_COMPILE = h8300-elf- -LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - -head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o - -core-y += arch/$(ARCH)/kernel/ \ - arch/$(ARCH)/mm/ -ifdef PLATFORM -core-y += arch/$(ARCH)/platform/$(PLATFORM)/ \ - arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/ -endif - -libs-y += arch/$(ARCH)/lib/ $(LIBGCC) - -boot := arch/h8300/boot - -export MODEL PLATFORM BOARD - -archmrproper: - -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -vmlinux.srec vmlinux.bin zImage: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -define archhelp - @echo 'vmlinux.bin - Create raw binary' - @echo 'vmlinux.srec - Create srec binary' - @echo 'zImage - Compressed kernel image' -endef diff --git a/arch/h8300/README b/arch/h8300/README deleted file mode 100644 index efa805fda19b..000000000000 --- a/arch/h8300/README +++ /dev/null @@ -1,38 +0,0 @@ -linux-2.6 for H8/300 README -Yoshinori Sato - -* Supported CPU -H8/300H and H8S - -* Supported Target -1.simulator of GDB - require patches. - -2.AE 3068/AE 3069 - more information - MICROTRONIQUE - Akizuki Denshi Tsusho Ltd. (Japanese Only) - -3.H8MAX - see http://ip-sol.jp/h8max/ (Japanese Only) - -4.EDOSK2674 - see http://www.eu.renesas.com/products/mpumcu/tool/edk/support/edosk2674.html - http://www.uclinux.org/pub/uClinux/ports/h8/HITACHI-EDOSK2674-HOWTO - http://www.azpower.com/H8-uClinux/ - -* Toolchain Version -gcc-3.1 or higher and patch -see arch/h8300/tools_patch/README -binutils-2.12 or higher -gdb-5.2 or higher -The environment that can compile a h8300-elf binary is necessary. - -* Userland Develop environment -used h8300-elf toolchains. -see http://www.uclinux.org/pub/uClinux/ports/h8/ - -* A few words of thanks -Porting to H8/300 serieses is support of Information-technology Promotion Agency, Japan. -I thank support. -and All developer/user. diff --git a/arch/h8300/boot/Makefile b/arch/h8300/boot/Makefile deleted file mode 100644 index 0bb62e064eea..000000000000 --- a/arch/h8300/boot/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# arch/h8300/boot/Makefile - -targets := vmlinux.srec vmlinux.bin zImage -subdir- := compressed - -OBJCOPYFLAGS_vmlinux.srec := -Osrec -OBJCOPYFLAGS_vmlinux.bin := -Obinary -OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S - -$(obj)/vmlinux.srec $(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' - -$(obj)/zImage: $(obj)/compressed/vmlinux FORCE - $(call if_changed,objcopy) - @echo 'Kernel: $@ is ready' - -$(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ - -CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec - diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile deleted file mode 100644 index a6c98fe3bbc3..000000000000 --- a/arch/h8300/boot/compressed/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# linux/arch/sh/boot/compressed/Makefile -# -# create a compressed vmlinux image from the original vmlinux -# - -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o -asflags-y := -traditional - -OBJECTS = $(obj)/head.o $(obj)/misc.o - -# -# IMAGE_OFFSET is the load offset of the compression loader -# Assign dummy values if these 2 variables are not defined, -# in order to suppress error message. -# -CONFIG_MEMORY_START ?= 0x00400000 -CONFIG_BOOT_LINK_OFFSET ?= 0x00140000 -IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)))) - -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds - -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE - $(call if_changed,ld) - @: - -$(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE - $(call if_changed,gzip) - -LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300 -T -OBJCOPYFLAGS := -O binary - -$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,ld) diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S deleted file mode 100644 index 10e9a2d1cc6c..000000000000 --- a/arch/h8300/boot/compressed/head.S +++ /dev/null @@ -1,47 +0,0 @@ -/* - * linux/arch/h8300/boot/compressed/head.S - * - * Copyright (C) 2006 Yoshinori Sato - */ - - .h8300h -#include - -#define SRAM_START 0xff4000 - - .section .text..startup - .global startup -startup: - mov.l #SRAM_START+0x8000, sp - mov.l #__sbss, er0 - mov.l #__ebss, er1 - sub.l er0, er1 - shlr er1 - shlr er1 - sub.l er2, er2 -1: - mov.l er2, @er0 - adds #4, er0 - dec.l #1, er1 - bne 1b - jsr @_decompress_kernel - jmp @0x400000 - - .align 9 -fake_headers_as_bzImage: - .word 0 - .ascii "HdrS" ; header signature - .word 0x0202 ; header version number (>= 0x0105) - ; or else old loadlin-1.5 will fail) - .word 0 ; default_switch - .word 0 ; SETUPSEG - .word 0x1000 - .word 0 ; pointing to kernel version string - .byte 0 ; = 0, old one (LILO, Loadlin, - ; 0xTV: T=0 for LILO - ; V = version - .byte 1 ; Load flags bzImage=1 - .word 0x8000 ; size to move, when setup is not - .long 0x100000 ; 0x100000 = default for big kernel - .long 0 ; address of loaded ramdisk image - .long 0 ; its size in bytes diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c deleted file mode 100644 index 4a1e3dd43948..000000000000 --- a/arch/h8300/boot/compressed/misc.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * arch/h8300/boot/compressed/misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * - * Adapted for h8300 by Yoshinori Sato 2006 - */ - -#include - -/* - * gzip declarations - */ - -#define OF(args) args -#define STATIC static - -#undef memset -#undef memcpy -#define memzero(s, n) memset ((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static int fill_inbuf(void); -static void flush_window(void); -static void error(char *m); - -extern char input_data[]; -extern int input_len; - -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; - -static void error(char *m); - -int puts(const char *); - -extern int _end; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -#define HEAP_SIZE 0x10000 - -#include "../../../../lib/inflate.c" - -#define SCR *((volatile unsigned char *)0xffff8a) -#define TDR *((volatile unsigned char *)0xffff8b) -#define SSR *((volatile unsigned char *)0xffff8c) - -int puts(const char *s) -{ - return 0; -} - -void* memset(void* s, int c, size_t n) -{ - int i; - char *ss = (char*)s; - - for (i=0;i> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; -} - -static void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while(1); /* Halt */ -} - -#define STACK_SIZE (4096) -long user_stack [STACK_SIZE]; -long* stack_start = &user_stack[STACK_SIZE]; - -void decompress_kernel(void) -{ - output_data = 0; - output_ptr = (unsigned long)0x400000; - free_mem_ptr = (unsigned long)&_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - - makecrc(); - puts("Uncompressing Linux... "); - gunzip(); - puts("Ok, booting the kernel.\n"); -} diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds deleted file mode 100644 index a0a3a0ed54ef..000000000000 --- a/arch/h8300/boot/compressed/vmlinux.lds +++ /dev/null @@ -1,32 +0,0 @@ -SECTIONS -{ - .text : - { - __stext = . ; - __text = .; - *(.text..startup) - *(.text) - __etext = . ; - } - - .rodata : - { - *(.rodata) - } - .data : - - { - __sdata = . ; - ___data_start = . ; - *(.data.*) - } - .bss : - { - . = ALIGN(0x4) ; - __sbss = . ; - *(.bss*) - . = ALIGN(0x4) ; - __ebss = . ; - __end = . ; - } -} diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr deleted file mode 100644 index a0f6962736e9..000000000000 --- a/arch/h8300/boot/compressed/vmlinux.scr +++ /dev/null @@ -1,9 +0,0 @@ -SECTIONS -{ - .data : { - _input_len = .; - LONG(_input_data_end - _input_data) _input_data = .; - *(.data) - _input_data_end = .; - } -} diff --git a/arch/h8300/defconfig b/arch/h8300/defconfig deleted file mode 100644 index 042425a02645..000000000000 --- a/arch/h8300/defconfig +++ /dev/null @@ -1,42 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_EXPERT=y -# CONFIG_UID16 is not set -# CONFIG_SYSCTL_SYSCALL is not set -# CONFIG_KALLSYMS is not set -# CONFIG_HOTPLUG is not set -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLOB=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_H83007=y -CONFIG_BINFMT_FLAT=y -CONFIG_BINFMT_ZFLAT=y -CONFIG_BINFMT_MISC=y -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_RAM=y -CONFIG_MTD_ROM=y -CONFIG_MTD_UCLINUX=y -# CONFIG_BLK_DEV is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_DNOTIFY is not set -CONFIG_ROMFS_FS=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_CRC32 is not set diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild deleted file mode 100644 index 8ada3cf0c98d..000000000000 --- a/arch/h8300/include/asm/Kbuild +++ /dev/null @@ -1,8 +0,0 @@ - -generic-y += clkdev.h -generic-y += exec.h -generic-y += linkage.h -generic-y += mmu.h -generic-y += module.h -generic-y += trace_clock.h -generic-y += xor.h diff --git a/arch/h8300/include/asm/asm-offsets.h b/arch/h8300/include/asm/asm-offsets.h deleted file mode 100644 index d370ee36a182..000000000000 --- a/arch/h8300/include/asm/asm-offsets.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h deleted file mode 100644 index 40901e353c21..000000000000 --- a/arch/h8300/include/asm/atomic.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef __ARCH_H8300_ATOMIC__ -#define __ARCH_H8300_ATOMIC__ - -#include -#include - -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc.. - */ - -#define ATOMIC_INIT(i) { (i) } - -#define atomic_read(v) (*(volatile int *)&(v)->counter) -#define atomic_set(v, i) (((v)->counter) = i) - -#include - -static __inline__ int atomic_add_return(int i, atomic_t *v) -{ - unsigned long flags; - int ret; - local_irq_save(flags); - ret = v->counter += i; - local_irq_restore(flags); - return ret; -} - -#define atomic_add(i, v) atomic_add_return(i, v) -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ int atomic_sub_return(int i, atomic_t *v) -{ - unsigned long flags; - int ret; - local_irq_save(flags); - ret = v->counter -= i; - local_irq_restore(flags); - return ret; -} - -#define atomic_sub(i, v) atomic_sub_return(i, v) -#define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0) - -static __inline__ int atomic_inc_return(atomic_t *v) -{ - unsigned long flags; - int ret; - local_irq_save(flags); - v->counter++; - ret = v->counter; - local_irq_restore(flags); - return ret; -} - -#define atomic_inc(v) atomic_inc_return(v) - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -static __inline__ int atomic_dec_return(atomic_t *v) -{ - unsigned long flags; - int ret; - local_irq_save(flags); - --v->counter; - ret = v->counter; - local_irq_restore(flags); - return ret; -} - -#define atomic_dec(v) atomic_dec_return(v) - -static __inline__ int atomic_dec_and_test(atomic_t *v) -{ - unsigned long flags; - int ret; - local_irq_save(flags); - --v->counter; - ret = v->counter; - local_irq_restore(flags); - return ret == 0; -} - -static inline int atomic_cmpxchg(atomic_t *v, int old, int new) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (likely(ret == old)) - v->counter = new; - local_irq_restore(flags); - return ret; -} - -static inline int __atomic_add_unless(atomic_t *v, int a, int u) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (ret != u) - v->counter += a; - local_irq_restore(flags); - return ret; -} - -static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v) -{ - __asm__ __volatile__("stc ccr,r1l\n\t" - "orc #0x80,ccr\n\t" - "mov.l %0,er0\n\t" - "and.l %1,er0\n\t" - "mov.l er0,%0\n\t" - "ldc r1l,ccr" - : "=m" (*v) : "g" (~(mask)) :"er0","er1"); -} - -static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v) -{ - __asm__ __volatile__("stc ccr,r1l\n\t" - "orc #0x80,ccr\n\t" - "mov.l %0,er0\n\t" - "or.l %1,er0\n\t" - "mov.l er0,%0\n\t" - "ldc r1l,ccr" - : "=m" (*v) : "g" (mask) :"er0","er1"); -} - -/* Atomic operations are already serializing */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#endif /* __ARCH_H8300_ATOMIC __ */ diff --git a/arch/h8300/include/asm/barrier.h b/arch/h8300/include/asm/barrier.h deleted file mode 100644 index 9e0aa9fc195d..000000000000 --- a/arch/h8300/include/asm/barrier.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _H8300_BARRIER_H -#define _H8300_BARRIER_H - -#define nop() asm volatile ("nop"::) - -/* - * Force strict CPU ordering. - * Not really required on H8... - */ -#define mb() asm volatile ("" : : :"memory") -#define rmb() asm volatile ("" : : :"memory") -#define wmb() asm volatile ("" : : :"memory") -#define set_mb(var, value) do { xchg(&var, value); } while (0) - -#define read_barrier_depends() do { } while (0) - -#ifdef CONFIG_SMP -#define smp_mb() mb() -#define smp_rmb() rmb() -#define smp_wmb() wmb() -#define smp_read_barrier_depends() read_barrier_depends() -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() do { } while(0) -#endif - -#endif /* _H8300_BARRIER_H */ diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h deleted file mode 100644 index eb34e0cd33d5..000000000000 --- a/arch/h8300/include/asm/bitops.h +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef _H8300_BITOPS_H -#define _H8300_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - * Copyright 2002, Yoshinori Sato - */ - -#include - -#ifdef __KERNEL__ - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -/* - * Function prototypes to keep gcc -Wall happy - */ - -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -static __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result; - - result = -1; - __asm__("1:\n\t" - "shlr.l %2\n\t" - "adds #1,%0\n\t" - "bcs 1b" - : "=r" (result) - : "0" (result),"r" (word)); - return result; -} - -#define H8300_GEN_BITOP_CONST(OP,BIT) \ - case BIT: \ - __asm__(OP " #" #BIT ",@%0"::"r"(b_addr):"memory"); \ - break; - -#define H8300_GEN_BITOP(FNAME,OP) \ -static __inline__ void FNAME(int nr, volatile unsigned long* addr) \ -{ \ - volatile unsigned char *b_addr; \ - b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - switch(nr & 7) { \ - H8300_GEN_BITOP_CONST(OP,0) \ - H8300_GEN_BITOP_CONST(OP,1) \ - H8300_GEN_BITOP_CONST(OP,2) \ - H8300_GEN_BITOP_CONST(OP,3) \ - H8300_GEN_BITOP_CONST(OP,4) \ - H8300_GEN_BITOP_CONST(OP,5) \ - H8300_GEN_BITOP_CONST(OP,6) \ - H8300_GEN_BITOP_CONST(OP,7) \ - } \ - } else { \ - __asm__(OP " %w0,@%1"::"r"(nr),"r"(b_addr):"memory"); \ - } \ -} - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() - -H8300_GEN_BITOP(set_bit ,"bset") -H8300_GEN_BITOP(clear_bit ,"bclr") -H8300_GEN_BITOP(change_bit,"bnot") -#define __set_bit(nr,addr) set_bit((nr),(addr)) -#define __clear_bit(nr,addr) clear_bit((nr),(addr)) -#define __change_bit(nr,addr) change_bit((nr),(addr)) - -#undef H8300_GEN_BITOP -#undef H8300_GEN_BITOP_CONST - -static __inline__ int test_bit(int nr, const unsigned long* addr) -{ - return (*((volatile unsigned char *)addr + - ((nr >> 3) ^ 3)) & (1UL << (nr & 7))) != 0; -} - -#define __test_bit(nr, addr) test_bit(nr, addr) - -#define H8300_GEN_TEST_BITOP_CONST_INT(OP,BIT) \ - case BIT: \ - __asm__("stc ccr,%w1\n\t" \ - "orc #0x80,ccr\n\t" \ - "bld #" #BIT ",@%4\n\t" \ - OP " #" #BIT ",@%4\n\t" \ - "rotxl.l %0\n\t" \ - "ldc %w1,ccr" \ - : "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr) \ - : "0" (retval),"r" (b_addr) \ - : "memory"); \ - break; - -#define H8300_GEN_TEST_BITOP_CONST(OP,BIT) \ - case BIT: \ - __asm__("bld #" #BIT ",@%3\n\t" \ - OP " #" #BIT ",@%3\n\t" \ - "rotxl.l %0\n\t" \ - : "=r"(retval),"=m"(*b_addr) \ - : "0" (retval),"r" (b_addr) \ - : "memory"); \ - break; - -#define H8300_GEN_TEST_BITOP(FNNAME,OP) \ -static __inline__ int FNNAME(int nr, volatile void * addr) \ -{ \ - int retval = 0; \ - char ccrsave; \ - volatile unsigned char *b_addr; \ - b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - switch(nr & 7) { \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,0) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,1) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,2) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,3) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,4) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,5) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,6) \ - H8300_GEN_TEST_BITOP_CONST_INT(OP,7) \ - } \ - } else { \ - __asm__("stc ccr,%w1\n\t" \ - "orc #0x80,ccr\n\t" \ - "btst %w5,@%4\n\t" \ - OP " %w5,@%4\n\t" \ - "beq 1f\n\t" \ - "inc.l #1,%0\n" \ - "1:\n\t" \ - "ldc %w1,ccr" \ - : "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr) \ - : "0" (retval),"r" (b_addr),"r"(nr) \ - : "memory"); \ - } \ - return retval; \ -} \ - \ -static __inline__ int __ ## FNNAME(int nr, volatile void * addr) \ -{ \ - int retval = 0; \ - volatile unsigned char *b_addr; \ - b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - switch(nr & 7) { \ - H8300_GEN_TEST_BITOP_CONST(OP,0) \ - H8300_GEN_TEST_BITOP_CONST(OP,1) \ - H8300_GEN_TEST_BITOP_CONST(OP,2) \ - H8300_GEN_TEST_BITOP_CONST(OP,3) \ - H8300_GEN_TEST_BITOP_CONST(OP,4) \ - H8300_GEN_TEST_BITOP_CONST(OP,5) \ - H8300_GEN_TEST_BITOP_CONST(OP,6) \ - H8300_GEN_TEST_BITOP_CONST(OP,7) \ - } \ - } else { \ - __asm__("btst %w4,@%3\n\t" \ - OP " %w4,@%3\n\t" \ - "beq 1f\n\t" \ - "inc.l #1,%0\n" \ - "1:" \ - : "=r"(retval),"=m"(*b_addr) \ - : "0" (retval),"r" (b_addr),"r"(nr) \ - : "memory"); \ - } \ - return retval; \ -} - -H8300_GEN_TEST_BITOP(test_and_set_bit, "bset") -H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr") -H8300_GEN_TEST_BITOP(test_and_change_bit,"bnot") -#undef H8300_GEN_TEST_BITOP_CONST -#undef H8300_GEN_TEST_BITOP_CONST_INT -#undef H8300_GEN_TEST_BITOP - -#include - -static __inline__ unsigned long __ffs(unsigned long word) -{ - unsigned long result; - - result = -1; - __asm__("1:\n\t" - "shlr.l %2\n\t" - "adds #1,%0\n\t" - "bcc 1b" - : "=r" (result) - : "0"(result),"r"(word)); - return result; -} - -#include -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -#include -#include -#include - -#endif /* _H8300_BITOPS_H */ diff --git a/arch/h8300/include/asm/bootinfo.h b/arch/h8300/include/asm/bootinfo.h deleted file mode 100644 index 5bed7e7aac0a..000000000000 --- a/arch/h8300/include/asm/bootinfo.h +++ /dev/null @@ -1,2 +0,0 @@ - -/* Nothing for h8300 */ diff --git a/arch/h8300/include/asm/bug.h b/arch/h8300/include/asm/bug.h deleted file mode 100644 index 1e1be8119935..000000000000 --- a/arch/h8300/include/asm/bug.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _H8300_BUG_H -#define _H8300_BUG_H - -/* always true */ -#define is_valid_bugaddr(addr) (1) - -#include - -struct pt_regs; -extern void die(const char *str, struct pt_regs *fp, unsigned long err); - -#endif diff --git a/arch/h8300/include/asm/bugs.h b/arch/h8300/include/asm/bugs.h deleted file mode 100644 index 1cb4afba6eb1..000000000000 --- a/arch/h8300/include/asm/bugs.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-h8300/bugs.h - * - * Copyright (C) 1994 Linus Torvalds - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -static void check_bugs(void) -{ -} diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h deleted file mode 100644 index 05887a1d80e5..000000000000 --- a/arch/h8300/include/asm/cache.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __ARCH_H8300_CACHE_H -#define __ARCH_H8300_CACHE_H - -/* bytes per L1 cache line */ -#define L1_CACHE_SHIFT 2 -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) - -/* m68k-elf-gcc 2.95.2 doesn't like these */ - -#define __cacheline_aligned -#define ____cacheline_aligned - -#endif diff --git a/arch/h8300/include/asm/cachectl.h b/arch/h8300/include/asm/cachectl.h deleted file mode 100644 index c464022d8e26..000000000000 --- a/arch/h8300/include/asm/cachectl.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _H8300_CACHECTL_H -#define _H8300_CACHECTL_H - -/* Definitions for the cacheflush system call. */ - -#define FLUSH_SCOPE_LINE 0 /* Flush a cache line */ -#define FLUSH_SCOPE_PAGE 0 /* Flush a page */ -#define FLUSH_SCOPE_ALL 0 /* Flush the whole cache -- superuser only */ - -#define FLUSH_CACHE_DATA 0 /* Writeback and flush data cache */ -#define FLUSH_CACHE_INSN 0 /* Flush instruction cache */ -#define FLUSH_CACHE_BOTH 0 /* Flush both caches */ - -#endif /* _H8300_CACHECTL_H */ diff --git a/arch/h8300/include/asm/cacheflush.h b/arch/h8300/include/asm/cacheflush.h deleted file mode 100644 index 4cf2df20c1ce..000000000000 --- a/arch/h8300/include/asm/cacheflush.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * (C) Copyright 2002, Yoshinori Sato - */ - -#ifndef _ASM_H8300_CACHEFLUSH_H -#define _ASM_H8300_CACHEFLUSH_H - -/* - * Cache handling functions - * No Cache memory all dummy functions - */ - -#define flush_cache_all() -#define flush_cache_mm(mm) -#define flush_cache_dup_mm(mm) do { } while (0) -#define flush_cache_range(vma,a,b) -#define flush_cache_page(vma,p,pfn) -#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 -#define flush_dcache_page(page) -#define flush_dcache_mmap_lock(mapping) -#define flush_dcache_mmap_unlock(mapping) -#define flush_icache() -#define flush_icache_page(vma,page) -#define flush_icache_range(start,len) -#define flush_cache_vmap(start, end) -#define flush_cache_vunmap(start, end) -#define cache_push_v(vaddr,len) -#define cache_push(paddr,len) -#define cache_clear(paddr,len) - -#define flush_dcache_range(a,b) - -#define flush_icache_user_range(vma,page,addr,len) - -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ - memcpy(dst, src, len) -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ - memcpy(dst, src, len) - -#endif /* _ASM_H8300_CACHEFLUSH_H */ diff --git a/arch/h8300/include/asm/checksum.h b/arch/h8300/include/asm/checksum.h deleted file mode 100644 index 98724e12508c..000000000000 --- a/arch/h8300/include/asm/checksum.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _H8300_CHECKSUM_H -#define _H8300_CHECKSUM_H - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -__wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * the same as csum_partial, but copies from src while it - * checksums - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ - -__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); - - -/* - * the same as csum_partial_copy, but copies from user space. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ - -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err); - -__sum16 ip_fast_csum(const void *iph, unsigned int ihl); - - -/* - * Fold a partial checksum - */ - -static inline __sum16 csum_fold(__wsum sum) -{ - __asm__("mov.l %0,er0\n\t" - "add.w e0,r0\n\t" - "xor.w e0,e0\n\t" - "rotxl.w e0\n\t" - "add.w e0,r0\n\t" - "sub.w e0,e0\n\t" - "mov.l er0,%0" - : "=r"(sum) - : "0"(sum) - : "er0"); - return (__force __sum16)~sum; -} - - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ - -static inline __wsum -csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, - unsigned short proto, __wsum sum) -{ - __asm__ ("sub.l er0,er0\n\t" - "add.l %2,%0\n\t" - "addx #0,r0l\n\t" - "add.l %3,%0\n\t" - "addx #0,r0l\n\t" - "add.l %4,%0\n\t" - "addx #0,r0l\n\t" - "add.l er0,%0\n\t" - "bcc 1f\n\t" - "inc.l #1,%0\n" - "1:" - : "=&r" (sum) - : "0" (sum), "r" (daddr), "r" (saddr), "r" (len + proto) - :"er0"); - return sum; -} - -static inline __sum16 -csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, - unsigned short proto, __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ - -extern __sum16 ip_compute_csum(const void *buff, int len); - -#endif /* _H8300_CHECKSUM_H */ diff --git a/arch/h8300/include/asm/cmpxchg.h b/arch/h8300/include/asm/cmpxchg.h deleted file mode 100644 index cdb203ef681f..000000000000 --- a/arch/h8300/include/asm/cmpxchg.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __ARCH_H8300_CMPXCHG__ -#define __ARCH_H8300_CMPXCHG__ - -#include - -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile struct __xchg_dummy *)(x)) - -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - unsigned long tmp, flags; - - local_irq_save(flags); - - switch (size) { - case 1: - __asm__ __volatile__ - ("mov.b %2,%0\n\t" - "mov.b %1,%2" - : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 2: - __asm__ __volatile__ - ("mov.w %2,%0\n\t" - "mov.w %1,%2" - : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 4: - __asm__ __volatile__ - ("mov.l %2,%0\n\t" - "mov.l %1,%2" - : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); - break; - default: - tmp = 0; - } - local_irq_restore(flags); - return tmp; -} - -#include - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ - (unsigned long)(n), sizeof(*(ptr)))) -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) - -#ifndef CONFIG_SMP -#include -#endif - -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - -#endif /* __ARCH_H8300_CMPXCHG__ */ diff --git a/arch/h8300/include/asm/cputime.h b/arch/h8300/include/asm/cputime.h deleted file mode 100644 index 092e187c7b08..000000000000 --- a/arch/h8300/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __H8300_CPUTIME_H -#define __H8300_CPUTIME_H - -#include - -#endif /* __H8300_CPUTIME_H */ diff --git a/arch/h8300/include/asm/current.h b/arch/h8300/include/asm/current.h deleted file mode 100644 index 57d74ee55a14..000000000000 --- a/arch/h8300/include/asm/current.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _H8300_CURRENT_H -#define _H8300_CURRENT_H -/* - * current.h - * (C) Copyright 2000, Lineo, David McCullough - * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) - * - * rather than dedicate a register (as the m68k source does), we - * just keep a global, we should probably just change it all to be - * current and lose _current_task. - */ - -#include -#include - -struct task_struct; - -static inline struct task_struct *get_current(void) -{ - return(current_thread_info()->task); -} - -#define current get_current() - -#endif /* _H8300_CURRENT_H */ diff --git a/arch/h8300/include/asm/dbg.h b/arch/h8300/include/asm/dbg.h deleted file mode 100644 index 2c6d1cbcf736..000000000000 --- a/arch/h8300/include/asm/dbg.h +++ /dev/null @@ -1,2 +0,0 @@ -#define DEBUG 1 -#define BREAK asm volatile ("trap #3") diff --git a/arch/h8300/include/asm/delay.h b/arch/h8300/include/asm/delay.h deleted file mode 100644 index 743beba70f82..000000000000 --- a/arch/h8300/include/asm/delay.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _H8300_DELAY_H -#define _H8300_DELAY_H - -#include - -/* - * Copyright (C) 2002 Yoshinori Sato - * - * Delay routines, using a pre-computed "loops_per_second" value. - */ - -static inline void __delay(unsigned long loops) -{ - __asm__ __volatile__ ("1:\n\t" - "dec.l #1,%0\n\t" - "bne 1b" - :"=r" (loops):"0"(loops)); -} - -/* - * Use only for very small delays ( < 1 msec). Should probably use a - * lookup table, really, as the multiplications take much too long with - * short delays. This is a "reasonable" implementation, though (and the - * first constant multiplications gets optimized away if the delay is - * a constant) - */ - -extern unsigned long loops_per_jiffy; - -static inline void udelay(unsigned long usecs) -{ - usecs *= 4295; /* 2**32 / 1000000 */ - usecs /= (loops_per_jiffy*HZ); - if (usecs) - __delay(usecs); -} - -#endif /* _H8300_DELAY_H */ diff --git a/arch/h8300/include/asm/device.h b/arch/h8300/include/asm/device.h deleted file mode 100644 index d8f9872b0e2d..000000000000 --- a/arch/h8300/include/asm/device.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Arch specific extensions to struct device - * - * This file is released under the GPLv2 - */ -#include - diff --git a/arch/h8300/include/asm/div64.h b/arch/h8300/include/asm/div64.h deleted file mode 100644 index 6cd978cefb28..000000000000 --- a/arch/h8300/include/asm/div64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/asm/dma.h b/arch/h8300/include/asm/dma.h deleted file mode 100644 index 3edbaaaedf5b..000000000000 --- a/arch/h8300/include/asm/dma.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _H8300_DMA_H -#define _H8300_DMA_H - - -/* - * Set number of channels of DMA on ColdFire for different implementations. - */ -#define MAX_DMA_CHANNELS 0 -#define MAX_DMA_ADDRESS PAGE_OFFSET - -/* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, const char *device_id); /* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr); /* release it again */ - -#endif /* _H8300_DMA_H */ diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h deleted file mode 100644 index 6db71248a82f..000000000000 --- a/arch/h8300/include/asm/elf.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __ASMH8300_ELF_H -#define __ASMH8300_ELF_H - -/* - * ELF register definitions.. - */ - -#include -#include - -typedef unsigned long elf_greg_t; - -#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -typedef unsigned long elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ((x)->e_machine == EM_H8_300) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB -#define ELF_ARCH EM_H8_300 -#if defined(__H8300H__) -#define ELF_CORE_EFLAGS 0x810000 -#endif -#if defined(__H8300S__) -#define ELF_CORE_EFLAGS 0x820000 -#endif - -#define ELF_PLAT_INIT(_r) _r->er1 = 0 - -#define ELF_EXEC_PAGESIZE 4096 - -/* This is the location that an ET_DYN program is loaded if exec'ed. Typical - use of this is to invoke "./ld.so someprog" to test out a new version of - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -#define ELF_ET_DYN_BASE 0xD0000000UL - -/* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. */ - -#define ELF_HWCAP (0) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. */ - -#define ELF_PLATFORM (NULL) - -#define R_H8_NONE 0 -#define R_H8_DIR32 1 -#define R_H8_DIR32_28 2 -#define R_H8_DIR32_24 3 -#define R_H8_DIR32_16 4 -#define R_H8_DIR32U 6 -#define R_H8_DIR32U_28 7 -#define R_H8_DIR32U_24 8 -#define R_H8_DIR32U_20 9 -#define R_H8_DIR32U_16 10 -#define R_H8_DIR24 11 -#define R_H8_DIR24_20 12 -#define R_H8_DIR24_16 13 -#define R_H8_DIR24U 14 -#define R_H8_DIR24U_20 15 -#define R_H8_DIR24U_16 16 -#define R_H8_DIR16 17 -#define R_H8_DIR16U 18 -#define R_H8_DIR16S_32 19 -#define R_H8_DIR16S_28 20 -#define R_H8_DIR16S_24 21 -#define R_H8_DIR16S_20 22 -#define R_H8_DIR16S 23 -#define R_H8_DIR8 24 -#define R_H8_DIR8U 25 -#define R_H8_DIR8Z_32 26 -#define R_H8_DIR8Z_28 27 -#define R_H8_DIR8Z_24 28 -#define R_H8_DIR8Z_20 29 -#define R_H8_DIR8Z_16 30 -#define R_H8_PCREL16 31 -#define R_H8_PCREL8 32 -#define R_H8_BPOS 33 -#define R_H8_PCREL32 34 -#define R_H8_GOT32O 35 -#define R_H8_GOT16O 36 -#define R_H8_DIR16A8 59 -#define R_H8_DIR16R8 60 -#define R_H8_DIR24A8 61 -#define R_H8_DIR24R8 62 -#define R_H8_DIR32A16 63 -#define R_H8_ABS32 65 -#define R_H8_ABS32A16 127 - -#endif diff --git a/arch/h8300/include/asm/emergency-restart.h b/arch/h8300/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42e..000000000000 --- a/arch/h8300/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/h8300/include/asm/fb.h b/arch/h8300/include/asm/fb.h deleted file mode 100644 index c7df38030992..000000000000 --- a/arch/h8300/include/asm/fb.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ASM_FB_H_ -#define _ASM_FB_H_ -#include - -#define fb_pgprotect(...) do {} while (0) - -static inline int fb_is_primary_device(struct fb_info *info) -{ - return 0; -} - -#endif /* _ASM_FB_H_ */ diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h deleted file mode 100644 index bd12b31b90e6..000000000000 --- a/arch/h8300/include/asm/flat.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * include/asm-h8300/flat.h -- uClinux flat-format executables - */ - -#ifndef __H8300_FLAT_H__ -#define __H8300_FLAT_H__ - -#define flat_argvp_envp_on_stack() 1 -#define flat_old_ram_flag(flags) 1 -#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_set_persistent(relval, p) 0 - -/* - * on the H8 a couple of the relocations have an instruction in the - * top byte. As there can only be 24bits of address space, we just - * always preserve that 8bits at the top, when it isn't an instruction - * is is 0 (davidm@snapgear.com) - */ - -#define flat_get_relocate_addr(rel) (rel) -#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ - (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) -#define flat_put_addr_at_rp(rp, addr, rel) \ - put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) - -#endif /* __H8300_FLAT_H__ */ diff --git a/arch/h8300/include/asm/fpu.h b/arch/h8300/include/asm/fpu.h deleted file mode 100644 index 4fc416e80bef..000000000000 --- a/arch/h8300/include/asm/fpu.h +++ /dev/null @@ -1 +0,0 @@ -/* Nothing do */ diff --git a/arch/h8300/include/asm/ftrace.h b/arch/h8300/include/asm/ftrace.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/h8300/include/asm/ftrace.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/h8300/include/asm/futex.h b/arch/h8300/include/asm/futex.h deleted file mode 100644 index 6a332a9f099c..000000000000 --- a/arch/h8300/include/asm/futex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#include - -#endif diff --git a/arch/h8300/include/asm/gpio-internal.h b/arch/h8300/include/asm/gpio-internal.h deleted file mode 100644 index a714f0c0efbc..000000000000 --- a/arch/h8300/include/asm/gpio-internal.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _H8300_GPIO_H -#define _H8300_GPIO_H - -#define H8300_GPIO_P1 0 -#define H8300_GPIO_P2 1 -#define H8300_GPIO_P3 2 -#define H8300_GPIO_P4 3 -#define H8300_GPIO_P5 4 -#define H8300_GPIO_P6 5 -#define H8300_GPIO_P7 6 -#define H8300_GPIO_P8 7 -#define H8300_GPIO_P9 8 -#define H8300_GPIO_PA 9 -#define H8300_GPIO_PB 10 -#define H8300_GPIO_PC 11 -#define H8300_GPIO_PD 12 -#define H8300_GPIO_PE 13 -#define H8300_GPIO_PF 14 -#define H8300_GPIO_PG 15 -#define H8300_GPIO_PH 16 - -#define H8300_GPIO_B7 0x80 -#define H8300_GPIO_B6 0x40 -#define H8300_GPIO_B5 0x20 -#define H8300_GPIO_B4 0x10 -#define H8300_GPIO_B3 0x08 -#define H8300_GPIO_B2 0x04 -#define H8300_GPIO_B1 0x02 -#define H8300_GPIO_B0 0x01 - -#define H8300_GPIO_INPUT 0 -#define H8300_GPIO_OUTPUT 1 - -#define H8300_GPIO_RESERVE(port, bits) \ - h8300_reserved_gpio(port, bits) - -#define H8300_GPIO_FREE(port, bits) \ - h8300_free_gpio(port, bits) - -#define H8300_GPIO_DDR(port, bit, dir) \ - h8300_set_gpio_dir(((port) << 8) | (bit), dir) - -#define H8300_GPIO_GETDIR(port, bit) \ - h8300_get_gpio_dir(((port) << 8) | (bit)) - -extern int h8300_reserved_gpio(int port, int bits); -extern int h8300_free_gpio(int port, int bits); -extern int h8300_set_gpio_dir(int port_bit, int dir); -extern int h8300_get_gpio_dir(int port_bit); -extern int h8300_init_gpio(void); - -#endif diff --git a/arch/h8300/include/asm/hardirq.h b/arch/h8300/include/asm/hardirq.h deleted file mode 100644 index c2e1aa0f0d14..000000000000 --- a/arch/h8300/include/asm/hardirq.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __H8300_HARDIRQ_H -#define __H8300_HARDIRQ_H - -#include - -#define HARDIRQ_BITS 8 - -/* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - -#include - -#endif diff --git a/arch/h8300/include/asm/hw_irq.h b/arch/h8300/include/asm/hw_irq.h deleted file mode 100644 index d75a5a1119e8..000000000000 --- a/arch/h8300/include/asm/hw_irq.h +++ /dev/null @@ -1 +0,0 @@ -/* Do Nothing */ diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h deleted file mode 100644 index c1a8df22080f..000000000000 --- a/arch/h8300/include/asm/io.h +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef _H8300_IO_H -#define _H8300_IO_H - -#ifdef __KERNEL__ - -#include - -#if defined(CONFIG_H83007) || defined(CONFIG_H83068) -#include -#elif defined(CONFIG_H8S2678) -#include -#else -#error UNKNOWN CPU TYPE -#endif - - -/* - * These are for ISA/PCI shared memory _only_ and should never be used - * on any other type of memory, including Zorro memory. They are meant to - * access the bus in the bus byte order which is little-endian!. - * - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the m68k architecture, we just read/write the - * memory location directly. - */ -/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates - * two accesses to memory, which may be undesirable for some devices. - */ - -/* - * swap functions are sometimes needed to interface little-endian hardware - */ - -static inline unsigned short _swapw(volatile unsigned short v) -{ -#ifndef H8300_IO_NOSWAP - unsigned short r; - __asm__("xor.b %w0,%x0\n\t" - "xor.b %x0,%w0\n\t" - "xor.b %w0,%x0" - :"=r"(r) - :"0"(v)); - return r; -#else - return v; -#endif -} - -static inline unsigned long _swapl(volatile unsigned long v) -{ -#ifndef H8300_IO_NOSWAP - unsigned long r; - __asm__("xor.b %w0,%x0\n\t" - "xor.b %x0,%w0\n\t" - "xor.b %w0,%x0\n\t" - "xor.w %e0,%f0\n\t" - "xor.w %f0,%e0\n\t" - "xor.w %e0,%f0\n\t" - "xor.b %w0,%x0\n\t" - "xor.b %x0,%w0\n\t" - "xor.b %w0,%x0" - :"=r"(r) - :"0"(v)); - return r; -#else - return v; -#endif -} - -#define readb(addr) \ - ({ unsigned char __v = \ - *(volatile unsigned char *)((unsigned long)(addr) & 0x00ffffff); \ - __v; }) -#define readw(addr) \ - ({ unsigned short __v = \ - *(volatile unsigned short *)((unsigned long)(addr) & 0x00ffffff); \ - __v; }) -#define readl(addr) \ - ({ unsigned long __v = \ - *(volatile unsigned long *)((unsigned long)(addr) & 0x00ffffff); \ - __v; }) - -#define writeb(b,addr) (void)((*(volatile unsigned char *) \ - ((unsigned long)(addr) & 0x00ffffff)) = (b)) -#define writew(b,addr) (void)((*(volatile unsigned short *) \ - ((unsigned long)(addr) & 0x00ffffff)) = (b)) -#define writel(b,addr) (void)((*(volatile unsigned long *) \ - ((unsigned long)(addr) & 0x00ffffff)) = (b)) -#define readb_relaxed(addr) readb(addr) -#define readw_relaxed(addr) readw(addr) -#define readl_relaxed(addr) readl(addr) - -#define __raw_readb readb -#define __raw_readw readw -#define __raw_readl readl -#define __raw_writeb writeb -#define __raw_writew writew -#define __raw_writel writel - -static inline int h8300_buswidth(unsigned int addr) -{ - return (*(volatile unsigned char *)ABWCR & (1 << ((addr >> 21) & 7))) == 0; -} - -static inline void io_outsb(unsigned int addr, const void *buf, int len) -{ - volatile unsigned char *ap_b = (volatile unsigned char *) addr; - volatile unsigned short *ap_w = (volatile unsigned short *) addr; - unsigned char *bp = (unsigned char *) buf; - - if(h8300_buswidth(addr) && (addr & 1)) { - while (len--) - *ap_w = *bp++; - } else { - while (len--) - *ap_b = *bp++; - } -} - -static inline void io_outsw(unsigned int addr, const void *buf, int len) -{ - volatile unsigned short *ap = (volatile unsigned short *) addr; - unsigned short *bp = (unsigned short *) buf; - while (len--) - *ap = _swapw(*bp++); -} - -static inline void io_outsl(unsigned int addr, const void *buf, int len) -{ - volatile unsigned long *ap = (volatile unsigned long *) addr; - unsigned long *bp = (unsigned long *) buf; - while (len--) - *ap = _swapl(*bp++); -} - -static inline void io_outsw_noswap(unsigned int addr, const void *buf, int len) -{ - volatile unsigned short *ap = (volatile unsigned short *) addr; - unsigned short *bp = (unsigned short *) buf; - while (len--) - *ap = *bp++; -} - -static inline void io_outsl_noswap(unsigned int addr, const void *buf, int len) -{ - volatile unsigned long *ap = (volatile unsigned long *) addr; - unsigned long *bp = (unsigned long *) buf; - while (len--) - *ap = *bp++; -} - -static inline void io_insb(unsigned int addr, void *buf, int len) -{ - volatile unsigned char *ap_b; - volatile unsigned short *ap_w; - unsigned char *bp = (unsigned char *) buf; - - if(h8300_buswidth(addr)) { - ap_w = (volatile unsigned short *)(addr & ~1); - while (len--) - *bp++ = *ap_w & 0xff; - } else { - ap_b = (volatile unsigned char *)addr; - while (len--) - *bp++ = *ap_b; - } -} - -static inline void io_insw(unsigned int addr, void *buf, int len) -{ - volatile unsigned short *ap = (volatile unsigned short *) addr; - unsigned short *bp = (unsigned short *) buf; - while (len--) - *bp++ = _swapw(*ap); -} - -static inline void io_insl(unsigned int addr, void *buf, int len) -{ - volatile unsigned long *ap = (volatile unsigned long *) addr; - unsigned long *bp = (unsigned long *) buf; - while (len--) - *bp++ = _swapl(*ap); -} - -static inline void io_insw_noswap(unsigned int addr, void *buf, int len) -{ - volatile unsigned short *ap = (volatile unsigned short *) addr; - unsigned short *bp = (unsigned short *) buf; - while (len--) - *bp++ = *ap; -} - -static inline void io_insl_noswap(unsigned int addr, void *buf, int len) -{ - volatile unsigned long *ap = (volatile unsigned long *) addr; - unsigned long *bp = (unsigned long *) buf; - while (len--) - *bp++ = *ap; -} - -/* - * make the short names macros so specific devices - * can override them as required - */ - -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -#define mmiowb() - -#define inb(addr) ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr)) -#define inw(addr) _swapw(readw(addr)) -#define inl(addr) _swapl(readl(addr)) -#define outb(x,addr) ((void)((h8300_buswidth(addr) && \ - ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr))) -#define outw(x,addr) ((void) writew(_swapw(x),addr)) -#define outl(x,addr) ((void) writel(_swapl(x),addr)) - -#define inb_p(addr) inb(addr) -#define inw_p(addr) inw(addr) -#define inl_p(addr) inl(addr) -#define outb_p(x,addr) outb(x,addr) -#define outw_p(x,addr) outw(x,addr) -#define outl_p(x,addr) outl(x,addr) - -#define outsb(a,b,l) io_outsb(a,b,l) -#define outsw(a,b,l) io_outsw(a,b,l) -#define outsl(a,b,l) io_outsl(a,b,l) - -#define insb(a,b,l) io_insb(a,b,l) -#define insw(a,b,l) io_insw(a,b,l) -#define insl(a,b,l) io_insl(a,b,l) - -#define IO_SPACE_LIMIT 0xffffff - - -/* Values for nocacheflag and cmode */ -#define IOMAP_FULL_CACHING 0 -#define IOMAP_NOCACHE_SER 1 -#define IOMAP_NOCACHE_NONSER 2 -#define IOMAP_WRITETHROUGH 3 - -extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); -extern void __iounmap(void *addr, unsigned long size); - -static inline void *ioremap(unsigned long physaddr, unsigned long size) -{ - return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); -} -static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size) -{ - return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); -} -static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size) -{ - return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); -} -static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size) -{ - return __ioremap(physaddr, size, IOMAP_FULL_CACHING); -} - -extern void iounmap(void *addr); - -/* H8/300 internal I/O functions */ -static __inline__ unsigned char ctrl_inb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -static __inline__ unsigned short ctrl_inw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -static __inline__ unsigned long ctrl_inl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -static __inline__ void ctrl_outb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -static __inline__ void ctrl_outw(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -static __inline__ void ctrl_outl(unsigned long b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -static __inline__ void ctrl_bclr(int b, unsigned long addr) -{ - if (__builtin_constant_p(b)) - switch (b) { - case 0: __asm__("bclr #0,@%0"::"r"(addr)); break; - case 1: __asm__("bclr #1,@%0"::"r"(addr)); break; - case 2: __asm__("bclr #2,@%0"::"r"(addr)); break; - case 3: __asm__("bclr #3,@%0"::"r"(addr)); break; - case 4: __asm__("bclr #4,@%0"::"r"(addr)); break; - case 5: __asm__("bclr #5,@%0"::"r"(addr)); break; - case 6: __asm__("bclr #6,@%0"::"r"(addr)); break; - case 7: __asm__("bclr #7,@%0"::"r"(addr)); break; - } - else - __asm__("bclr %w0,@%1"::"r"(b), "r"(addr)); -} - -static __inline__ void ctrl_bset(int b, unsigned long addr) -{ - if (__builtin_constant_p(b)) - switch (b) { - case 0: __asm__("bset #0,@%0"::"r"(addr)); break; - case 1: __asm__("bset #1,@%0"::"r"(addr)); break; - case 2: __asm__("bset #2,@%0"::"r"(addr)); break; - case 3: __asm__("bset #3,@%0"::"r"(addr)); break; - case 4: __asm__("bset #4,@%0"::"r"(addr)); break; - case 5: __asm__("bset #5,@%0"::"r"(addr)); break; - case 6: __asm__("bset #6,@%0"::"r"(addr)); break; - case 7: __asm__("bset #7,@%0"::"r"(addr)); break; - } - else - __asm__("bset %w0,@%1"::"r"(b), "r"(addr)); -} - -/* Pages to physical address... */ -#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) -#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT) - -/* - * Macros used for converting between virtual and physical mappings. - */ -#define phys_to_virt(vaddr) ((void *) (vaddr)) -#define virt_to_phys(vaddr) ((unsigned long) (vaddr)) - -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - -#endif /* __KERNEL__ */ - -#endif /* _H8300_IO_H */ diff --git a/arch/h8300/include/asm/irq.h b/arch/h8300/include/asm/irq.h deleted file mode 100644 index 13d7c601cd0a..000000000000 --- a/arch/h8300/include/asm/irq.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _H8300_IRQ_H_ -#define _H8300_IRQ_H_ - -#include - -#if defined(CONFIG_CPU_H8300H) -#define NR_IRQS 64 -#define EXT_IRQ0 12 -#define EXT_IRQ1 13 -#define EXT_IRQ2 14 -#define EXT_IRQ3 15 -#define EXT_IRQ4 16 -#define EXT_IRQ5 17 -#define EXT_IRQ6 18 -#define EXT_IRQ7 19 -#define EXT_IRQS 5 -#define IER_REGS *(volatile unsigned char *)IER -#endif -#if defined(CONFIG_CPU_H8S) -#define NR_IRQS 128 -#define EXT_IRQ0 16 -#define EXT_IRQ1 17 -#define EXT_IRQ2 18 -#define EXT_IRQ3 19 -#define EXT_IRQ4 20 -#define EXT_IRQ5 21 -#define EXT_IRQ6 22 -#define EXT_IRQ7 23 -#define EXT_IRQ8 24 -#define EXT_IRQ9 25 -#define EXT_IRQ10 26 -#define EXT_IRQ11 27 -#define EXT_IRQ12 28 -#define EXT_IRQ13 29 -#define EXT_IRQ14 30 -#define EXT_IRQ15 31 -#define EXT_IRQS 15 - -#define IER_REGS *(volatile unsigned short *)IER -#endif - -static __inline__ int irq_canonicalize(int irq) -{ - return irq; -} - -typedef void (*h8300_vector)(void); - -#endif /* _H8300_IRQ_H_ */ diff --git a/arch/h8300/include/asm/irq_regs.h b/arch/h8300/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b70270..000000000000 --- a/arch/h8300/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h deleted file mode 100644 index 9617cd57aebd..000000000000 --- a/arch/h8300/include/asm/irqflags.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _H8300_IRQFLAGS_H -#define _H8300_IRQFLAGS_H - -static inline unsigned long arch_local_save_flags(void) -{ - unsigned long flags; - asm volatile ("stc ccr,%w0" : "=r" (flags)); - return flags; -} - -static inline void arch_local_irq_disable(void) -{ - asm volatile ("orc #0x80,ccr" : : : "memory"); -} - -static inline void arch_local_irq_enable(void) -{ - asm volatile ("andc #0x7f,ccr" : : : "memory"); -} - -static inline unsigned long arch_local_irq_save(void) -{ - unsigned long flags = arch_local_save_flags(); - arch_local_irq_disable(); - return flags; -} - -static inline void arch_local_irq_restore(unsigned long flags) -{ - asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory"); -} - -static inline bool arch_irqs_disabled_flags(unsigned long flags) -{ - return (flags & 0x80) == 0x80; -} - -static inline bool arch_irqs_disabled(void) -{ - return arch_irqs_disabled_flags(arch_local_save_flags()); -} - -#endif /* _H8300_IRQFLAGS_H */ diff --git a/arch/h8300/include/asm/kdebug.h b/arch/h8300/include/asm/kdebug.h deleted file mode 100644 index 6ece1b037665..000000000000 --- a/arch/h8300/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/asm/kmap_types.h b/arch/h8300/include/asm/kmap_types.h deleted file mode 100644 index be12a7160116..000000000000 --- a/arch/h8300/include/asm/kmap_types.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_H8300_KMAP_TYPES_H -#define _ASM_H8300_KMAP_TYPES_H - -#include - -#endif diff --git a/arch/h8300/include/asm/local.h b/arch/h8300/include/asm/local.h deleted file mode 100644 index fdd4efe437cd..000000000000 --- a/arch/h8300/include/asm/local.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_LOCAL_H_ -#define _H8300_LOCAL_H_ - -#include - -#endif diff --git a/arch/h8300/include/asm/local64.h b/arch/h8300/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239..000000000000 --- a/arch/h8300/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/asm/mc146818rtc.h b/arch/h8300/include/asm/mc146818rtc.h deleted file mode 100644 index ab9d9646d241..000000000000 --- a/arch/h8300/include/asm/mc146818rtc.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Machine dependent access functions for RTC registers. - */ -#ifndef _H8300_MC146818RTC_H -#define _H8300_MC146818RTC_H - -/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */ - -#endif /* _H8300_MC146818RTC_H */ diff --git a/arch/h8300/include/asm/mmu_context.h b/arch/h8300/include/asm/mmu_context.h deleted file mode 100644 index f44b730da54d..000000000000 --- a/arch/h8300/include/asm/mmu_context.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __H8300_MMU_CONTEXT_H -#define __H8300_MMU_CONTEXT_H - -#include -#include -#include -#include - -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - -static inline int -init_new_context(struct task_struct *tsk, struct mm_struct *mm) -{ - // mm->context = virt_to_phys(mm->pgd); - return(0); -} - -#define destroy_context(mm) do { } while(0) -#define deactivate_mm(tsk,mm) do { } while(0) - -static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) -{ -} - -static inline void activate_mm(struct mm_struct *prev_mm, - struct mm_struct *next_mm) -{ -} - -#endif diff --git a/arch/h8300/include/asm/mutex.h b/arch/h8300/include/asm/mutex.h deleted file mode 100644 index 458c1f7fbc18..000000000000 --- a/arch/h8300/include/asm/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include diff --git a/arch/h8300/include/asm/page.h b/arch/h8300/include/asm/page.h deleted file mode 100644 index 837381a2df46..000000000000 --- a/arch/h8300/include/asm/page.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _H8300_PAGE_H -#define _H8300_PAGE_H - -/* PAGE_SHIFT determines the page size */ - -#define PAGE_SHIFT (12) -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) - -#include - -#ifndef __ASSEMBLY__ - -#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) -#define free_user_page(page, addr) free_page(addr) - -#define clear_page(page) memset((page), 0, PAGE_SIZE) -#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) - -#define clear_user_page(page, vaddr, pg) clear_page(page) -#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) - -#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) -#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE - -/* - * These are used to make use of C type-checking.. - */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pmd[16]; } pmd_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; -typedef struct page *pgtable_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((&x)->pmd[0]) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -extern unsigned long memory_start; -extern unsigned long memory_end; - -#endif /* !__ASSEMBLY__ */ - -#include - -#define PAGE_OFFSET (PAGE_OFFSET_RAW) - -#ifndef __ASSEMBLY__ - -#define __pa(vaddr) virt_to_phys(vaddr) -#define __va(paddr) phys_to_virt((unsigned long)paddr) - -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) - -#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) -#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) -#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) -#define pfn_valid(page) (page < max_mapnr) - -#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) - -#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ - ((void *)(kaddr) < (void *)memory_end)) - -#endif /* __ASSEMBLY__ */ - -#include -#include - -#endif /* _H8300_PAGE_H */ diff --git a/arch/h8300/include/asm/page_offset.h b/arch/h8300/include/asm/page_offset.h deleted file mode 100644 index f8706463008c..000000000000 --- a/arch/h8300/include/asm/page_offset.h +++ /dev/null @@ -1,3 +0,0 @@ - -#define PAGE_OFFSET_RAW 0x00000000 - diff --git a/arch/h8300/include/asm/param.h b/arch/h8300/include/asm/param.h deleted file mode 100644 index c3909e7ff178..000000000000 --- a/arch/h8300/include/asm/param.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _H8300_PARAM_H -#define _H8300_PARAM_H - -#include - -#define HZ CONFIG_HZ -#define USER_HZ HZ -#define CLOCKS_PER_SEC (USER_HZ) -#endif /* _H8300_PARAM_H */ diff --git a/arch/h8300/include/asm/pci.h b/arch/h8300/include/asm/pci.h deleted file mode 100644 index 0b2acaa3dd84..000000000000 --- a/arch/h8300/include/asm/pci.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_H8300_PCI_H -#define _ASM_H8300_PCI_H - -/* - * asm-h8300/pci.h - H8/300 specific PCI declarations. - * - * Yoshinori Sato - */ - -#define pcibios_assign_all_busses() 0 - -static inline void pcibios_penalize_isa_irq(int irq, int active) -{ - /* We don't do dynamic PCI IRQ allocation */ -} - -#define PCI_DMA_BUS_IS_PHYS (1) - -#endif /* _ASM_H8300_PCI_H */ diff --git a/arch/h8300/include/asm/percpu.h b/arch/h8300/include/asm/percpu.h deleted file mode 100644 index 72c03e3666d8..000000000000 --- a/arch/h8300/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARCH_H8300_PERCPU__ -#define __ARCH_H8300_PERCPU__ - -#include - -#endif /* __ARCH_H8300_PERCPU__ */ diff --git a/arch/h8300/include/asm/pgalloc.h b/arch/h8300/include/asm/pgalloc.h deleted file mode 100644 index c2e89a286d23..000000000000 --- a/arch/h8300/include/asm/pgalloc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _H8300_PGALLOC_H -#define _H8300_PGALLOC_H - -#include - -#define check_pgt_cache() do { } while (0) - -#endif /* _H8300_PGALLOC_H */ diff --git a/arch/h8300/include/asm/pgtable.h b/arch/h8300/include/asm/pgtable.h deleted file mode 100644 index 7ca20f894dd7..000000000000 --- a/arch/h8300/include/asm/pgtable.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _H8300_PGTABLE_H -#define _H8300_PGTABLE_H - -#include - -#include -#include -#include -#include - -#define pgd_present(pgd) (1) /* pages are always present on NO_MM */ -#define pgd_none(pgd) (0) -#define pgd_bad(pgd) (0) -#define pgd_clear(pgdp) -#define kern_addr_valid(addr) (1) -#define pmd_offset(a, b) ((void *)0) -#define pmd_none(pmd) (1) -#define pgd_offset_k(adrdress) ((pgd_t *)0) -#define pte_offset_kernel(dir, address) ((pte_t *)0) - -#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */ - -extern void paging_init(void); -#define swapper_pg_dir ((pgd_t *) 0) - -#define __swp_type(x) (0) -#define __swp_offset(x) (0) -#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - -static inline int pte_file(pte_t pte) { return 0; } - -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -#define ZERO_PAGE(vaddr) (virt_to_page(0)) - -/* - * These would be in other places but having them here reduces the diffs. - */ -extern unsigned int kobjsize(const void *objp); -extern int is_in_rom(unsigned long); - -/* - * No page table caches to initialise - */ -#define pgtable_cache_init() do { } while (0) - -/* - * All 32bit addresses are effectively valid for vmalloc... - * Sort of meaningless for non-VM targets. - */ -#define VMALLOC_START 0 -#define VMALLOC_END 0xffffffff - -/* - * All 32bit addresses are effectively valid for vmalloc... - * Sort of meaningless for non-VM targets. - */ -#define VMALLOC_START 0 -#define VMALLOC_END 0xffffffff - -#define arch_enter_lazy_cpu_mode() do {} while (0) - -#include - -#endif /* _H8300_PGTABLE_H */ diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h deleted file mode 100644 index 4b0ca49bb463..000000000000 --- a/arch/h8300/include/asm/processor.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * include/asm-h8300/processor.h - * - * Copyright (C) 2002 Yoshinori Sato - * - * Based on: linux/asm-m68nommu/processor.h - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#ifndef __ASM_H8300_PROCESSOR_H -#define __ASM_H8300_PROCESSOR_H - -/* - * Default implementation of macro that returns current - * instruction pointer ("program counter"). - */ -#define current_text_addr() ({ __label__ _l; _l: &&_l;}) - -#include -#include -#include -#include -#include - -static inline unsigned long rdusp(void) { - extern unsigned int sw_usp; - return(sw_usp); -} - -static inline void wrusp(unsigned long usp) { - extern unsigned int sw_usp; - sw_usp = usp; -} - -/* - * User space process size: 3.75GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. - */ -#define TASK_SIZE (0xFFFFFFFFUL) - -#ifdef __KERNEL__ -#define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP -#endif - -/* - * This decides where the kernel will search for a free chunk of vm - * space during mmap's. We won't be using it - */ -#define TASK_UNMAPPED_BASE 0 - -struct thread_struct { - unsigned long ksp; /* kernel stack pointer */ - unsigned long usp; /* user stack pointer */ - unsigned long ccr; /* saved status register */ - unsigned long esp0; /* points to SR of stack frame */ - struct { - unsigned short *addr; - unsigned short inst; - } breakinfo; -}; - -#define INIT_THREAD { \ - .ksp = sizeof(init_stack) + (unsigned long)init_stack, \ - .usp = 0, \ - .ccr = PS_S, \ - .esp0 = 0, \ - .breakinfo = { \ - .addr = (unsigned short *)-1, \ - .inst = 0 \ - } \ -} - -/* - * Do necessary setup to start up a newly executed thread. - * - * pass the data segment into user programs if it exists, - * it can't hurt anything as far as I can tell - */ -#if defined(__H8300H__) -#define start_thread(_regs, _pc, _usp) \ -do { \ - (_regs)->pc = (_pc); \ - (_regs)->ccr = 0x00; /* clear all flags */ \ - (_regs)->er5 = current->mm->start_data; /* GOT base */ \ - wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3); \ -} while(0) -#endif -#if defined(__H8300S__) -#define start_thread(_regs, _pc, _usp) \ -do { \ - (_regs)->pc = (_pc); \ - (_regs)->ccr = 0x00; /* clear kernel flag */ \ - (_regs)->exr = 0x78; /* enable all interrupts */ \ - (_regs)->er5 = current->mm->start_data; /* GOT base */ \ - /* 14 = space for retaddr(4), vector(4), er0(4) and ext(2) on stack */ \ - wrusp(((unsigned long)(_usp)) - 14); \ -} while(0) -#endif - -/* Forward declaration, a strange C thing */ -struct task_struct; - -/* Free all resources held by a thread. */ -static inline void release_thread(struct task_struct *dead_task) -{ -} - -/* - * Free current thread data structures etc.. - */ -static inline void exit_thread(void) -{ -} - -/* - * Return saved PC of a blocked thread. - */ -unsigned long thread_saved_pc(struct task_struct *tsk); -unsigned long get_wchan(struct task_struct *p); - -#define KSTK_EIP(tsk) \ - ({ \ - unsigned long eip = 0; \ - if ((tsk)->thread.esp0 > PAGE_SIZE && \ - MAP_NR((tsk)->thread.esp0) < max_mapnr) \ - eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \ - eip; }) -#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) - -#define cpu_relax() barrier() - -#define HARD_RESET_NOW() ({ \ - local_irq_disable(); \ - asm("jmp @@0"); \ -}) - -#endif diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h deleted file mode 100644 index c1826b95c5ca..000000000000 --- a/arch/h8300/include/asm/ptrace.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _H8300_PTRACE_H -#define _H8300_PTRACE_H - -#include - -#ifndef __ASSEMBLY__ -#if defined(CONFIG_CPU_H8S) -#endif -#ifndef PS_S -#define PS_S (0x10) -#endif - -#if defined(__H8300H__) -#define H8300_REGS_NO 11 -#endif -#if defined(__H8300S__) -#define H8300_REGS_NO 12 -#endif - -/* Find the stack offset for a register, relative to thread.esp0. */ -#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) - -#define arch_has_single_step() (1) - -#define user_mode(regs) (!((regs)->ccr & PS_S)) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) instruction_pointer(regs) -#define current_pt_regs() ((struct pt_regs *) \ - (THREAD_SIZE + (unsigned long)current_thread_info()) - 1) -#define signal_pt_regs() ((struct pt_regs *)current->thread.esp0) -#define current_user_stack_pointer() rdusp() -#endif /* __ASSEMBLY__ */ -#endif /* _H8300_PTRACE_H */ diff --git a/arch/h8300/include/asm/regs267x.h b/arch/h8300/include/asm/regs267x.h deleted file mode 100644 index 1bff731a9f77..000000000000 --- a/arch/h8300/include/asm/regs267x.h +++ /dev/null @@ -1,336 +0,0 @@ -/* internal Peripherals Register address define */ -/* CPU: H8/306x */ - -#if !defined(__REGS_H8S267x__) -#define __REGS_H8S267x__ - -#if defined(__KERNEL__) - -#define DASTCR 0xFEE01A -#define DADR0 0xFFFFA4 -#define DADR1 0xFFFFA5 -#define DACR01 0xFFFFA6 -#define DADR2 0xFFFFA8 -#define DADR3 0xFFFFA9 -#define DACR23 0xFFFFAA - -#define ADDRA 0xFFFF90 -#define ADDRAH 0xFFFF90 -#define ADDRAL 0xFFFF91 -#define ADDRB 0xFFFF92 -#define ADDRBH 0xFFFF92 -#define ADDRBL 0xFFFF93 -#define ADDRC 0xFFFF94 -#define ADDRCH 0xFFFF94 -#define ADDRCL 0xFFFF95 -#define ADDRD 0xFFFF96 -#define ADDRDH 0xFFFF96 -#define ADDRDL 0xFFFF97 -#define ADDRE 0xFFFF98 -#define ADDREH 0xFFFF98 -#define ADDREL 0xFFFF99 -#define ADDRF 0xFFFF9A -#define ADDRFH 0xFFFF9A -#define ADDRFL 0xFFFF9B -#define ADDRG 0xFFFF9C -#define ADDRGH 0xFFFF9C -#define ADDRGL 0xFFFF9D -#define ADDRH 0xFFFF9E -#define ADDRHH 0xFFFF9E -#define ADDRHL 0xFFFF9F - -#define ADCSR 0xFFFFA0 -#define ADCR 0xFFFFA1 - -#define ABWCR 0xFFFEC0 -#define ASTCR 0xFFFEC1 -#define WTCRAH 0xFFFEC2 -#define WTCRAL 0xFFFEC3 -#define WTCRBH 0xFFFEC4 -#define WTCRBL 0xFFFEC5 -#define RDNCR 0xFFFEC6 -#define CSACRH 0xFFFEC8 -#define CSACRL 0xFFFEC9 -#define BROMCRH 0xFFFECA -#define BROMCRL 0xFFFECB -#define BCR 0xFFFECC -#define DRAMCR 0xFFFED0 -#define DRACCR 0xFFFED2 -#define REFCR 0xFFFED4 -#define RTCNT 0xFFFED6 -#define RTCOR 0xFFFED7 - -#define MAR0AH 0xFFFEE0 -#define MAR0AL 0xFFFEE2 -#define IOAR0A 0xFFFEE4 -#define ETCR0A 0xFFFEE6 -#define MAR0BH 0xFFFEE8 -#define MAR0BL 0xFFFEEA -#define IOAR0B 0xFFFEEC -#define ETCR0B 0xFFFEEE -#define MAR1AH 0xFFFEF0 -#define MAR1AL 0xFFFEF2 -#define IOAR1A 0xFFFEF4 -#define ETCR1A 0xFFFEF6 -#define MAR1BH 0xFFFEF8 -#define MAR1BL 0xFFFEFA -#define IOAR1B 0xFFFEFC -#define ETCR1B 0xFFFEFE -#define DMAWER 0xFFFF20 -#define DMATCR 0xFFFF21 -#define DMACR0A 0xFFFF22 -#define DMACR0B 0xFFFF23 -#define DMACR1A 0xFFFF24 -#define DMACR1B 0xFFFF25 -#define DMABCRH 0xFFFF26 -#define DMABCRL 0xFFFF27 - -#define EDSAR0 0xFFFDC0 -#define EDDAR0 0xFFFDC4 -#define EDTCR0 0xFFFDC8 -#define EDMDR0 0xFFFDCC -#define EDMDR0H 0xFFFDCC -#define EDMDR0L 0xFFFDCD -#define EDACR0 0xFFFDCE -#define EDSAR1 0xFFFDD0 -#define EDDAR1 0xFFFDD4 -#define EDTCR1 0xFFFDD8 -#define EDMDR1 0xFFFDDC -#define EDMDR1H 0xFFFDDC -#define EDMDR1L 0xFFFDDD -#define EDACR1 0xFFFDDE -#define EDSAR2 0xFFFDE0 -#define EDDAR2 0xFFFDE4 -#define EDTCR2 0xFFFDE8 -#define EDMDR2 0xFFFDEC -#define EDMDR2H 0xFFFDEC -#define EDMDR2L 0xFFFDED -#define EDACR2 0xFFFDEE -#define EDSAR3 0xFFFDF0 -#define EDDAR3 0xFFFDF4 -#define EDTCR3 0xFFFDF8 -#define EDMDR3 0xFFFDFC -#define EDMDR3H 0xFFFDFC -#define EDMDR3L 0xFFFDFD -#define EDACR3 0xFFFDFE - -#define IPRA 0xFFFE00 -#define IPRB 0xFFFE02 -#define IPRC 0xFFFE04 -#define IPRD 0xFFFE06 -#define IPRE 0xFFFE08 -#define IPRF 0xFFFE0A -#define IPRG 0xFFFE0C -#define IPRH 0xFFFE0E -#define IPRI 0xFFFE10 -#define IPRJ 0xFFFE12 -#define IPRK 0xFFFE14 -#define ITSR 0xFFFE16 -#define SSIER 0xFFFE18 -#define ISCRH 0xFFFE1A -#define ISCRL 0xFFFE1C - -#define INTCR 0xFFFF31 -#define IER 0xFFFF32 -#define IERH 0xFFFF32 -#define IERL 0xFFFF33 -#define ISR 0xFFFF34 -#define ISRH 0xFFFF34 -#define ISRL 0xFFFF35 - -#define P1DDR 0xFFFE20 -#define P2DDR 0xFFFE21 -#define P3DDR 0xFFFE22 -#define P4DDR 0xFFFE23 -#define P5DDR 0xFFFE24 -#define P6DDR 0xFFFE25 -#define P7DDR 0xFFFE26 -#define P8DDR 0xFFFE27 -#define P9DDR 0xFFFE28 -#define PADDR 0xFFFE29 -#define PBDDR 0xFFFE2A -#define PCDDR 0xFFFE2B -#define PDDDR 0xFFFE2C -#define PEDDR 0xFFFE2D -#define PFDDR 0xFFFE2E -#define PGDDR 0xFFFE2F -#define PHDDR 0xFFFF74 - -#define PFCR0 0xFFFE32 -#define PFCR1 0xFFFE33 -#define PFCR2 0xFFFE34 - -#define PAPCR 0xFFFE36 -#define PBPCR 0xFFFE37 -#define PCPCR 0xFFFE38 -#define PDPCR 0xFFFE39 -#define PEPCR 0xFFFE3A - -#define P3ODR 0xFFFE3C -#define PAODR 0xFFFE3D - -#define P1DR 0xFFFF60 -#define P2DR 0xFFFF61 -#define P3DR 0xFFFF62 -#define P4DR 0xFFFF63 -#define P5DR 0xFFFF64 -#define P6DR 0xFFFF65 -#define P7DR 0xFFFF66 -#define P8DR 0xFFFF67 -#define P9DR 0xFFFF68 -#define PADR 0xFFFF69 -#define PBDR 0xFFFF6A -#define PCDR 0xFFFF6B -#define PDDR 0xFFFF6C -#define PEDR 0xFFFF6D -#define PFDR 0xFFFF6E -#define PGDR 0xFFFF6F -#define PHDR 0xFFFF72 - -#define PORT1 0xFFFF50 -#define PORT2 0xFFFF51 -#define PORT3 0xFFFF52 -#define PORT4 0xFFFF53 -#define PORT5 0xFFFF54 -#define PORT6 0xFFFF55 -#define PORT7 0xFFFF56 -#define PORT8 0xFFFF57 -#define PORT9 0xFFFF58 -#define PORTA 0xFFFF59 -#define PORTB 0xFFFF5A -#define PORTC 0xFFFF5B -#define PORTD 0xFFFF5C -#define PORTE 0xFFFF5D -#define PORTF 0xFFFF5E -#define PORTG 0xFFFF5F -#define PORTH 0xFFFF70 - -#define PCR 0xFFFF46 -#define PMR 0xFFFF47 -#define NDERH 0xFFFF48 -#define NDERL 0xFFFF49 -#define PODRH 0xFFFF4A -#define PODRL 0xFFFF4B -#define NDRH1 0xFFFF4C -#define NDRL1 0xFFFF4D -#define NDRH2 0xFFFF4E -#define NDRL2 0xFFFF4F - -#define SMR0 0xFFFF78 -#define BRR0 0xFFFF79 -#define SCR0 0xFFFF7A -#define TDR0 0xFFFF7B -#define SSR0 0xFFFF7C -#define RDR0 0xFFFF7D -#define SCMR0 0xFFFF7E -#define SMR1 0xFFFF80 -#define BRR1 0xFFFF81 -#define SCR1 0xFFFF82 -#define TDR1 0xFFFF83 -#define SSR1 0xFFFF84 -#define RDR1 0xFFFF85 -#define SCMR1 0xFFFF86 -#define SMR2 0xFFFF88 -#define BRR2 0xFFFF89 -#define SCR2 0xFFFF8A -#define TDR2 0xFFFF8B -#define SSR2 0xFFFF8C -#define RDR2 0xFFFF8D -#define SCMR2 0xFFFF8E - -#define IRCR0 0xFFFE1E -#define SEMR 0xFFFDA8 - -#define MDCR 0xFFFF3E -#define SYSCR 0xFFFF3D -#define MSTPCRH 0xFFFF40 -#define MSTPCRL 0xFFFF41 -#define FLMCR1 0xFFFFC8 -#define FLMCR2 0xFFFFC9 -#define EBR1 0xFFFFCA -#define EBR2 0xFFFFCB -#define CTGARC_RAMCR 0xFFFECE -#define SBYCR 0xFFFF3A -#define SCKCR 0xFFFF3B -#define PLLCR 0xFFFF45 - -#define TSTR 0xFFFFC0 -#define TSNC 0XFFFFC1 - -#define TCR0 0xFFFFD0 -#define TMDR0 0xFFFFD1 -#define TIORH0 0xFFFFD2 -#define TIORL0 0xFFFFD3 -#define TIER0 0xFFFFD4 -#define TSR0 0xFFFFD5 -#define TCNT0 0xFFFFD6 -#define GRA0 0xFFFFD8 -#define GRB0 0xFFFFDA -#define GRC0 0xFFFFDC -#define GRD0 0xFFFFDE -#define TCR1 0xFFFFE0 -#define TMDR1 0xFFFFE1 -#define TIORH1 0xFFFFE2 -#define TIORL1 0xFFFFE3 -#define TIER1 0xFFFFE4 -#define TSR1 0xFFFFE5 -#define TCNT1 0xFFFFE6 -#define GRA1 0xFFFFE8 -#define GRB1 0xFFFFEA -#define TCR2 0xFFFFF0 -#define TMDR2 0xFFFFF1 -#define TIORH2 0xFFFFF2 -#define TIORL2 0xFFFFF3 -#define TIER2 0xFFFFF4 -#define TSR2 0xFFFFF5 -#define TCNT2 0xFFFFF6 -#define GRA2 0xFFFFF8 -#define GRB2 0xFFFFFA -#define TCR3 0xFFFE80 -#define TMDR3 0xFFFE81 -#define TIORH3 0xFFFE82 -#define TIORL3 0xFFFE83 -#define TIER3 0xFFFE84 -#define TSR3 0xFFFE85 -#define TCNT3 0xFFFE86 -#define GRA3 0xFFFE88 -#define GRB3 0xFFFE8A -#define GRC3 0xFFFE8C -#define GRD3 0xFFFE8E -#define TCR4 0xFFFE90 -#define TMDR4 0xFFFE91 -#define TIORH4 0xFFFE92 -#define TIORL4 0xFFFE93 -#define TIER4 0xFFFE94 -#define TSR4 0xFFFE95 -#define TCNT4 0xFFFE96 -#define GRA4 0xFFFE98 -#define GRB4 0xFFFE9A -#define TCR5 0xFFFEA0 -#define TMDR5 0xFFFEA1 -#define TIORH5 0xFFFEA2 -#define TIORL5 0xFFFEA3 -#define TIER5 0xFFFEA4 -#define TSR5 0xFFFEA5 -#define TCNT5 0xFFFEA6 -#define GRA5 0xFFFEA8 -#define GRB5 0xFFFEAA - -#define _8TCR0 0xFFFFB0 -#define _8TCR1 0xFFFFB1 -#define _8TCSR0 0xFFFFB2 -#define _8TCSR1 0xFFFFB3 -#define _8TCORA0 0xFFFFB4 -#define _8TCORA1 0xFFFFB5 -#define _8TCORB0 0xFFFFB6 -#define _8TCORB1 0xFFFFB7 -#define _8TCNT0 0xFFFFB8 -#define _8TCNT1 0xFFFFB9 - -#define TCSR 0xFFFFBC -#define TCNT 0xFFFFBD -#define RSTCSRW 0xFFFFBE -#define RSTCSRR 0xFFFFBF - -#endif /* __KERNEL__ */ -#endif /* __REGS_H8S267x__ */ diff --git a/arch/h8300/include/asm/regs306x.h b/arch/h8300/include/asm/regs306x.h deleted file mode 100644 index 027dd633fa25..000000000000 --- a/arch/h8300/include/asm/regs306x.h +++ /dev/null @@ -1,212 +0,0 @@ -/* internal Peripherals Register address define */ -/* CPU: H8/306x */ - -#if !defined(__REGS_H8306x__) -#define __REGS_H8306x__ - -#if defined(__KERNEL__) - -#define DASTCR 0xFEE01A -#define DADR0 0xFEE09C -#define DADR1 0xFEE09D -#define DACR 0xFEE09E - -#define ADDRAH 0xFFFFE0 -#define ADDRAL 0xFFFFE1 -#define ADDRBH 0xFFFFE2 -#define ADDRBL 0xFFFFE3 -#define ADDRCH 0xFFFFE4 -#define ADDRCL 0xFFFFE5 -#define ADDRDH 0xFFFFE6 -#define ADDRDL 0xFFFFE7 -#define ADCSR 0xFFFFE8 -#define ADCR 0xFFFFE9 - -#define BRCR 0xFEE013 -#define ADRCR 0xFEE01E -#define CSCR 0xFEE01F -#define ABWCR 0xFEE020 -#define ASTCR 0xFEE021 -#define WCRH 0xFEE022 -#define WCRL 0xFEE023 -#define BCR 0xFEE024 -#define DRCRA 0xFEE026 -#define DRCRB 0xFEE027 -#define RTMCSR 0xFEE028 -#define RTCNT 0xFEE029 -#define RTCOR 0xFEE02A - -#define MAR0AR 0xFFFF20 -#define MAR0AE 0xFFFF21 -#define MAR0AH 0xFFFF22 -#define MAR0AL 0xFFFF23 -#define ETCR0AL 0xFFFF24 -#define ETCR0AH 0xFFFF25 -#define IOAR0A 0xFFFF26 -#define DTCR0A 0xFFFF27 -#define MAR0BR 0xFFFF28 -#define MAR0BE 0xFFFF29 -#define MAR0BH 0xFFFF2A -#define MAR0BL 0xFFFF2B -#define ETCR0BL 0xFFFF2C -#define ETCR0BH 0xFFFF2D -#define IOAR0B 0xFFFF2E -#define DTCR0B 0xFFFF2F -#define MAR1AR 0xFFFF30 -#define MAR1AE 0xFFFF31 -#define MAR1AH 0xFFFF32 -#define MAR1AL 0xFFFF33 -#define ETCR1AL 0xFFFF34 -#define ETCR1AH 0xFFFF35 -#define IOAR1A 0xFFFF36 -#define DTCR1A 0xFFFF37 -#define MAR1BR 0xFFFF38 -#define MAR1BE 0xFFFF39 -#define MAR1BH 0xFFFF3A -#define MAR1BL 0xFFFF3B -#define ETCR1BL 0xFFFF3C -#define ETCR1BH 0xFFFF3D -#define IOAR1B 0xFFFF3E -#define DTCR1B 0xFFFF3F - -#define ISCR 0xFEE014 -#define IER 0xFEE015 -#define ISR 0xFEE016 -#define IPRA 0xFEE018 -#define IPRB 0xFEE019 - -#define P1DDR 0xFEE000 -#define P2DDR 0xFEE001 -#define P3DDR 0xFEE002 -#define P4DDR 0xFEE003 -#define P5DDR 0xFEE004 -#define P6DDR 0xFEE005 -/*#define P7DDR 0xFEE006*/ -#define P8DDR 0xFEE007 -#define P9DDR 0xFEE008 -#define PADDR 0xFEE009 -#define PBDDR 0xFEE00A - -#define P1DR 0xFFFFD0 -#define P2DR 0xFFFFD1 -#define P3DR 0xFFFFD2 -#define P4DR 0xFFFFD3 -#define P5DR 0xFFFFD4 -#define P6DR 0xFFFFD5 -/*#define P7DR 0xFFFFD6*/ -#define P8DR 0xFFFFD7 -#define P9DR 0xFFFFD8 -#define PADR 0xFFFFD9 -#define PBDR 0xFFFFDA - -#define P2CR 0xFEE03C -#define P4CR 0xFEE03E -#define P5CR 0xFEE03F - -#define SMR0 0xFFFFB0 -#define BRR0 0xFFFFB1 -#define SCR0 0xFFFFB2 -#define TDR0 0xFFFFB3 -#define SSR0 0xFFFFB4 -#define RDR0 0xFFFFB5 -#define SCMR0 0xFFFFB6 -#define SMR1 0xFFFFB8 -#define BRR1 0xFFFFB9 -#define SCR1 0xFFFFBA -#define TDR1 0xFFFFBB -#define SSR1 0xFFFFBC -#define RDR1 0xFFFFBD -#define SCMR1 0xFFFFBE -#define SMR2 0xFFFFC0 -#define BRR2 0xFFFFC1 -#define SCR2 0xFFFFC2 -#define TDR2 0xFFFFC3 -#define SSR2 0xFFFFC4 -#define RDR2 0xFFFFC5 -#define SCMR2 0xFFFFC6 - -#define MDCR 0xFEE011 -#define SYSCR 0xFEE012 -#define DIVCR 0xFEE01B -#define MSTCRH 0xFEE01C -#define MSTCRL 0xFEE01D -#define FLMCR1 0xFEE030 -#define FLMCR2 0xFEE031 -#define EBR1 0xFEE032 -#define EBR2 0xFEE033 -#define RAMCR 0xFEE077 - -#define TSTR 0xFFFF60 -#define TSNC 0XFFFF61 -#define TMDR 0xFFFF62 -#define TOLR 0xFFFF63 -#define TISRA 0xFFFF64 -#define TISRB 0xFFFF65 -#define TISRC 0xFFFF66 -#define TCR0 0xFFFF68 -#define TIOR0 0xFFFF69 -#define TCNT0H 0xFFFF6A -#define TCNT0L 0xFFFF6B -#define GRA0H 0xFFFF6C -#define GRA0L 0xFFFF6D -#define GRB0H 0xFFFF6E -#define GRB0L 0xFFFF6F -#define TCR1 0xFFFF70 -#define TIOR1 0xFFFF71 -#define TCNT1H 0xFFFF72 -#define TCNT1L 0xFFFF73 -#define GRA1H 0xFFFF74 -#define GRA1L 0xFFFF75 -#define GRB1H 0xFFFF76 -#define GRB1L 0xFFFF77 -#define TCR3 0xFFFF78 -#define TIOR3 0xFFFF79 -#define TCNT3H 0xFFFF7A -#define TCNT3L 0xFFFF7B -#define GRA3H 0xFFFF7C -#define GRA3L 0xFFFF7D -#define GRB3H 0xFFFF7E -#define GRB3L 0xFFFF7F - -#define _8TCR0 0xFFFF80 -#define _8TCR1 0xFFFF81 -#define _8TCSR0 0xFFFF82 -#define _8TCSR1 0xFFFF83 -#define TCORA0 0xFFFF84 -#define TCORA1 0xFFFF85 -#define TCORB0 0xFFFF86 -#define TCORB1 0xFFFF87 -#define _8TCNT0 0xFFFF88 -#define _8TCNT1 0xFFFF89 - -#define _8TCR2 0xFFFF90 -#define _8TCR3 0xFFFF91 -#define _8TCSR2 0xFFFF92 -#define _8TCSR3 0xFFFF93 -#define TCORA2 0xFFFF94 -#define TCORA3 0xFFFF95 -#define TCORB2 0xFFFF96 -#define TCORB3 0xFFFF97 -#define _8TCNT2 0xFFFF98 -#define _8TCNT3 0xFFFF99 - -#define TCSR 0xFFFF8C -#define TCNT 0xFFFF8D -#define RSTCSR 0xFFFF8F - -#define TPMR 0xFFFFA0 -#define TPCR 0xFFFFA1 -#define NDERB 0xFFFFA2 -#define NDERA 0xFFFFA3 -#define NDRB1 0xFFFFA4 -#define NDRA1 0xFFFFA5 -#define NDRB2 0xFFFFA6 -#define NDRA2 0xFFFFA7 - -#define TCSR 0xFFFF8C -#define TCNT 0xFFFF8D -#define RSTCSRW 0xFFFF8E -#define RSTCSRR 0xFFFF8F - -#endif /* __KERNEL__ */ -#endif /* __REGS_H8306x__ */ diff --git a/arch/h8300/include/asm/scatterlist.h b/arch/h8300/include/asm/scatterlist.h deleted file mode 100644 index 82130eda0e5f..000000000000 --- a/arch/h8300/include/asm/scatterlist.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_SCATTERLIST_H -#define _H8300_SCATTERLIST_H - -#include - -#endif /* !(_H8300_SCATTERLIST_H) */ diff --git a/arch/h8300/include/asm/sections.h b/arch/h8300/include/asm/sections.h deleted file mode 100644 index a81743e8b743..000000000000 --- a/arch/h8300/include/asm/sections.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_SECTIONS_H_ -#define _H8300_SECTIONS_H_ - -#include - -#endif diff --git a/arch/h8300/include/asm/segment.h b/arch/h8300/include/asm/segment.h deleted file mode 100644 index b79a82d0f99d..000000000000 --- a/arch/h8300/include/asm/segment.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _H8300_SEGMENT_H -#define _H8300_SEGMENT_H - -/* define constants */ -#define USER_DATA (1) -#ifndef __USER_DS -#define __USER_DS (USER_DATA) -#endif -#define USER_PROGRAM (2) -#define SUPER_DATA (3) -#ifndef __KERNEL_DS -#define __KERNEL_DS (SUPER_DATA) -#endif -#define SUPER_PROGRAM (4) - -#ifndef __ASSEMBLY__ - -typedef struct { - unsigned long seg; -} mm_segment_t; - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -#define USER_DS MAKE_MM_SEG(__USER_DS) -#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS) - -/* - * Get/set the SFC/DFC registers for MOVES instructions - */ - -static inline mm_segment_t get_fs(void) -{ - return USER_DS; -} - -static inline mm_segment_t get_ds(void) -{ - /* return the supervisor data space code */ - return KERNEL_DS; -} - -static inline void set_fs(mm_segment_t val) -{ -} - -#define segment_eq(a,b) ((a).seg == (b).seg) - -#endif /* __ASSEMBLY__ */ - -#endif /* _H8300_SEGMENT_H */ diff --git a/arch/h8300/include/asm/sh_bios.h b/arch/h8300/include/asm/sh_bios.h deleted file mode 100644 index b6bb6e58295c..000000000000 --- a/arch/h8300/include/asm/sh_bios.h +++ /dev/null @@ -1,29 +0,0 @@ -/* eCos HAL interface header */ - -#ifndef SH_BIOS_H -#define SH_BIOS_H - -#define HAL_IF_VECTOR_TABLE 0xfffe20 -#define CALL_IF_SET_CONSOLE_COMM 13 -#define QUERY_CURRENT -1 -#define MANGLER -3 - -/* Checking for GDB stub active */ -/* suggestion Jonathan Larmour */ -static int sh_bios_in_gdb_mode(void) -{ - static int gdb_active = -1; - if (gdb_active == -1) { - int (*set_console_comm)(int); - set_console_comm = ((void **)HAL_IF_VECTOR_TABLE)[CALL_IF_SET_CONSOLE_COMM]; - gdb_active = (set_console_comm(QUERY_CURRENT) == MANGLER); - } - return gdb_active; -} - -static void sh_bios_gdb_detach(void) -{ - -} - -#endif diff --git a/arch/h8300/include/asm/shm.h b/arch/h8300/include/asm/shm.h deleted file mode 100644 index ed6623c0545d..000000000000 --- a/arch/h8300/include/asm/shm.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _H8300_SHM_H -#define _H8300_SHM_H - - -/* format of page table entries that correspond to shared memory pages - currently out in swap space (see also mm/swap.c): - bits 0-1 (PAGE_PRESENT) is = 0 - bits 8..2 (SWP_TYPE) are = SHM_SWP_TYPE - bits 31..9 are used like this: - bits 15..9 (SHM_ID) the id of the shared memory segment - bits 30..16 (SHM_IDX) the index of the page within the shared memory segment - (actually only bits 25..16 get used since SHMMAX is so low) - bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach -*/ -/* on the m68k both bits 0 and 1 must be zero */ -/* format on the sun3 is similar, but bits 30, 31 are set to zero and all - others are reduced by 2. --m */ - -#ifndef CONFIG_SUN3 -#define SHM_ID_SHIFT 9 -#else -#define SHM_ID_SHIFT 7 -#endif -#define _SHM_ID_BITS 7 -#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1) - -#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS) -#define _SHM_IDX_BITS 15 -#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1) - -#endif /* _H8300_SHM_H */ diff --git a/arch/h8300/include/asm/shmparam.h b/arch/h8300/include/asm/shmparam.h deleted file mode 100644 index d1863953ec64..000000000000 --- a/arch/h8300/include/asm/shmparam.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_SHMPARAM_H -#define _H8300_SHMPARAM_H - -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ - -#endif /* _H8300_SHMPARAM_H */ diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h deleted file mode 100644 index 6341e36386f8..000000000000 --- a/arch/h8300/include/asm/signal.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _H8300_SIGNAL_H -#define _H8300_SIGNAL_H - -#include - -/* Most things should be clean enough to redefine this at will, if care - is taken to make libc match. */ - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#define __ARCH_HAS_SA_RESTORER - -#include -#undef __HAVE_ARCH_SIG_BITOPS - -#endif /* _H8300_SIGNAL_H */ diff --git a/arch/h8300/include/asm/smp.h b/arch/h8300/include/asm/smp.h deleted file mode 100644 index 9e9bd7e58922..000000000000 --- a/arch/h8300/include/asm/smp.h +++ /dev/null @@ -1 +0,0 @@ -/* nothing required here yet */ diff --git a/arch/h8300/include/asm/spinlock.h b/arch/h8300/include/asm/spinlock.h deleted file mode 100644 index d5407fa173e4..000000000000 --- a/arch/h8300/include/asm/spinlock.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __H8300_SPINLOCK_H -#define __H8300_SPINLOCK_H - -#error "H8/300 doesn't do SMP yet" - -#endif diff --git a/arch/h8300/include/asm/string.h b/arch/h8300/include/asm/string.h deleted file mode 100644 index ca5034897d87..000000000000 --- a/arch/h8300/include/asm/string.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _H8300_STRING_H_ -#define _H8300_STRING_H_ - -#ifdef __KERNEL__ /* only set these up for kernel code */ - -#include -#include - -#define __HAVE_ARCH_MEMSET -extern void * memset(void * s, int c, size_t count); - -#define __HAVE_ARCH_MEMCPY -extern void * memcpy(void *d, const void *s, size_t count); - -#else /* KERNEL */ - -/* - * let user libraries deal with these, - * IMHO the kernel has no place defining these functions for user apps - */ - -#define __HAVE_ARCH_STRCPY 1 -#define __HAVE_ARCH_STRNCPY 1 -#define __HAVE_ARCH_STRCAT 1 -#define __HAVE_ARCH_STRNCAT 1 -#define __HAVE_ARCH_STRCMP 1 -#define __HAVE_ARCH_STRNCMP 1 -#define __HAVE_ARCH_STRNICMP 1 -#define __HAVE_ARCH_STRCHR 1 -#define __HAVE_ARCH_STRRCHR 1 -#define __HAVE_ARCH_STRSTR 1 -#define __HAVE_ARCH_STRLEN 1 -#define __HAVE_ARCH_STRNLEN 1 -#define __HAVE_ARCH_MEMSET 1 -#define __HAVE_ARCH_MEMCPY 1 -#define __HAVE_ARCH_MEMMOVE 1 -#define __HAVE_ARCH_MEMSCAN 1 -#define __HAVE_ARCH_MEMCMP 1 -#define __HAVE_ARCH_MEMCHR 1 -#define __HAVE_ARCH_STRTOK 1 - -#endif /* KERNEL */ - -#endif /* _M68K_STRING_H_ */ diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h deleted file mode 100644 index cdd8731ce487..000000000000 --- a/arch/h8300/include/asm/switch_to.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _H8300_SWITCH_TO_H -#define _H8300_SWITCH_TO_H - -/* - * switch_to(n) should switch tasks to task ptr, first checking that - * ptr isn't the current task, in which case it does nothing. This - * also clears the TS-flag if the task we switched to has used the - * math co-processor latest. - */ -/* - * switch_to() saves the extra registers, that are not saved - * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and - * a0-a1. Some of these are used by schedule() and its predecessors - * and so we might get see unexpected behaviors when a task returns - * with unexpected register values. - * - * syscall stores these registers itself and none of them are used - * by syscall after the function in the syscall has been called. - * - * Beware that resume now expects *next to be in d1 and the offset of - * tss to be in a1. This saves a few instructions as we no longer have - * to push them onto the stack and read them back right after. - * - * 02/17/96 - Jes Sorensen (jds@kom.auc.dk) - * - * Changed 96/09/19 by Andreas Schwab - * pass prev in a0, next in a1, offset of tss in d1, and whether - * the mm structures are shared in d2 (to avoid atc flushing). - * - * H8/300 Porting 2002/09/04 Yoshinori Sato - */ - -asmlinkage void resume(void); -#define switch_to(prev,next,last) { \ - void *_last; \ - __asm__ __volatile__( \ - "mov.l %1, er0\n\t" \ - "mov.l %2, er1\n\t" \ - "mov.l %3, er2\n\t" \ - "jsr @_resume\n\t" \ - "mov.l er2,%0\n\t" \ - : "=r" (_last) \ - : "r" (&(prev->thread)), \ - "r" (&(next->thread)), \ - "g" (prev) \ - : "cc", "er0", "er1", "er2", "er3"); \ - (last) = _last; \ -} - -#endif /* _H8300_SWITCH_TO_H */ diff --git a/arch/h8300/include/asm/target_time.h b/arch/h8300/include/asm/target_time.h deleted file mode 100644 index 9f2a9aa1fe6f..000000000000 --- a/arch/h8300/include/asm/target_time.h +++ /dev/null @@ -1,4 +0,0 @@ -extern int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)); -extern void platform_timer_eoi(void); -extern void platform_gettod(unsigned int *year, unsigned int *mon, unsigned int *day, - unsigned int *hour, unsigned int *min, unsigned int *sec); diff --git a/arch/h8300/include/asm/termios.h b/arch/h8300/include/asm/termios.h deleted file mode 100644 index 93a63df56247..000000000000 --- a/arch/h8300/include/asm/termios.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _H8300_TERMIOS_H -#define _H8300_TERMIOS_H - -#include - -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - unsigned short tmp; \ - get_user(tmp, &(termio)->c_iflag); \ - (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \ - get_user(tmp, &(termio)->c_oflag); \ - (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \ - get_user(tmp, &(termio)->c_cflag); \ - (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \ - get_user(tmp, &(termio)->c_lflag); \ - (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \ - get_user((termios)->c_line, &(termio)->c_line); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) -#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) - -#endif /* _H8300_TERMIOS_H */ diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h deleted file mode 100644 index ec2f7777c65a..000000000000 --- a/arch/h8300/include/asm/thread_info.h +++ /dev/null @@ -1,103 +0,0 @@ -/* thread_info.h: h8300 low-level thread information - * adapted from the i386 and PPC versions by Yoshinori Sato - * - * Copyright (C) 2002 David Howells (dhowells@redhat.com) - * - Incorporating suggestions made by Linus Torvalds and Dave Miller - */ - -#ifndef _ASM_THREAD_INFO_H -#define _ASM_THREAD_INFO_H - -#include - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -/* - * low level task data. - * If you change this, change the TI_* offsets below to match. - */ -struct thread_info { - struct task_struct *task; /* main task structure */ - struct exec_domain *exec_domain; /* execution domain */ - unsigned long flags; /* low level flags */ - int cpu; /* cpu we're on */ - int preempt_count; /* 0 => preemptable, <0 => BUG */ - struct restart_block restart_block; -}; - -/* - * macros/functions for gaining access to the thread information structure - */ -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .exec_domain = &default_exec_domain, \ - .flags = 0, \ - .cpu = 0, \ - .preempt_count = INIT_PREEMPT_COUNT, \ - .restart_block = { \ - .fn = do_no_restart_syscall, \ - }, \ -} - -#define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) - - -/* - * Size of kernel stack for each process. This must be a power of 2... - */ -#define THREAD_SIZE_ORDER 1 -#define THREAD_SIZE 8192 /* 2 pages */ - - -/* how to get the thread information struct from C */ -static inline struct thread_info *current_thread_info(void) -{ - struct thread_info *ti; - __asm__( - "mov.l sp, %0 \n\t" - "and.l %1, %0" - : "=&r"(ti) - : "i" (~(THREAD_SIZE-1)) - ); - return ti; -} - -#endif /* __ASSEMBLY__ */ - -/* - * Offsets in thread_info structure, used in assembly code - */ -#define TI_TASK 0 -#define TI_EXECDOMAIN 4 -#define TI_FLAGS 8 -#define TI_CPU 12 -#define TI_PRE_COUNT 16 - -#define PREEMPT_ACTIVE 0x4000000 - -/* - * thread information flag bit numbers - */ -#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_SIGPENDING 1 /* signal pending */ -#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ -#define TIF_MEMDIE 4 /* is terminating due to OOM killer */ -#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ -#define TIF_NOTIFY_RESUME 6 /* callback before returning to user */ - -/* as above, but as bit values */ -#define _TIF_SYSCALL_TRACE (1< limit) \ - break; \ - } \ - if (div == ARRAY_SIZE(divide_rate)) \ - panic("Timer counter overflow"); \ - cnt /= divide_rate[div]; \ -} while(0) - -#endif diff --git a/arch/h8300/include/asm/timex.h b/arch/h8300/include/asm/timex.h deleted file mode 100644 index 23e67013439f..000000000000 --- a/arch/h8300/include/asm/timex.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-h8300/timex.h - * - * H8/300 architecture timex specifications - */ -#ifndef _ASM_H8300_TIMEX_H -#define _ASM_H8300_TIMEX_H - -#define CLOCK_TICK_RATE (CONFIG_CPU_CLOCK*1000/8192) /* Timer input freq. */ - -typedef unsigned long cycles_t; -extern short h8300_timer_count; - -static inline cycles_t get_cycles(void) -{ - return 0; -} - -#endif diff --git a/arch/h8300/include/asm/tlb.h b/arch/h8300/include/asm/tlb.h deleted file mode 100644 index 7f0743051ad5..000000000000 --- a/arch/h8300/include/asm/tlb.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __H8300_TLB_H__ -#define __H8300_TLB_H__ - -#define tlb_flush(tlb) do { } while(0) - -#include - -#endif diff --git a/arch/h8300/include/asm/tlbflush.h b/arch/h8300/include/asm/tlbflush.h deleted file mode 100644 index 41c148a9208e..000000000000 --- a/arch/h8300/include/asm/tlbflush.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _H8300_TLBFLUSH_H -#define _H8300_TLBFLUSH_H - -/* - * Copyright (C) 2000 Lineo, David McCullough - * Copyright (C) 2000-2002, Greg Ungerer - */ - -#include - -/* - * flush all user-space atc entries. - */ -static inline void __flush_tlb(void) -{ - BUG(); -} - -static inline void __flush_tlb_one(unsigned long addr) -{ - BUG(); -} - -#define flush_tlb() __flush_tlb() - -/* - * flush all atc entries (both kernel and user-space entries). - */ -static inline void flush_tlb_all(void) -{ - BUG(); -} - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ - BUG(); -} - -static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) -{ - BUG(); -} - -static inline void flush_tlb_range(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - BUG(); -} - -static inline void flush_tlb_kernel_page(unsigned long addr) -{ - BUG(); -} - -#endif /* _H8300_TLBFLUSH_H */ diff --git a/arch/h8300/include/asm/topology.h b/arch/h8300/include/asm/topology.h deleted file mode 100644 index fdc121924d4c..000000000000 --- a/arch/h8300/include/asm/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_H8300_TOPOLOGY_H -#define _ASM_H8300_TOPOLOGY_H - -#include - -#endif /* _ASM_H8300_TOPOLOGY_H */ diff --git a/arch/h8300/include/asm/traps.h b/arch/h8300/include/asm/traps.h deleted file mode 100644 index 41cf6be02f68..000000000000 --- a/arch/h8300/include/asm/traps.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/include/asm-h8300/traps.h - * - * Copyright (C) 2003 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef _H8300_TRAPS_H -#define _H8300_TRAPS_H - -extern void system_call(void); -extern void interrupt_entry(void); -extern void trace_break(void); - -#define JMP_OP 0x5a000000 -#define JSR_OP 0x5e000000 -#define VECTOR(address) ((JMP_OP)|((unsigned long)address)) -#define REDIRECT(address) ((JSR_OP)|((unsigned long)address)) - -#define TRACE_VEC 5 - -#define TRAP0_VEC 8 -#define TRAP1_VEC 9 -#define TRAP2_VEC 10 -#define TRAP3_VEC 11 - -#if defined(__H8300H__) -#define NR_TRAPS 12 -#endif -#if defined(__H8300S__) -#define NR_TRAPS 16 -#endif - -#endif /* _H8300_TRAPS_H */ diff --git a/arch/h8300/include/asm/types.h b/arch/h8300/include/asm/types.h deleted file mode 100644 index c012707f6037..000000000000 --- a/arch/h8300/include/asm/types.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _H8300_TYPES_H -#define _H8300_TYPES_H - -#include - - -#define BITS_PER_LONG 32 - -#endif /* _H8300_TYPES_H */ diff --git a/arch/h8300/include/asm/uaccess.h b/arch/h8300/include/asm/uaccess.h deleted file mode 100644 index 8725d1ad4272..000000000000 --- a/arch/h8300/include/asm/uaccess.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef __H8300_UACCESS_H -#define __H8300_UACCESS_H - -/* - * User space memory access functions - */ -#include -#include -#include - -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* We let the MMU do all checking */ -#define access_ok(type, addr, size) __access_ok((unsigned long)addr,size) -static inline int __access_ok(unsigned long addr, unsigned long size) -{ -#define RANGE_CHECK_OK(addr, size, lower, upper) \ - (((addr) >= (lower)) && (((addr) + (size)) < (upper))) - - extern unsigned long _ramend; - return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend)); -} - -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -/* Returns 0 if exception not found and fixup otherwise. */ -extern unsigned long search_exception_table(unsigned long); - - -/* - * These are the main single-value transfer routines. They automatically - * use the right size if we just have the right pointer type. - */ - -#define put_user(x, ptr) \ -({ \ - int __pu_err = 0; \ - typeof(*(ptr)) __pu_val = (x); \ - switch (sizeof (*(ptr))) { \ - case 1: \ - case 2: \ - case 4: \ - *(ptr) = (__pu_val); \ - break; \ - case 8: \ - memcpy(ptr, &__pu_val, sizeof (*(ptr))); \ - break; \ - default: \ - __pu_err = __put_user_bad(); \ - break; \ - } \ - __pu_err; \ -}) -#define __put_user(x, ptr) put_user(x, ptr) - -extern int __put_user_bad(void); - -/* - * Tell gcc we read from memory instead of writing: this is because - * we do not write to any memory gcc knows about, so there are no - * aliasing issues. - */ - -#define __ptr(x) ((unsigned long *)(x)) - -/* - * Tell gcc we read from memory instead of writing: this is because - * we do not write to any memory gcc knows about, so there are no - * aliasing issues. - */ - -#define get_user(x, ptr) \ -({ \ - int __gu_err = 0; \ - typeof(*(ptr)) __gu_val = *ptr; \ - switch (sizeof(*(ptr))) { \ - case 1: \ - case 2: \ - case 4: \ - case 8: \ - break; \ - default: \ - __gu_err = __get_user_bad(); \ - break; \ - } \ - (x) = __gu_val; \ - __gu_err; \ -}) -#define __get_user(x, ptr) get_user(x, ptr) - -extern int __get_user_bad(void); - -#define copy_from_user(to, from, n) (memcpy(to, from, n), 0) -#define copy_to_user(to, from, n) (memcpy(to, from, n), 0) - -#define __copy_from_user(to, from, n) copy_from_user(to, from, n) -#define __copy_to_user(to, from, n) copy_to_user(to, from, n) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) - -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) - -/* - * Copy a null terminated string from userspace. - */ - -static inline long -strncpy_from_user(char *dst, const char *src, long count) -{ - char *tmp; - strncpy(dst, src, count); - for (tmp = dst; *tmp && count > 0; tmp++, count--) - ; - return(tmp - dst); /* DAVIDM should we count a NUL ? check getname */ -} - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 on exception, a value greater than N if too long - */ -static inline long strnlen_user(const char *src, long n) -{ - return(strlen(src) + 1); /* DAVIDM make safer */ -} - -#define strlen_user(str) strnlen_user(str, 32767) - -/* - * Zero Userspace - */ - -static inline unsigned long -clear_user(void *to, unsigned long n) -{ - memset(to, 0, n); - return 0; -} - -#define __clear_user clear_user - -#endif /* _H8300_UACCESS_H */ diff --git a/arch/h8300/include/asm/ucontext.h b/arch/h8300/include/asm/ucontext.h deleted file mode 100644 index 0bcf8f85fab9..000000000000 --- a/arch/h8300/include/asm/ucontext.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _H8300_UCONTEXT_H -#define _H8300_UCONTEXT_H - -struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ -}; - -#endif diff --git a/arch/h8300/include/asm/unaligned.h b/arch/h8300/include/asm/unaligned.h deleted file mode 100644 index b8d06c70c2da..000000000000 --- a/arch/h8300/include/asm/unaligned.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _ASM_H8300_UNALIGNED_H -#define _ASM_H8300_UNALIGNED_H - -#include -#include -#include - -#define get_unaligned __get_unaligned_be -#define put_unaligned __put_unaligned_be - -#endif /* _ASM_H8300_UNALIGNED_H */ diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h deleted file mode 100644 index ab671ecf5196..000000000000 --- a/arch/h8300/include/asm/unistd.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _ASM_H8300_UNISTD_H_ -#define _ASM_H8300_UNISTD_H_ - -#include - - -#define NR_syscalls 321 - -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_IPC -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLD_MMAP -#define __ARCH_WANT_SYS_OLD_SELECT -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_FORK -#define __ARCH_WANT_SYS_VFORK -#define __ARCH_WANT_SYS_CLONE - -#endif /* _ASM_H8300_UNISTD_H_ */ diff --git a/arch/h8300/include/asm/user.h b/arch/h8300/include/asm/user.h deleted file mode 100644 index 14a9e18950f1..000000000000 --- a/arch/h8300/include/asm/user.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _H8300_USER_H -#define _H8300_USER_H - -#include - -/* Core file format: The core file is written in such a way that gdb - can understand it and provide useful information to the user (under - linux we use the 'trad-core' bfd). There are quite a number of - obstacles to being able to view the contents of the floating point - registers, and until these are solved you will not be able to view the - contents of them. Actually, you can read in the core file and look at - the contents of the user struct to find out what the floating point - registers contain. - The actual file contents are as follows: - UPAGE: 1 page consisting of a user struct that tells gdb what is present - in the file. Directly after this is a copy of the task_struct, which - is currently not used by gdb, but it may come in useful at some point. - All of the registers are stored as part of the upage. The upage should - always be only one page. - DATA: The data area is stored. We use current->end_text to - current->brk to pick up all of the user variables, plus any memory - that may have been malloced. No attempt is made to determine if a page - is demand-zero or if a page is totally unused, we just cover the entire - range. All of the addresses are rounded in such a way that an integral - number of pages is written. - STACK: We need the stack information in order to get a meaningful - backtrace. We need to write the data from (esp) to - current->start_stack, so we round each of these off in order to be able - to write an integer number of pages. - The minimum core file size is 3 pages, or 12288 bytes. -*/ - -/* This is the old layout of "struct pt_regs" as of Linux 1.x, and - is still the layout used by user (the new pt_regs doesn't have - all registers). */ -struct user_regs_struct { - long er1,er2,er3,er4,er5,er6; - long er0; - long usp; - long orig_er0; - short ccr; - long pc; -}; - - -/* When the kernel dumps core, it starts by dumping the user struct - - this will be used by gdb to figure out where the data and stack segments - are within the file, and what virtual addresses to use. */ -struct user{ -/* We start with the registers, to mimic the way that "memory" is returned - from the ptrace(3,...) function. */ - struct user_regs_struct regs; /* Where the registers are actually stored */ -/* ptrace does not yet supply these. Someday.... */ -/* The rest of this junk is to help gdb figure out what goes where */ - unsigned long int u_tsize; /* Text segment size (pages). */ - unsigned long int u_dsize; /* Data segment size (pages). */ - unsigned long int u_ssize; /* Stack segment size (pages). */ - unsigned long start_code; /* Starting virtual address of text. */ - unsigned long start_stack; /* Starting virtual address of stack area. - This is actually the bottom of the stack, - the top of the stack is always found in the - esp register. */ - long int signal; /* Signal that caused the core dump. */ - int reserved; /* No longer used */ - unsigned long u_ar0; /* Used by gdb to help find the values for */ - /* the registers. */ - unsigned long magic; /* To uniquely identify a core file */ - char u_comm[32]; /* User command that was responsible */ -}; -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif diff --git a/arch/h8300/include/asm/virtconvert.h b/arch/h8300/include/asm/virtconvert.h deleted file mode 100644 index 19cfd62b11c3..000000000000 --- a/arch/h8300/include/asm/virtconvert.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __H8300_VIRT_CONVERT__ -#define __H8300_VIRT_CONVERT__ - -/* - * Macros used for converting between virtual and physical mappings. - */ - -#ifdef __KERNEL__ - -#include -#include - -#define phys_to_virt(vaddr) ((void *) (vaddr)) -#define virt_to_phys(vaddr) ((unsigned long) (vaddr)) - -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - -#endif -#endif diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild deleted file mode 100644 index 040178cdb3eb..000000000000 --- a/arch/h8300/include/uapi/asm/Kbuild +++ /dev/null @@ -1,34 +0,0 @@ -# UAPI Header export list -include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/h8300/include/uapi/asm/auxvec.h b/arch/h8300/include/uapi/asm/auxvec.h deleted file mode 100644 index 1d36fe38b088..000000000000 --- a/arch/h8300/include/uapi/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ASMH8300_AUXVEC_H -#define __ASMH8300_AUXVEC_H - -#endif diff --git a/arch/h8300/include/uapi/asm/bitsperlong.h b/arch/h8300/include/uapi/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b2..000000000000 --- a/arch/h8300/include/uapi/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/byteorder.h b/arch/h8300/include/uapi/asm/byteorder.h deleted file mode 100644 index 13539da99efd..000000000000 --- a/arch/h8300/include/uapi/asm/byteorder.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_BYTEORDER_H -#define _H8300_BYTEORDER_H - -#include - -#endif /* _H8300_BYTEORDER_H */ diff --git a/arch/h8300/include/uapi/asm/errno.h b/arch/h8300/include/uapi/asm/errno.h deleted file mode 100644 index 0c2f5641fdcc..000000000000 --- a/arch/h8300/include/uapi/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_ERRNO_H -#define _H8300_ERRNO_H - -#include - -#endif /* _H8300_ERRNO_H */ diff --git a/arch/h8300/include/uapi/asm/fcntl.h b/arch/h8300/include/uapi/asm/fcntl.h deleted file mode 100644 index 1952cb2e3b06..000000000000 --- a/arch/h8300/include/uapi/asm/fcntl.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _H8300_FCNTL_H -#define _H8300_FCNTL_H - -#define O_DIRECTORY 040000 /* must be a directory */ -#define O_NOFOLLOW 0100000 /* don't follow links */ -#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ -#define O_LARGEFILE 0400000 - -#include - -#endif /* _H8300_FCNTL_H */ diff --git a/arch/h8300/include/uapi/asm/ioctl.h b/arch/h8300/include/uapi/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5..000000000000 --- a/arch/h8300/include/uapi/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/ioctls.h b/arch/h8300/include/uapi/asm/ioctls.h deleted file mode 100644 index 30eaed2facdb..000000000000 --- a/arch/h8300/include/uapi/asm/ioctls.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ARCH_H8300_IOCTLS_H__ -#define __ARCH_H8300_IOCTLS_H__ - -#define FIOQSIZE 0x545E - -#include - -#endif /* __ARCH_H8300_IOCTLS_H__ */ diff --git a/arch/h8300/include/uapi/asm/ipcbuf.h b/arch/h8300/include/uapi/asm/ipcbuf.h deleted file mode 100644 index 84c7e51cb6d0..000000000000 --- a/arch/h8300/include/uapi/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/kvm_para.h b/arch/h8300/include/uapi/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b957..000000000000 --- a/arch/h8300/include/uapi/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/mman.h b/arch/h8300/include/uapi/asm/mman.h deleted file mode 100644 index 8eebf89f5ab1..000000000000 --- a/arch/h8300/include/uapi/asm/mman.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/msgbuf.h b/arch/h8300/include/uapi/asm/msgbuf.h deleted file mode 100644 index 6b148cd09aa5..000000000000 --- a/arch/h8300/include/uapi/asm/msgbuf.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _H8300_MSGBUF_H -#define _H8300_MSGBUF_H - -/* - * The msqid64_ds structure for H8/300 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - unsigned long __unused1; - __kernel_time_t msg_rtime; /* last msgrcv time */ - unsigned long __unused2; - __kernel_time_t msg_ctime; /* last change time */ - unsigned long __unused3; - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif /* _H8300_MSGBUF_H */ diff --git a/arch/h8300/include/uapi/asm/param.h b/arch/h8300/include/uapi/asm/param.h deleted file mode 100644 index 3dd18ae15f03..000000000000 --- a/arch/h8300/include/uapi/asm/param.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _UAPI_H8300_PARAM_H -#define _UAPI_H8300_PARAM_H - -#ifndef __KERNEL__ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _UAPI_H8300_PARAM_H */ diff --git a/arch/h8300/include/uapi/asm/poll.h b/arch/h8300/include/uapi/asm/poll.h deleted file mode 100644 index f61540c22d94..000000000000 --- a/arch/h8300/include/uapi/asm/poll.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __H8300_POLL_H -#define __H8300_POLL_H - -#define POLLWRNORM POLLOUT -#define POLLWRBAND 256 - -#include - -#undef POLLREMOVE - -#endif diff --git a/arch/h8300/include/uapi/asm/posix_types.h b/arch/h8300/include/uapi/asm/posix_types.h deleted file mode 100644 index 91e62ba4c7b0..000000000000 --- a/arch/h8300/include/uapi/asm/posix_types.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ARCH_H8300_POSIX_TYPES_H -#define __ARCH_H8300_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned short __kernel_mode_t; -#define __kernel_mode_t __kernel_mode_t - -typedef unsigned short __kernel_ipc_pid_t; -#define __kernel_ipc_pid_t __kernel_ipc_pid_t - -typedef unsigned short __kernel_uid_t; -typedef unsigned short __kernel_gid_t; -#define __kernel_uid_t __kernel_uid_t - -typedef unsigned short __kernel_old_uid_t; -typedef unsigned short __kernel_old_gid_t; -#define __kernel_old_uid_t __kernel_old_uid_t - -#include - -#endif diff --git a/arch/h8300/include/uapi/asm/ptrace.h b/arch/h8300/include/uapi/asm/ptrace.h deleted file mode 100644 index ef39ec5977b6..000000000000 --- a/arch/h8300/include/uapi/asm/ptrace.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _UAPI_H8300_PTRACE_H -#define _UAPI_H8300_PTRACE_H - -#ifndef __ASSEMBLY__ - -#define PT_ER1 0 -#define PT_ER2 1 -#define PT_ER3 2 -#define PT_ER4 3 -#define PT_ER5 4 -#define PT_ER6 5 -#define PT_ER0 6 -#define PT_ORIG_ER0 7 -#define PT_CCR 8 -#define PT_PC 9 -#define PT_USP 10 -#define PT_EXR 12 - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long retpc; - long er4; - long er5; - long er6; - long er3; - long er2; - long er1; - long orig_er0; - unsigned short ccr; - long er0; - long vector; -#if defined(CONFIG_CPU_H8S) - unsigned short exr; -#endif - unsigned long pc; -} __attribute__((aligned(2),packed)); - -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 - -#endif /* __ASSEMBLY__ */ -#endif /* _UAPI_H8300_PTRACE_H */ diff --git a/arch/h8300/include/uapi/asm/resource.h b/arch/h8300/include/uapi/asm/resource.h deleted file mode 100644 index 46c5f4391607..000000000000 --- a/arch/h8300/include/uapi/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_RESOURCE_H -#define _H8300_RESOURCE_H - -#include - -#endif /* _H8300_RESOURCE_H */ diff --git a/arch/h8300/include/uapi/asm/sembuf.h b/arch/h8300/include/uapi/asm/sembuf.h deleted file mode 100644 index e04a3ec0cb92..000000000000 --- a/arch/h8300/include/uapi/asm/sembuf.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _H8300_SEMBUF_H -#define _H8300_SEMBUF_H - -/* - * The semid64_ds structure for m68k architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - unsigned long __unused1; - __kernel_time_t sem_ctime; /* last change time */ - unsigned long __unused2; - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _H8300_SEMBUF_H */ diff --git a/arch/h8300/include/uapi/asm/setup.h b/arch/h8300/include/uapi/asm/setup.h deleted file mode 100644 index e2c600e96733..000000000000 --- a/arch/h8300/include/uapi/asm/setup.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __H8300_SETUP_H -#define __H8300_SETUP_H - -#define COMMAND_LINE_SIZE 512 - -#endif diff --git a/arch/h8300/include/uapi/asm/shmbuf.h b/arch/h8300/include/uapi/asm/shmbuf.h deleted file mode 100644 index 64e77993a7a9..000000000000 --- a/arch/h8300/include/uapi/asm/shmbuf.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _H8300_SHMBUF_H -#define _H8300_SHMBUF_H - -/* - * The shmid64_ds structure for m68k architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - unsigned long __unused1; - __kernel_time_t shm_dtime; /* last detach time */ - unsigned long __unused2; - __kernel_time_t shm_ctime; /* last change time */ - unsigned long __unused3; - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused4; - unsigned long __unused5; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _H8300_SHMBUF_H */ diff --git a/arch/h8300/include/uapi/asm/sigcontext.h b/arch/h8300/include/uapi/asm/sigcontext.h deleted file mode 100644 index e4b81505f8f8..000000000000 --- a/arch/h8300/include/uapi/asm/sigcontext.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _ASM_H8300_SIGCONTEXT_H -#define _ASM_H8300_SIGCONTEXT_H - -struct sigcontext { - unsigned long sc_mask; /* old sigmask */ - unsigned long sc_usp; /* old user stack pointer */ - unsigned long sc_er0; - unsigned long sc_er1; - unsigned long sc_er2; - unsigned long sc_er3; - unsigned long sc_er4; - unsigned long sc_er5; - unsigned long sc_er6; - unsigned short sc_ccr; - unsigned long sc_pc; -}; - -#endif diff --git a/arch/h8300/include/uapi/asm/siginfo.h b/arch/h8300/include/uapi/asm/siginfo.h deleted file mode 100644 index bc8fbea931a5..000000000000 --- a/arch/h8300/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_SIGINFO_H -#define _H8300_SIGINFO_H - -#include - -#endif diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h deleted file mode 100644 index af3a6c37fee6..000000000000 --- a/arch/h8300/include/uapi/asm/signal.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef _UAPI_H8300_SIGNAL_H -#define _UAPI_H8300_SIGNAL_H - -#include - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 /* not supported yet */ -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - - -#endif /* _UAPI_H8300_SIGNAL_H */ diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h deleted file mode 100644 index 9490758c5e2b..000000000000 --- a/arch/h8300/include/uapi/asm/socket.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H - -#include - -/* For setsockoptions(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -#define SO_REUSEPORT 15 -#define SO_PASSCRED 16 -#define SO_PEERCRED 17 -#define SO_RCVLOWAT 18 -#define SO_SNDLOWAT 19 -#define SO_RCVTIMEO 20 -#define SO_SNDTIMEO 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 -#define SO_GET_FILTER SO_ATTACH_FILTER - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 -#define SO_PASSSEC 34 -#define SO_TIMESTAMPNS 35 -#define SCM_TIMESTAMPNS SO_TIMESTAMPNS - -#define SO_MARK 36 - -#define SO_TIMESTAMPING 37 -#define SCM_TIMESTAMPING SO_TIMESTAMPING - -#define SO_PROTOCOL 38 -#define SO_DOMAIN 39 - -#define SO_RXQ_OVFL 40 - -#define SO_WIFI_STATUS 41 -#define SCM_WIFI_STATUS SO_WIFI_STATUS -#define SO_PEEK_OFF 42 - -/* Instruct lower device to use last 4-bytes of skb data as FCS */ -#define SO_NOFCS 43 - -#define SO_LOCK_FILTER 44 - -#define SO_SELECT_ERR_QUEUE 45 - -#define SO_BUSY_POLL 46 - -#endif /* _ASM_SOCKET_H */ diff --git a/arch/h8300/include/uapi/asm/sockios.h b/arch/h8300/include/uapi/asm/sockios.h deleted file mode 100644 index e9c7ec810c23..000000000000 --- a/arch/h8300/include/uapi/asm/sockios.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __ARCH_H8300_SOCKIOS__ -#define __ARCH_H8300_SOCKIOS__ - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ -#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ - -#endif /* __ARCH_H8300_SOCKIOS__ */ diff --git a/arch/h8300/include/uapi/asm/stat.h b/arch/h8300/include/uapi/asm/stat.h deleted file mode 100644 index 62c3cc24dfe6..000000000000 --- a/arch/h8300/include/uapi/asm/stat.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _H8300_STAT_H -#define _H8300_STAT_H - -struct __old_kernel_stat { - unsigned short st_dev; - unsigned short st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned long st_size; - unsigned long st_atime; - unsigned long st_mtime; - unsigned long st_ctime; -}; - -struct stat { - unsigned short st_dev; - unsigned short __pad1; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned short __pad2; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long __unused1; - unsigned long st_mtime; - unsigned long __unused2; - unsigned long st_ctime; - unsigned long __unused3; - unsigned long __unused4; - unsigned long __unused5; -}; - -/* This matches struct stat64 in glibc2.1, hence the absolutely - * insane amounts of padding around dev_t's. - */ -struct stat64 { - unsigned long long st_dev; - unsigned char __pad1[2]; - -#define STAT64_HAS_BROKEN_ST_INO 1 - unsigned long __st_ino; - - unsigned int st_mode; - unsigned int st_nlink; - - unsigned long st_uid; - unsigned long st_gid; - - unsigned long long st_rdev; - unsigned char __pad3[2]; - - long long st_size; - unsigned long st_blksize; - - unsigned long __pad4; /* future possible st_blocks high bits */ - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ - - unsigned long st_atime; - unsigned long st_atime_nsec; - - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; - - unsigned long long st_ino; -}; - -#endif /* _H8300_STAT_H */ diff --git a/arch/h8300/include/uapi/asm/statfs.h b/arch/h8300/include/uapi/asm/statfs.h deleted file mode 100644 index b96efa712aac..000000000000 --- a/arch/h8300/include/uapi/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _H8300_STATFS_H -#define _H8300_STATFS_H - -#include - -#endif /* _H8300_STATFS_H */ diff --git a/arch/h8300/include/uapi/asm/swab.h b/arch/h8300/include/uapi/asm/swab.h deleted file mode 100644 index 39abbf52807d..000000000000 --- a/arch/h8300/include/uapi/asm/swab.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _H8300_SWAB_H -#define _H8300_SWAB_H - -#include - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __SWAB_64_THRU_32__ -#endif - -#endif /* _H8300_SWAB_H */ diff --git a/arch/h8300/include/uapi/asm/termbits.h b/arch/h8300/include/uapi/asm/termbits.h deleted file mode 100644 index 3287a6244d74..000000000000 --- a/arch/h8300/include/uapi/asm/termbits.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef __ARCH_H8300_TERMBITS_H__ -#define __ARCH_H8300_TERMBITS_H__ - -#include - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -struct termios2 { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -struct ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define BOTHER 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate */ -#define CMSPAR 010000000000 /* mark or space (stick) parity */ -#define CRTSCTS 020000000000 /* flow control */ - -#define IBSHIFT 16 /* shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 -#define EXTPROC 0200000 - - -/* tcflow() and TCXONC use these */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* __ARCH_H8300_TERMBITS_H__ */ diff --git a/arch/h8300/include/uapi/asm/termios.h b/arch/h8300/include/uapi/asm/termios.h deleted file mode 100644 index 5a67d7e38843..000000000000 --- a/arch/h8300/include/uapi/asm/termios.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _UAPI_H8300_TERMIOS_H -#define _UAPI_H8300_TERMIOS_H - -#include -#include - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - - -#endif /* _UAPI_H8300_TERMIOS_H */ diff --git a/arch/h8300/include/uapi/asm/types.h b/arch/h8300/include/uapi/asm/types.h deleted file mode 100644 index 9ec9d4c5ac4d..000000000000 --- a/arch/h8300/include/uapi/asm/types.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h deleted file mode 100644 index 8cb5d429f840..000000000000 --- a/arch/h8300/include/uapi/asm/unistd.h +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef _UAPI_ASM_H8300_UNISTD_H_ -#define _UAPI_ASM_H8300_UNISTD_H_ - -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_lchown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86old 113 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_modify_ldt 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_vm86 166 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_chown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_pivot_root 217 -#define __NR_mincore 218 -#define __NR_madvise 219 -#define __NR_madvise1 219 -#define __NR_getdents64 220 -#define __NR_fcntl64 221 -/* 223 is unused */ -#define __NR_gettid 224 -#define __NR_readahead 225 -#define __NR_setxattr 226 -#define __NR_lsetxattr 227 -#define __NR_fsetxattr 228 -#define __NR_getxattr 229 -#define __NR_lgetxattr 230 -#define __NR_fgetxattr 231 -#define __NR_listxattr 232 -#define __NR_llistxattr 233 -#define __NR_flistxattr 234 -#define __NR_removexattr 235 -#define __NR_lremovexattr 236 -#define __NR_fremovexattr 237 -#define __NR_tkill 238 -#define __NR_sendfile64 239 -#define __NR_futex 240 -#define __NR_sched_setaffinity 241 -#define __NR_sched_getaffinity 242 -#define __NR_set_thread_area 243 -#define __NR_get_thread_area 244 -#define __NR_io_setup 245 -#define __NR_io_destroy 246 -#define __NR_io_getevents 247 -#define __NR_io_submit 248 -#define __NR_io_cancel 249 -#define __NR_fadvise64 250 -/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ -#define __NR_exit_group 252 -#define __NR_lookup_dcookie 253 -#define __NR_epoll_create 254 -#define __NR_epoll_ctl 255 -#define __NR_epoll_wait 256 -#define __NR_remap_file_pages 257 -#define __NR_set_tid_address 258 -#define __NR_timer_create 259 -#define __NR_timer_settime (__NR_timer_create+1) -#define __NR_timer_gettime (__NR_timer_create+2) -#define __NR_timer_getoverrun (__NR_timer_create+3) -#define __NR_timer_delete (__NR_timer_create+4) -#define __NR_clock_settime (__NR_timer_create+5) -#define __NR_clock_gettime (__NR_timer_create+6) -#define __NR_clock_getres (__NR_timer_create+7) -#define __NR_clock_nanosleep (__NR_timer_create+8) -#define __NR_statfs64 268 -#define __NR_fstatfs64 269 -#define __NR_tgkill 270 -#define __NR_utimes 271 -#define __NR_fadvise64_64 272 -#define __NR_vserver 273 -#define __NR_mbind 274 -#define __NR_get_mempolicy 275 -#define __NR_set_mempolicy 276 -#define __NR_mq_open 277 -#define __NR_mq_unlink (__NR_mq_open+1) -#define __NR_mq_timedsend (__NR_mq_open+2) -#define __NR_mq_timedreceive (__NR_mq_open+3) -#define __NR_mq_notify (__NR_mq_open+4) -#define __NR_mq_getsetattr (__NR_mq_open+5) -#define __NR_kexec_load 283 -#define __NR_waitid 284 -/* #define __NR_sys_setaltroot 285 */ -#define __NR_add_key 286 -#define __NR_request_key 287 -#define __NR_keyctl 288 -#define __NR_ioprio_set 289 -#define __NR_ioprio_get 290 -#define __NR_inotify_init 291 -#define __NR_inotify_add_watch 292 -#define __NR_inotify_rm_watch 293 -#define __NR_migrate_pages 294 -#define __NR_openat 295 -#define __NR_mkdirat 296 -#define __NR_mknodat 297 -#define __NR_fchownat 298 -#define __NR_futimesat 299 -#define __NR_fstatat64 300 -#define __NR_unlinkat 301 -#define __NR_renameat 302 -#define __NR_linkat 303 -#define __NR_symlinkat 304 -#define __NR_readlinkat 305 -#define __NR_fchmodat 306 -#define __NR_faccessat 307 -#define __NR_pselect6 308 -#define __NR_ppoll 309 -#define __NR_unshare 310 -#define __NR_set_robust_list 311 -#define __NR_get_robust_list 312 -#define __NR_splice 313 -#define __NR_sync_file_range 314 -#define __NR_tee 315 -#define __NR_vmsplice 316 -#define __NR_move_pages 317 -#define __NR_getcpu 318 -#define __NR_epoll_pwait 319 -#define __NR_setns 320 - -#endif /* _UAPI_ASM_H8300_UNISTD_H_ */ diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile deleted file mode 100644 index 1cc57f872d34..000000000000 --- a/arch/h8300/kernel/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := vmlinux.lds - -obj-y := process.o traps.o ptrace.o irq.o \ - sys_h8300.o time.o signal.o \ - setup.o gpio.o syscalls.o \ - entry.o timer/ - -obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c deleted file mode 100644 index fd961e0bd741..000000000000 --- a/arch/h8300/kernel/asm-offsets.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int main(void) -{ - /* offsets into the task struct */ - DEFINE(TASK_STATE, offsetof(struct task_struct, state)); - DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); - DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); - DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); - DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); - - /* offsets into the thread struct */ - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr)); - - /* offsets into the pt_regs struct */ - DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long)); - DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long)); - DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long)); - DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long)); - DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long)); - DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long)); - DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long)); - DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long)); - DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long)); - DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long)); -#if defined(__H8300S__) - DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long)); -#endif - DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long)); - - DEFINE(PT_PTRACED, PT_PTRACED); - - return 0; -} diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S deleted file mode 100644 index 94bd30f11df6..000000000000 --- a/arch/h8300/kernel/entry.S +++ /dev/null @@ -1,402 +0,0 @@ -/* -*- mode: asm -*- - * - * linux/arch/h8300/platform/h8300h/entry.S - * - * Yoshinori Sato - * David McCullough - * - */ - -/* - * entry.S - * include exception/interrupt gateway - * system call entry - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CPU_H8300H) -#define USERRET 8 -INTERRUPTS = 64 - .h8300h - .macro SHLL2 reg - shll.l \reg - shll.l \reg - .endm - .macro SHLR2 reg - shlr.l \reg - shlr.l \reg - .endm - .macro SAVEREGS - mov.l er0,@-sp - mov.l er1,@-sp - mov.l er2,@-sp - mov.l er3,@-sp - .endm - .macro RESTOREREGS - mov.l @sp+,er3 - mov.l @sp+,er2 - .endm - .macro SAVEEXR - .endm - .macro RESTOREEXR - .endm -#endif -#if defined(CONFIG_CPU_H8S) -#define USERRET 10 -#define USEREXR 8 -INTERRUPTS = 128 - .h8300s - .macro SHLL2 reg - shll.l #2,\reg - .endm - .macro SHLR2 reg - shlr.l #2,\reg - .endm - .macro SAVEREGS - stm.l er0-er3,@-sp - .endm - .macro RESTOREREGS - ldm.l @sp+,er2-er3 - .endm - .macro SAVEEXR - mov.w @(USEREXR:16,er0),r1 - mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */ - .endm - .macro RESTOREEXR - mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */ - mov.b r1l,r1h - mov.w r1,@(USEREXR:16,er0) - .endm -#endif - - -/* CPU context save/restore macros. */ - - .macro SAVE_ALL - mov.l er0,@-sp - stc ccr,r0l /* check kernel mode */ - btst #4,r0l - bne 5f - - /* user mode */ - mov.l sp,@_sw_usp - mov.l @sp,er0 /* restore saved er0 */ - orc #0x10,ccr /* switch kernel stack */ - mov.l @_sw_ksp,sp - sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */ - SAVEREGS - mov.l @_sw_usp,er0 - mov.l @(USERRET:16,er0),er1 /* copy the RET addr */ - mov.l er1,@(LRET-LER3:16,sp) - SAVEEXR - - mov.l @(LORIG-LER3:16,sp),er0 - mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */ - mov.w e1,r1 /* e1 highbyte = ccr */ - and #0xef,r1h /* mask mode? flag */ - bra 6f -5: - /* kernel mode */ - mov.l @sp,er0 /* restore saved er0 */ - subs #2,sp /* set dummy ccr */ - SAVEREGS - mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */ -6: - mov.b r1h,r1l - mov.b #0,r1h - mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */ - mov.l er6,@-sp /* syscall arg #6 */ - mov.l er5,@-sp /* syscall arg #5 */ - mov.l er4,@-sp /* syscall arg #4 */ - .endm /* r1 = ccr */ - - .macro RESTORE_ALL - mov.l @sp+,er4 - mov.l @sp+,er5 - mov.l @sp+,er6 - RESTOREREGS - mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */ - btst #4,r0l - bne 7f - - orc #0x80,ccr - mov.l @_sw_usp,er0 - mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ - mov.l er1,@er0 - RESTOREEXR - mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ - mov.b r1l,r1h - mov.b @(LRET+1-LER1:16,sp),r1l - mov.w r1,e1 - mov.w @(LRET+2-LER1:16,sp),r1 - mov.l er1,@(USERRET:16,er0) - - mov.l @sp+,er1 - add.l #(LRET-LER1),sp /* remove LORIG - LRET */ - mov.l sp,@_sw_ksp - andc #0xef,ccr /* switch to user mode */ - mov.l er0,sp - bra 8f -7: - mov.l @sp+,er1 - adds #4,sp - adds #2,sp -8: - mov.l @sp+,er0 - adds #4,sp /* remove the sw created LVEC */ - rte - .endm - -.globl _system_call -.globl _ret_from_exception -.globl _ret_from_fork -.globl _ret_from_kernel_thread -.globl _ret_from_interrupt -.globl _interrupt_redirect_table -.globl _sw_ksp,_sw_usp -.globl _resume -.globl _interrupt_entry -.globl _trace_break - -#if defined(CONFIG_ROMKERNEL) - .section .int_redirect,"ax" -_interrupt_redirect_table: -#if defined(CONFIG_CPU_H8300H) - .rept 7 - .long 0 - .endr -#endif -#if defined(CONFIG_CPU_H8S) - .rept 5 - .long 0 - .endr - jmp @_trace_break - .long 0 -#endif - - jsr @_interrupt_entry /* NMI */ - jmp @_system_call /* TRAPA #0 (System call) */ - .long 0 - .long 0 - jmp @_trace_break /* TRAPA #3 (breakpoint) */ - .rept INTERRUPTS-12 - jsr @_interrupt_entry - .endr -#endif -#if defined(CONFIG_RAMKERNEL) -.globl _interrupt_redirect_table - .section .bss -_interrupt_redirect_table: - .space 4 -#endif - - .section .text - .align 2 -_interrupt_entry: - SAVE_ALL - mov.l sp,er0 - add.l #LVEC,er0 - btst #4,r1l - bne 1f - /* user LVEC */ - mov.l @_sw_usp,er0 - adds #4,er0 -1: - mov.l @er0,er0 /* LVEC address */ -#if defined(CONFIG_ROMKERNEL) - sub.l #_interrupt_redirect_table,er0 -#endif -#if defined(CONFIG_RAMKERNEL) - mov.l @_interrupt_redirect_table,er1 - sub.l er1,er0 -#endif - SHLR2 er0 - dec.l #1,er0 - mov.l sp,er1 - subs #4,er1 /* adjust ret_pc */ - jsr @_do_IRQ - jmp @_ret_from_interrupt - -_system_call: - subs #4,sp /* dummy LVEC */ - SAVE_ALL - andc #0x7f,ccr - mov.l er0,er4 - - /* save top of frame */ - mov.l sp,er0 - jsr @_set_esp0 - mov.l sp,er2 - and.w #0xe000,r2 - mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l - btst #(TIF_SYSCALL_TRACE & 7),r2l - beq 1f - jsr @_do_syscall_trace -1: - cmp.l #NR_syscalls,er4 - bcc badsys - SHLL2 er4 - mov.l #_sys_call_table,er0 - add.l er4,er0 - mov.l @er0,er4 - beq _ret_from_exception:16 - mov.l @(LER1:16,sp),er0 - mov.l @(LER2:16,sp),er1 - mov.l @(LER3:16,sp),er2 - jsr @er4 - mov.l er0,@(LER0:16,sp) /* save the return value */ - mov.l sp,er2 - and.w #0xe000,r2 - mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l - btst #(TIF_SYSCALL_TRACE & 7),r2l - beq 2f - jsr @_do_syscall_trace -2: -#if defined(CONFIG_SYSCALL_PRINT) - jsr @_syscall_print -#endif - orc #0x80,ccr - bra resume_userspace - -badsys: - mov.l #-ENOSYS,er0 - mov.l er0,@(LER0:16,sp) - bra resume_userspace - -#if !defined(CONFIG_PREEMPT) -#define resume_kernel restore_all -#endif - -_ret_from_exception: -#if defined(CONFIG_PREEMPT) - orc #0x80,ccr -#endif -_ret_from_interrupt: - mov.b @(LCCR+1:16,sp),r0l - btst #4,r0l - bne resume_kernel:8 /* return from kernel */ -resume_userspace: - andc #0x7f,ccr - mov.l sp,er4 - and.w #0xe000,r4 /* er4 <- current thread info */ - mov.l @(TI_FLAGS:16,er4),er1 - and.l #_TIF_WORK_MASK,er1 - beq restore_all:8 -work_pending: - btst #TIF_NEED_RESCHED,r1l - bne work_resched:8 - /* work notifysig */ - mov.l sp,er0 - subs #4,er0 /* er0: pt_regs */ - jsr @_do_notify_resume - bra restore_all:8 -work_resched: - mov.l sp,er0 - jsr @_set_esp0 - jsr @_schedule - bra resume_userspace:8 -restore_all: - RESTORE_ALL /* Does RTE */ - -#if defined(CONFIG_PREEMPT) -resume_kernel: - mov.l @(TI_PRE_COUNT:16,er4),er0 - bne restore_all:8 -need_resched: - mov.l @(TI_FLAGS:16,er4),er0 - btst #TIF_NEED_RESCHED,r0l - beq restore_all:8 - mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */ - bmi restore_all:8 - mov.l #PREEMPT_ACTIVE,er0 - mov.l er0,@(TI_PRE_COUNT:16,er4) - andc #0x7f,ccr - mov.l sp,er0 - jsr @_set_esp0 - jsr @_schedule - orc #0x80,ccr - bra need_resched:8 -#endif - -_ret_from_fork: - mov.l er2,er0 - jsr @_schedule_tail - jmp @_ret_from_exception - -_ret_from_kernel_thread: - mov.l er2,er0 - jsr @_schedule_tail - mov.l @(LER4:16,sp),er0 - mov.l @(LER5:16,sp),er1 - jsr @er1 - jmp @_ret_from_exception - -_resume: - /* - * Beware - when entering resume, offset of tss is in d1, - * prev (the current task) is in a0, next (the new task) - * is in a1 and d2.b is non-zero if the mm structure is - * shared between the tasks, so don't change these - * registers until their contents are no longer needed. - */ - - /* save sr */ - sub.w r3,r3 - stc ccr,r3l - mov.w r3,@(THREAD_CCR+2:16,er0) - - /* disable interrupts */ - orc #0x80,ccr - mov.l @_sw_usp,er3 - mov.l er3,@(THREAD_USP:16,er0) - mov.l sp,@(THREAD_KSP:16,er0) - - /* Skip address space switching if they are the same. */ - /* FIXME: what did we hack out of here, this does nothing! */ - - mov.l @(THREAD_USP:16,er1),er0 - mov.l er0,@_sw_usp - mov.l @(THREAD_KSP:16,er1),sp - - /* restore status register */ - mov.w @(THREAD_CCR+2:16,er1),r3 - - ldc r3l,ccr - rts - -_trace_break: - subs #4,sp - SAVE_ALL - sub.l er1,er1 - dec.l #1,er1 - mov.l er1,@(LORIG,sp) - mov.l sp,er0 - jsr @_set_esp0 - mov.l @_sw_usp,er0 - mov.l @er0,er1 - mov.w @(-2:16,er1),r2 - cmp.w #0x5730,r2 - beq 1f - subs #2,er1 - mov.l er1,@er0 -1: - and.w #0xff,e1 - mov.l er1,er0 - jsr @_trace_trap - jmp @_ret_from_exception - - .section .bss -_sw_ksp: - .space 4 -_sw_usp: - .space 4 - - .end diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c deleted file mode 100644 index 084bfd0c107e..000000000000 --- a/arch/h8300/kernel/gpio.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * linux/arch/h8300/kernel/gpio.c - * - * Yoshinori Sato - * - */ - -/* - * Internal I/O Port Management - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _(addr) (volatile unsigned char *)(addr) -#if defined(CONFIG_H83007) || defined(CONFIG_H83068) -#include -static volatile unsigned char *ddrs[] = { - _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), - NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), -}; -#define MAX_PORT 11 -#endif - - #if defined(CONFIG_H83002) || defined(CONFIG_H8048) -/* Fix me!! */ -#include -static volatile unsigned char *ddrs[] = { - _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), - NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), -}; -#define MAX_PORT 11 -#endif - -#if defined(CONFIG_H8S2678) -#include -static volatile unsigned char *ddrs[] = { - _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR), - _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR), - _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR), - _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR), - _(PGDDR),_(PHDDR) -}; -#define MAX_PORT 17 -#endif -#undef _ - -#if !defined(P1DDR) -#error Unsuppoted CPU Selection -#endif - -static struct { - unsigned char used; - unsigned char ddr; -} gpio_regs[MAX_PORT]; - -extern char *_platform_gpio_table(int length); - -int h8300_reserved_gpio(int port, unsigned int bits) -{ - unsigned char *used; - - if (port < 0 || port >= MAX_PORT) - return -1; - used = &(gpio_regs[port].used); - if ((*used & bits) != 0) - return 0; - *used |= bits; - return 1; -} - -int h8300_free_gpio(int port, unsigned int bits) -{ - unsigned char *used; - - if (port < 0 || port >= MAX_PORT) - return -1; - used = &(gpio_regs[port].used); - if ((*used & bits) != bits) - return 0; - *used &= (~bits); - return 1; -} - -int h8300_set_gpio_dir(int port_bit,int dir) -{ - int port = (port_bit >> 8) & 0xff; - int bit = port_bit & 0xff; - - if (ddrs[port] == NULL) - return 0; - if (gpio_regs[port].used & bit) { - if (dir) - gpio_regs[port].ddr |= bit; - else - gpio_regs[port].ddr &= ~bit; - *ddrs[port] = gpio_regs[port].ddr; - return 1; - } else - return 0; -} - -int h8300_get_gpio_dir(int port_bit) -{ - int port = (port_bit >> 8) & 0xff; - int bit = port_bit & 0xff; - - if (ddrs[port] == NULL) - return 0; - if (gpio_regs[port].used & bit) { - return (gpio_regs[port].ddr & bit) != 0; - } else - return -1; -} - -#if defined(CONFIG_PROC_FS) -static char *port_status(int portno) -{ - static char result[10]; - static const char io[2]={'I','O'}; - char *rp; - int c; - unsigned char used,ddr; - - used = gpio_regs[portno].used; - ddr = gpio_regs[portno].ddr; - result[8]='\0'; - rp = result + 7; - for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1) - if (used & 0x01) - *rp = io[ ddr & 0x01]; - else - *rp = '-'; - return result; -} - -static int gpio_proc_show(struct seq_file *m, void *v) -{ - static const char port_name[]="123456789ABCDEFGH"; - int c; - - for (c = 0; c < MAX_PORT; c++) { - if (ddrs[c] == NULL) - continue; - seq_printf(m, "P%c: %s\n", port_name[c], port_status(c)); - } - return 0; -} - -static int gpio_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, gpio_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations gpio_proc_fops = { - .open = gpio_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static __init int register_proc(void) -{ - return proc_create("gpio", S_IRUGO, NULL, &gpio_proc_fops) != NULL; -} - -__initcall(register_proc); -#endif - -void __init h8300_gpio_init(void) -{ - memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs)); -} diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c deleted file mode 100644 index 53d7c0e4bd83..000000000000 --- a/arch/h8300/kernel/h8300_ksyms.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -//asmlinkage long long __ashrdi3 (long long, int); -//asmlinkage long long __lshrdi3 (long long, int); -extern char h8300_debug_device[]; - -/* platform dependent support */ - -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); - -EXPORT_SYMBOL(ip_fast_csum); - -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); - -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy_nocheck); - -/* The following are special because they're not called - explicitly (the C compiler generates them). Fortunately, - their interface isn't gonna change any time soon now, so - it's OK to leave it out of version control. */ -//EXPORT_SYMBOL(__ashrdi3); -//EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memscan); -EXPORT_SYMBOL(memmove); - -/* - * libgcc functions - functions that are used internally by the - * compiler... (prototypes are not correct though, but that - * doesn't really matter since they're not versioned). - */ -extern void __gcc_bcmp(void); -extern void __ashldi3(void); -extern void __ashrdi3(void); -extern void __cmpdi2(void); -extern void __divdi3(void); -extern void __divsi3(void); -extern void __lshrdi3(void); -extern void __moddi3(void); -extern void __modsi3(void); -extern void __muldi3(void); -extern void __mulsi3(void); -extern void __negdi2(void); -extern void __ucmpdi2(void); -extern void __udivdi3(void); -extern void __udivmoddi4(void); -extern void __udivsi3(void); -extern void __umoddi3(void); -extern void __umodsi3(void); - - /* gcc lib functions */ -EXPORT_SYMBOL(__gcc_bcmp); -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__cmpdi2); -EXPORT_SYMBOL(__divdi3); -EXPORT_SYMBOL(__divsi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__moddi3); -EXPORT_SYMBOL(__modsi3); -EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL(__mulsi3); -EXPORT_SYMBOL(__negdi2); -EXPORT_SYMBOL(__ucmpdi2); -EXPORT_SYMBOL(__udivdi3); -EXPORT_SYMBOL(__udivmoddi4); -EXPORT_SYMBOL(__udivsi3); -EXPORT_SYMBOL(__umoddi3); -EXPORT_SYMBOL(__umodsi3); - -EXPORT_SYMBOL(h8300_reserved_gpio); -EXPORT_SYMBOL(h8300_free_gpio); -EXPORT_SYMBOL(h8300_set_gpio_dir); diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c deleted file mode 100644 index 2fa8ac7b79b5..000000000000 --- a/arch/h8300/kernel/irq.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * linux/arch/h8300/kernel/irq.c - * - * Copyright 2007 Yoshinori Sato - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/*#define DEBUG*/ - -extern unsigned long *interrupt_redirect_table; -extern const int h8300_saved_vectors[]; -extern const h8300_vector h8300_trap_table[]; -int h8300_enable_irq_pin(unsigned int irq); -void h8300_disable_irq_pin(unsigned int irq); - -#define CPU_VECTOR ((unsigned long *)0x000000) -#define ADDR_MASK (0xffffff) - -static inline int is_ext_irq(unsigned int irq) -{ - return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS)); -} - -static void h8300_enable_irq(struct irq_data *data) -{ - if (is_ext_irq(data->irq)) - IER_REGS |= 1 << (data->irq - EXT_IRQ0); -} - -static void h8300_disable_irq(struct irq_data *data) -{ - if (is_ext_irq(data->irq)) - IER_REGS &= ~(1 << (data->irq - EXT_IRQ0)); -} - -static unsigned int h8300_startup_irq(struct irq_data *data) -{ - if (is_ext_irq(data->irq)) - return h8300_enable_irq_pin(data->irq); - else - return 0; -} - -static void h8300_shutdown_irq(struct irq_data *data) -{ - if (is_ext_irq(data->irq)) - h8300_disable_irq_pin(data->irq); -} - -/* - * h8300 interrupt controller implementation - */ -struct irq_chip h8300irq_chip = { - .name = "H8300-INTC", - .irq_startup = h8300_startup_irq, - .irq_shutdown = h8300_shutdown_irq, - .irq_enable = h8300_enable_irq, - .irq_disable = h8300_disable_irq, -}; - -#if defined(CONFIG_RAMKERNEL) -static unsigned long __init *get_vector_address(void) -{ - unsigned long *rom_vector = CPU_VECTOR; - unsigned long base,tmp; - int vec_no; - - base = rom_vector[EXT_IRQ0] & ADDR_MASK; - - /* check romvector format */ - for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) { - if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK)) - return NULL; - } - - /* ramvector base address */ - base -= EXT_IRQ0*4; - - /* writerble check */ - tmp = ~(*(volatile unsigned long *)base); - (*(volatile unsigned long *)base) = tmp; - if ((*(volatile unsigned long *)base) != tmp) - return NULL; - return (unsigned long *)base; -} - -static void __init setup_vector(void) -{ - int i; - unsigned long *ramvec,*ramvec_p; - const h8300_vector *trap_entry; - const int *saved_vector; - - ramvec = get_vector_address(); - if (ramvec == NULL) - panic("interrupt vector serup failed."); - else - printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec); - - /* create redirect table */ - ramvec_p = ramvec; - trap_entry = h8300_trap_table; - saved_vector = h8300_saved_vectors; - for ( i = 0; i < NR_IRQS; i++) { - if (i == *saved_vector) { - ramvec_p++; - saved_vector++; - } else { - if ( i < NR_TRAPS ) { - if (*trap_entry) - *ramvec_p = VECTOR(*trap_entry); - ramvec_p++; - trap_entry++; - } else - *ramvec_p++ = REDIRECT(interrupt_entry); - } - } - interrupt_redirect_table = ramvec; -#ifdef DEBUG - ramvec_p = ramvec; - for (i = 0; i < NR_IRQS; i++) { - if ((i % 8) == 0) - printk(KERN_DEBUG "\n%p: ",ramvec_p); - printk(KERN_DEBUG "%p ",*ramvec_p); - ramvec_p++; - } - printk(KERN_DEBUG "\n"); -#endif -} -#else -#define setup_vector() do { } while(0) -#endif - -void __init init_IRQ(void) -{ - int c; - - setup_vector(); - - for (c = 0; c < NR_IRQS; c++) - irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq); -} - -asmlinkage void do_IRQ(int irq) -{ - irq_enter(); - generic_handle_irq(irq); - irq_exit(); -} diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c deleted file mode 100644 index 1d526e05db19..000000000000 --- a/arch/h8300/kernel/module.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { - /* This is where to make the change */ - uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr - + rela[i].r_offset); - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rela[i].r_info); - uint32_t v = sym->st_value + rela[i].r_addend; - - switch (ELF32_R_TYPE(rela[i].r_info)) { - case R_H8_DIR24R8: - loc = (uint32_t *)((uint32_t)loc - 1); - *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); - break; - case R_H8_DIR24A8: - if (ELF32_R_SYM(rela[i].r_info)) - *loc += v; - break; - case R_H8_DIR32: - case R_H8_DIR32A16: - *loc += v; - break; - case R_H8_PCREL16: - v -= (unsigned long)loc + 2; - if ((Elf32_Sword)v > 0x7fff || - (Elf32_Sword)v < -(Elf32_Sword)0x8000) - goto overflow; - else - *(unsigned short *)loc = v; - break; - case R_H8_PCREL8: - v -= (unsigned long)loc + 1; - if ((Elf32_Sword)v > 0x7f || - (Elf32_Sword)v < -(Elf32_Sword)0x80) - goto overflow; - else - *(unsigned char *)loc = v; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rela[i].r_info)); - return -ENOEXEC; - } - } - return 0; - overflow: - printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", - me->name, rela[i].r_offset); - return -ENOEXEC; -} diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c deleted file mode 100644 index 1a744ab7e7e5..000000000000 --- a/arch/h8300/kernel/process.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * linux/arch/h8300/kernel/process.c - * - * Yoshinori Sato - * - * Based on: - * - * linux/arch/m68knommu/kernel/process.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Kenneth Albanowski , - * The Silver Hammer Group, Ltd. - * - * linux/arch/m68k/kernel/process.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * 68060 fixes by Jesper Skov - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -void (*pm_power_off)(void) = NULL; -EXPORT_SYMBOL(pm_power_off); - -asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); - -/* - * The idle loop on an H8/300.. - */ -#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM) -void arch_cpu_idle(void) -{ - local_irq_enable(); - /* XXX: race here! What if need_resched() gets set now? */ - __asm__("sleep"); -} -#endif - -void machine_restart(char * __unused) -{ - local_irq_disable(); - __asm__("jmp @@0"); -} - -void machine_halt(void) -{ - local_irq_disable(); - __asm__("sleep"); - for (;;); -} - -void machine_power_off(void) -{ - local_irq_disable(); - __asm__("sleep"); - for (;;); -} - -void show_regs(struct pt_regs * regs) -{ - show_regs_print_info(KERN_DEFAULT); - - printk("\nPC: %08lx Status: %02x", - regs->pc, regs->ccr); - printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx", - regs->orig_er0, regs->er0, regs->er1); - printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx", - regs->er2, regs->er3, regs->er4, regs->er5); - printk("\nER6' %08lx ",regs->er6); - if (user_mode(regs)) - printk("USP: %08lx\n", rdusp()); - else - printk("\n"); -} - -void flush_thread(void) -{ -} - -int copy_thread(unsigned long clone_flags, - unsigned long usp, unsigned long topstk, - struct task_struct * p) -{ - struct pt_regs * childregs; - - childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; - - if (unlikely(p->flags & PF_KTHREAD)) { - memset(childregs, 0, sizeof(struct pt_regs)); - childregs->retpc = (unsigned long) ret_from_kernel_thread; - childregs->er4 = topstk; /* arg */ - childregs->er5 = usp; /* fn */ - p->thread.ksp = (unsigned long)childregs; - } - *childregs = *current_pt_regs(); - childregs->retpc = (unsigned long) ret_from_fork; - childregs->er0 = 0; - p->thread.usp = usp ?: rdusp(); - p->thread.ksp = (unsigned long)childregs; - - return 0; -} - -unsigned long thread_saved_pc(struct task_struct *tsk) -{ - return ((struct pt_regs *)tsk->thread.esp0)->pc; -} - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long fp, pc; - unsigned long stack_page; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - stack_page = (unsigned long)p; - fp = ((struct pt_regs *)p->thread.ksp)->er6; - do { - if (fp < stack_page+sizeof(struct thread_info) || - fp >= 8184+stack_page) - return 0; - pc = ((unsigned long *)fp)[1]; - if (!in_sched_functions(pc)) - return pc; - fp = *(unsigned long *) fp; - } while (count++ < 16); - return 0; -} diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c deleted file mode 100644 index 748cf6585aa4..000000000000 --- a/arch/h8300/kernel/ptrace.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * linux/arch/h8300/kernel/ptrace.c - * - * Yoshinori Sato - * - * Based on: - * linux/arch/m68k/kernel/ptrace.c - * - * Copyright (C) 1994 by Hamish Macdonald - * Taken from linux/kernel/ptrace.c and modified for M680x0. - * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* cpu depend functions */ -extern long h8300_get_reg(struct task_struct *task, int regno); -extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data); - - -void user_disable_single_step(struct task_struct *child) -{ -} - -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - int regno = addr >> 2; - unsigned long __user *datap = (unsigned long __user *) data; - - switch (request) { - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp = 0; - - if ((addr & 3) || addr >= sizeof(struct user)) { - ret = -EIO; - break ; - } - - ret = 0; /* Default return condition */ - - if (regno < H8300_REGS_NO) - tmp = h8300_get_reg(child, regno); - else { - switch (regno) { - case 49: - tmp = child->mm->start_code; - break ; - case 50: - tmp = child->mm->start_data; - break ; - case 51: - tmp = child->mm->end_code; - break ; - case 52: - tmp = child->mm->end_data; - break ; - default: - ret = -EIO; - } - } - if (!ret) - ret = put_user(tmp, datap); - break ; - } - - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - if ((addr & 3) || addr >= sizeof(struct user)) { - ret = -EIO; - break ; - } - - if (regno == PT_ORIG_ER0) { - ret = -EIO; - break ; - } - if (regno < H8300_REGS_NO) { - ret = h8300_put_reg(child, regno, data); - break ; - } - ret = -EIO; - break ; - - case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - int i; - unsigned long tmp; - for (i = 0; i < H8300_REGS_NO; i++) { - tmp = h8300_get_reg(child, i); - if (put_user(tmp, datap)) { - ret = -EFAULT; - break; - } - datap++; - } - ret = 0; - break; - } - - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - int i; - unsigned long tmp; - for (i = 0; i < H8300_REGS_NO; i++) { - if (get_user(tmp, datap)) { - ret = -EFAULT; - break; - } - h8300_put_reg(child, i, tmp); - datap++; - } - ret = 0; - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - return ret; -} - -asmlinkage void do_syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(current->ptrace & PT_PTRACED)) - return; - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c deleted file mode 100644 index d0b1607f2711..000000000000 --- a/arch/h8300/kernel/setup.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * linux/arch/h8300/kernel/setup.c - * - * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} - * Copyright (C) 1999,2000 Greg Ungerer (gerg@snapgear.com) - * Copyright (C) 1998,1999 D. Jeff Dionne - * Copyright (C) 1998 Kenneth Albanowski - * Copyright (C) 1995 Hamish Macdonald - * Copyright (C) 2000 Lineo Inc. (www.lineo.com) - * Copyright (C) 2001 Lineo, Inc. - * - * H8/300 porting Yoshinori Sato - */ - -/* - * This file handles the architecture-dependent parts of system setup - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(__H8300H__) -#define CPU "H8/300H" -#include -#endif - -#if defined(__H8300S__) -#define CPU "H8S" -#include -#endif - -#define STUBSIZE 0xc000 - -unsigned long rom_length; -unsigned long memory_start; -unsigned long memory_end; - -char __initdata command_line[COMMAND_LINE_SIZE]; - -extern int _ramstart, _ramend; -extern char _target_name[]; -extern void h8300_gpio_init(void); - -#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \ - && defined(CONFIG_GDB_MAGICPRINT) -/* printk with gdb service */ -static void gdb_console_output(struct console *c, const char *msg, unsigned len) -{ - for (; len > 0; len--) { - asm("mov.w %0,r2\n\t" - "jsr @0xc4"::"r"(*msg++):"er2"); - } -} - -/* - * Setup initial baud/bits/parity. We do two things here: - * - construct a cflag setting for the first rs_open() - * - initialize the serial port - * Return non-zero if we didn't find a serial port. - */ -static int __init gdb_console_setup(struct console *co, char *options) -{ - return 0; -} - -static const struct console gdb_console = { - .name = "gdb_con", - .write = gdb_console_output, - .device = NULL, - .setup = gdb_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; -#endif - -void __init setup_arch(char **cmdline_p) -{ - int bootmap_size; - - memory_start = (unsigned long) &_ramstart; - - /* allow for ROMFS on the end of the kernel */ - if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) { -#if defined(CONFIG_BLK_DEV_INITRD) - initrd_start = memory_start; - initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]); -#else - memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]); -#endif - } - memory_start = PAGE_ALIGN(memory_start); -#if !defined(CONFIG_BLKDEV_RESERVE) - memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */ -#if defined(CONFIG_GDB_DEBUG) - memory_end -= STUBSIZE; -#endif -#else - if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && - (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS)) - /* overlap userarea */ - memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; -#endif - - init_mm.start_code = (unsigned long) _stext; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) 0; - -#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT) - register_console((struct console *)&gdb_console); -#endif - - printk(KERN_INFO "\r\n\nuClinux " CPU "\n"); - printk(KERN_INFO "Target Hardware: %s\n",_target_name); - printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); - printk(KERN_INFO "H8/300 series support by Yoshinori Sato \n"); - -#ifdef DEBUG - printk(KERN_DEBUG "KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p " - "BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start, - __bss_stop); - printk(KERN_DEBUG "KERNEL -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx " - "STACK=0x%06lx-0x%p\n", __bss_stop, memory_start, memory_start, - memory_end, memory_end, &_ramend); -#endif - -#ifdef CONFIG_DEFAULT_CMDLINE - /* set from default command line */ - if (*command_line == '\0') - strcpy(command_line,CONFIG_KERNEL_COMMAND); -#endif - /* Keep a copy of command line */ - *cmdline_p = &command_line[0]; - memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); - boot_command_line[COMMAND_LINE_SIZE-1] = 0; - -#ifdef DEBUG - if (strlen(*cmdline_p)) - printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p); -#endif - - /* - * give all the memory to the bootmap allocator, tell it to put the - * boot mem_map at the start of memory - */ - bootmap_size = init_bootmem_node( - NODE_DATA(0), - memory_start >> PAGE_SHIFT, /* map goes here */ - PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */ - memory_end >> PAGE_SHIFT); - /* - * free the usable memory, we have to make sure we do not free - * the bootmem bitmap so we then reserve it after freeing it :-) - */ - free_bootmem(memory_start, memory_end - memory_start); - reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT); - /* - * get kmalloc into gear - */ - paging_init(); - h8300_gpio_init(); -#if defined(CONFIG_H8300_AKI3068NET) && defined(CONFIG_IDE) - { -#define AREABIT(addr) (1 << (((addr) >> 21) & 7)) - /* setup BSC */ - volatile unsigned char *abwcr = (volatile unsigned char *)ABWCR; - volatile unsigned char *cscr = (volatile unsigned char *)CSCR; - *abwcr &= ~(AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)); - *cscr |= (AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)) | 0x0f; - } -#endif -#ifdef DEBUG - printk(KERN_DEBUG "Done setup_arch\n"); -#endif -} - -/* - * Get CPU information for use by the procfs. - */ - -static int show_cpuinfo(struct seq_file *m, void *v) -{ - char *cpu; - int mode; - u_long clockfreq; - - cpu = CPU; - mode = *(volatile unsigned char *)MDCR & 0x07; - - clockfreq = CONFIG_CPU_CLOCK; - - seq_printf(m, "CPU:\t\t%s (mode:%d)\n" - "Clock:\t\t%lu.%1luMHz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu,mode, - clockfreq/1000,clockfreq%1000, - (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, - (loops_per_jiffy*HZ)); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return c_start(m, pos); -} - -static void c_stop(struct seq_file *m, void *v) -{ -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c deleted file mode 100644 index a65ff3b76326..000000000000 --- a/arch/h8300/kernel/signal.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * linux/arch/h8300/kernel/signal.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -/* - * uClinux H8/300 support by Yoshinori Sato - * and David McCullough - * - * Based on - * Linux/m68k by Hamish Macdonald - */ - -/* - * ++roman (07/09/96): implemented signal stacks (specially for tosemu on - * Atari :-) Current limitation: Only one sigstack can be active at one time. - * If a second signal with SA_ONSTACK set arrives while working on a sigstack, - * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested - * signal handlers! - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Do a signal return; undo the signal stack. - * - * Keep the return code on the stack quadword aligned! - * That makes the cache flush below easier. - */ - -struct sigframe -{ - long dummy_er0; - long dummy_vector; -#if defined(CONFIG_CPU_H8S) - short dummy_exr; -#endif - long dummy_pc; - char *pretcode; - unsigned char retcode[8]; - unsigned long extramask[_NSIG_WORDS-1]; - struct sigcontext sc; - int sig; -} __attribute__((aligned(2),packed)); - -struct rt_sigframe -{ - long dummy_er0; - long dummy_vector; -#if defined(CONFIG_CPU_H8S) - short dummy_exr; -#endif - long dummy_pc; - char *pretcode; - struct siginfo *pinfo; - void *puc; - unsigned char retcode[8]; - struct siginfo info; - struct ucontext uc; - int sig; -} __attribute__((aligned(2),packed)); - -static inline int -restore_sigcontext(struct sigcontext *usc, int *pd0) -{ - struct pt_regs *regs = current_pt_regs(); - int err = 0; - unsigned int ccr; - unsigned int usp; - unsigned int er0; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - -#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r) /* restore passed registers */ - COPY(er1); - COPY(er2); - COPY(er3); - COPY(er5); - COPY(pc); - ccr = regs->ccr & 0x10; - COPY(ccr); -#undef COPY - regs->ccr &= 0xef; - regs->ccr |= ccr; - regs->orig_er0 = -1; /* disable syscall checks */ - err |= __get_user(usp, &usc->sc_usp); - wrusp(usp); - - err |= __get_user(er0, &usc->sc_er0); - *pd0 = er0; - return err; -} - -asmlinkage int sys_sigreturn(void) -{ - unsigned long usp = rdusp(); - struct sigframe *frame = (struct sigframe *)(usp - 4); - sigset_t set; - int er0; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.sc_mask) || - (_NSIG_WORDS > 1 && - __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(&frame->sc, &er0)) - goto badframe; - return er0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(void) -{ - unsigned long usp = rdusp(); - struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); - sigset_t set; - int er0; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(&frame->uc.uc_mcontext, &er0)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - return er0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err = 0; - - err |= __put_user(regs->er0, &sc->sc_er0); - err |= __put_user(regs->er1, &sc->sc_er1); - err |= __put_user(regs->er2, &sc->sc_er2); - err |= __put_user(regs->er3, &sc->sc_er3); - err |= __put_user(regs->er4, &sc->sc_er4); - err |= __put_user(regs->er5, &sc->sc_er5); - err |= __put_user(regs->er6, &sc->sc_er6); - err |= __put_user(rdusp(), &sc->sc_usp); - err |= __put_user(regs->pc, &sc->sc_pc); - err |= __put_user(regs->ccr, &sc->sc_ccr); - err |= __put_user(mask, &sc->sc_mask); - - return err; -} - -static inline void * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) -{ - unsigned long usp; - - /* Default to using normal stack. */ - usp = rdusp(); - - /* This is the X/Open sanctioned signal stack switching. */ - if (ka->sa.sa_flags & SA_ONSTACK) { - if (!sas_ss_flags(usp)) - usp = current->sas_ss_sp + current->sas_ss_size; - } - return (void *)((usp - frame_size) & -8UL); -} - -static int setup_frame (int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe *frame; - int err = 0; - int usig; - unsigned char *ret; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - usig = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(usig, &frame->sig); - if (err) - goto give_sigsegv; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - if (err) - goto give_sigsegv; - - if (_NSIG_WORDS > 1) { - err |= copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - if (err) - goto give_sigsegv; - } - - ret = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) - ret = (unsigned char *)(ka->sa.sa_restorer); - else { - /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ - err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), - (unsigned long *)(frame->retcode + 0)); - err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); - } - - /* Set up to return from userspace. */ - err |= __put_user(ret, &frame->pretcode); - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->er0 = (current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig); - regs->er1 = (unsigned long)&(frame->sc); - regs->er5 = current->mm->start_data; /* GOT base */ - - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; -} - -static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe *frame; - int err = 0; - int usig; - unsigned char *ret; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - usig = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(usig, &frame->sig); - if (err) - goto give_sigsegv; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - if (err) - goto give_sigsegv; - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); - err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. */ - ret = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) - ret = (unsigned char *)(ka->sa.sa_restorer); - else { - /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ - err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), - (unsigned long *)(frame->retcode + 0)); - err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); - } - err |= __put_user(ret, &frame->pretcode); - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->er0 = (current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig); - regs->er1 = (unsigned long)&(frame->info); - regs->er2 = (unsigned long)&frame->uc; - regs->er5 = current->mm->start_data; /* GOT base */ - - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; -} - -/* - * OK, we're invoking a handler - */ -static void -handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs * regs) -{ - sigset_t *oldset = sigmask_to_save(); - int ret; - /* are we from a system call? */ - if (regs->orig_er0 >= 0) { - switch (regs->er0) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - regs->er0 = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->er0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - regs->er0 = regs->orig_er0; - regs->pc -= 2; - } - } - - /* set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset, regs); - else - ret = setup_frame(sig, ka, oldset, regs); - - if (!ret) - signal_delivered(sig, info, ka, regs, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - */ -static void do_signal(struct pt_regs *regs) -{ - siginfo_t info; - int signr; - struct k_sigaction ka; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if ((regs->ccr & 0x10)) - return; - - current->thread.esp0 = (unsigned long) regs; - - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { - /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); - return; - } - /* Did we come from a system call? */ - if (regs->orig_er0 >= 0) { - /* Restart the system call - no handlers present */ - if (regs->er0 == -ERESTARTNOHAND || - regs->er0 == -ERESTARTSYS || - regs->er0 == -ERESTARTNOINTR) { - regs->er0 = regs->orig_er0; - regs->pc -= 2; - } - if (regs->er0 == -ERESTART_RESTARTBLOCK){ - regs->er0 = __NR_restart_syscall; - regs->pc -= 2; - } - } - - /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); -} - -asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) -{ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs); - - if (thread_info_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } -} diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c deleted file mode 100644 index bf350cb7f597..000000000000 --- a/arch/h8300/kernel/sys_h8300.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/h8300/kernel/sys_h8300.c - * - * This file contains various random system calls that - * have a non-standard calling sequence on the H8/300 - * platform. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* sys_cacheflush -- no support. */ -asmlinkage int -sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) -{ - return -EINVAL; -} - -asmlinkage int sys_getpagesize(void) -{ - return PAGE_SIZE; -} - -#if defined(CONFIG_SYSCALL_PRINT) -asmlinkage void syscall_print(void *dummy,...) -{ - struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); - printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n", - ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); -} -#endif diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S deleted file mode 100644 index c55e0ed270d5..000000000000 --- a/arch/h8300/kernel/syscalls.S +++ /dev/null @@ -1,338 +0,0 @@ -/* Systemcall Entry Table */ -#include -#include -#include - -#define CALL(x) .long _ ## x - -.globl _sys_call_table - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#endif - .section .text - .align 2 -_sys_call_table: - CALL(sys_ni_syscall) /* 0 - old "setup()" system call*/ - CALL(sys_exit) - CALL(sys_fork) - CALL(sys_read) - CALL(sys_write) - CALL(sys_open) /* 5 */ - CALL(sys_close) - CALL(sys_waitpid) - CALL(sys_creat) - CALL(sys_link) - CALL(sys_unlink) /* 10 */ - CALL(sys_execve) - CALL(sys_chdir) - CALL(sys_time) - CALL(sys_mknod) - CALL(sys_chmod) /* 15 */ - CALL(sys_chown16) - CALL(sys_ni_syscall) /* old break syscall holder */ - CALL(sys_stat) - CALL(sys_lseek) - CALL(sys_getpid) /* 20 */ - CALL(sys_mount) - CALL(sys_oldumount) - CALL(sys_setuid16) - CALL(sys_getuid16) - CALL(sys_stime) /* 25 */ - CALL(sys_ptrace) - CALL(sys_alarm) - CALL(sys_fstat) - CALL(sys_pause) - CALL(sys_utime) /* 30 */ - CALL(sys_ni_syscall) /* old stty syscall holder */ - CALL(sys_ni_syscall) /* old gtty syscall holder */ - CALL(sys_access) - CALL(sys_nice) - CALL(sys_ni_syscall) /* 35 old ftime syscall holder */ - CALL(sys_sync) - CALL(sys_kill) - CALL(sys_rename) - CALL(sys_mkdir) - CALL(sys_rmdir) /* 40 */ - CALL(sys_dup) - CALL(sys_pipe) - CALL(sys_times) - CALL(sys_ni_syscall) /* old prof syscall holder */ - CALL(sys_brk) /* 45 */ - CALL(sys_setgid16) - CALL(sys_getgid16) - CALL(sys_signal) - CALL(sys_geteuid16) - CALL(sys_getegid16) /* 50 */ - CALL(sys_acct) - CALL(sys_umount) /* recycled never used phys() */ - CALL(sys_ni_syscall) /* old lock syscall holder */ - CALL(sys_ioctl) - CALL(sys_fcntl) /* 55 */ - CALL(sys_ni_syscall) /* old mpx syscall holder */ - CALL(sys_setpgid) - CALL(sys_ni_syscall) /* old ulimit syscall holder */ - CALL(sys_ni_syscall) - CALL(sys_umask) /* 60 */ - CALL(sys_chroot) - CALL(sys_ustat) - CALL(sys_dup2) - CALL(sys_getppid) - CALL(sys_getpgrp) /* 65 */ - CALL(sys_setsid) - CALL(sys_sigaction) - CALL(sys_sgetmask) - CALL(sys_ssetmask) - CALL(sys_setreuid16) /* 70 */ - CALL(sys_setregid16) - CALL(sys_sigsuspend) - CALL(sys_sigpending) - CALL(sys_sethostname) - CALL(sys_setrlimit) /* 75 */ - CALL(sys_old_getrlimit) - CALL(sys_getrusage) - CALL(sys_gettimeofday) - CALL(sys_settimeofday) - CALL(sys_getgroups16) /* 80 */ - CALL(sys_setgroups16) - CALL(sys_old_select) - CALL(sys_symlink) - CALL(sys_lstat) - CALL(sys_readlink) /* 85 */ - CALL(sys_uselib) - CALL(sys_swapon) - CALL(sys_reboot) - CALL(sys_old_readdir) - CALL(sys_old_mmap) /* 90 */ - CALL(sys_munmap) - CALL(sys_truncate) - CALL(sys_ftruncate) - CALL(sys_fchmod) - CALL(sys_fchown16) /* 95 */ - CALL(sys_getpriority) - CALL(sys_setpriority) - CALL(sys_ni_syscall) /* old profil syscall holder */ - CALL(sys_statfs) - CALL(sys_fstatfs) /* 100 */ - CALL(sys_ni_syscall) /* ioperm for i386 */ - CALL(sys_socketcall) - CALL(sys_syslog) - CALL(sys_setitimer) - CALL(sys_getitimer) /* 105 */ - CALL(sys_newstat) - CALL(sys_newlstat) - CALL(sys_newfstat) - CALL(sys_ni_syscall) - CALL(sys_ni_syscall) /* iopl for i386 */ /* 110 */ - CALL(sys_vhangup) - CALL(sys_ni_syscall) /* obsolete idle() syscall */ - CALL(sys_ni_syscall) /* vm86old for i386 */ - CALL(sys_wait4) - CALL(sys_swapoff) /* 115 */ - CALL(sys_sysinfo) - CALL(sys_ipc) - CALL(sys_fsync) - CALL(sys_sigreturn) - CALL(sys_clone) /* 120 */ - CALL(sys_setdomainname) - CALL(sys_newuname) - CALL(sys_cacheflush) /* modify_ldt for i386 */ - CALL(sys_adjtimex) - CALL(sys_ni_syscall) /* 125 sys_mprotect */ - CALL(sys_sigprocmask) - CALL(sys_ni_syscall) /* sys_create_module */ - CALL(sys_init_module) - CALL(sys_delete_module) - CALL(sys_ni_syscall) /* 130 sys_get_kernel_syms */ - CALL(sys_quotactl) - CALL(sys_getpgid) - CALL(sys_fchdir) - CALL(sys_bdflush) - CALL(sys_sysfs) /* 135 */ - CALL(sys_personality) - CALL(sys_ni_syscall) /* for afs_syscall */ - CALL(sys_setfsuid16) - CALL(sys_setfsgid16) - CALL(sys_llseek) /* 140 */ - CALL(sys_getdents) - CALL(sys_select) - CALL(sys_flock) - CALL(sys_ni_syscall) /* sys_msync */ - CALL(sys_readv) /* 145 */ - CALL(sys_writev) - CALL(sys_getsid) - CALL(sys_fdatasync) - CALL(sys_sysctl) - CALL(sys_ni_syscall) /* 150 sys_mlock */ - CALL(sys_ni_syscall) /* sys_munlock */ - CALL(sys_ni_syscall) /* sys_mlockall */ - CALL(sys_ni_syscall) /* sys_munlockall */ - CALL(sys_sched_setparam) - CALL(sys_sched_getparam) /* 155 */ - CALL(sys_sched_setscheduler) - CALL(sys_sched_getscheduler) - CALL(sys_sched_yield) - CALL(sys_sched_get_priority_max) - CALL(sys_sched_get_priority_min) /* 160 */ - CALL(sys_sched_rr_get_interval) - CALL(sys_nanosleep) - CALL(sys_ni_syscall) /* sys_mremap */ - CALL(sys_setresuid16) - CALL(sys_getresuid16) /* 165 */ - CALL(sys_ni_syscall) /* for vm86 */ - CALL(sys_ni_syscall) /* sys_query_module */ - CALL(sys_poll) - CALL(sys_ni_syscall) /* old nfsservctl */ - CALL(sys_setresgid16) /* 170 */ - CALL(sys_getresgid16) - CALL(sys_prctl) - CALL(sys_rt_sigreturn) - CALL(sys_rt_sigaction) - CALL(sys_rt_sigprocmask) /* 175 */ - CALL(sys_rt_sigpending) - CALL(sys_rt_sigtimedwait) - CALL(sys_rt_sigqueueinfo) - CALL(sys_rt_sigsuspend) - CALL(sys_pread64) /* 180 */ - CALL(sys_pwrite64) - CALL(sys_lchown16); - CALL(sys_getcwd) - CALL(sys_capget) - CALL(sys_capset) /* 185 */ - CALL(sys_sigaltstack) - CALL(sys_sendfile) - CALL(sys_ni_syscall) /* streams1 */ - CALL(sys_ni_syscall) /* streams2 */ - CALL(sys_vfork) /* 190 */ - CALL(sys_getrlimit) - CALL(sys_mmap_pgoff) - CALL(sys_truncate64) - CALL(sys_ftruncate64) - CALL(sys_stat64) /* 195 */ - CALL(sys_lstat64) - CALL(sys_fstat64) - CALL(sys_chown) - CALL(sys_getuid) - CALL(sys_getgid) /* 200 */ - CALL(sys_geteuid) - CALL(sys_getegid) - CALL(sys_setreuid) - CALL(sys_setregid) - CALL(sys_getgroups) /* 205 */ - CALL(sys_setgroups) - CALL(sys_fchown) - CALL(sys_setresuid) - CALL(sys_getresuid) - CALL(sys_setresgid) /* 210 */ - CALL(sys_getresgid) - CALL(sys_lchown) - CALL(sys_setuid) - CALL(sys_setgid) - CALL(sys_setfsuid) /* 215 */ - CALL(sys_setfsgid) - CALL(sys_pivot_root) - CALL(sys_ni_syscall) - CALL(sys_ni_syscall) - CALL(sys_getdents64) /* 220 */ - CALL(sys_fcntl64) - CALL(sys_ni_syscall) /* reserved TUX */ - CALL(sys_ni_syscall) /* reserved Security */ - CALL(sys_gettid) - CALL(sys_readahead) /* 225 */ - CALL(sys_setxattr) - CALL(sys_lsetxattr) - CALL(sys_fsetxattr) - CALL(sys_getxattr) - CALL(sys_lgetxattr) /* 230 */ - CALL(sys_fgetxattr) - CALL(sys_listxattr) - CALL(sys_llistxattr) - CALL(sys_flistxattr) - CALL(sys_removexattr) /* 235 */ - CALL(sys_lremovexattr) - CALL(sys_fremovexattr) - CALL(sys_tkill) - CALL(sys_sendfile64) - CALL(sys_futex) /* 240 */ - CALL(sys_sched_setaffinity) - CALL(sys_sched_getaffinity) - CALL(sys_ni_syscall) - CALL(sys_ni_syscall) - CALL(sys_io_setup) /* 245 */ - CALL(sys_io_destroy) - CALL(sys_io_getevents) - CALL(sys_io_submit) - CALL(sys_io_cancel) - CALL(sys_fadvise64) /* 250 */ - CALL(sys_ni_syscall) - CALL(sys_exit_group) - CALL(sys_lookup_dcookie) - CALL(sys_epoll_create) - CALL(sys_epoll_ctl) /* 255 */ - CALL(sys_epoll_wait) - CALL(sys_ni_syscall) /* sys_remap_file_pages */ - CALL(sys_set_tid_address) - CALL(sys_timer_create) - CALL(sys_timer_settime) /* 260 */ - CALL(sys_timer_gettime) - CALL(sys_timer_getoverrun) - CALL(sys_timer_delete) - CALL(sys_clock_settime) - CALL(sys_clock_gettime) /* 265 */ - CALL(sys_clock_getres) - CALL(sys_clock_nanosleep) - CALL(sys_statfs64) - CALL(sys_fstatfs64) - CALL(sys_tgkill) /* 270 */ - CALL(sys_utimes) - CALL(sys_fadvise64_64) - CALL(sys_ni_syscall) /* sys_vserver */ - CALL(sys_ni_syscall) - CALL(sys_get_mempolicy) /* 275 */ - CALL(sys_set_mempolicy) - CALL(sys_mq_open) - CALL(sys_mq_unlink) - CALL(sys_mq_timedsend) - CALL(sys_mq_timedreceive) /* 280 */ - CALL(sys_mq_notify) - CALL(sys_mq_getsetattr) - CALL(sys_waitid) - CALL(sys_ni_syscall) /* sys_kexec_load */ - CALL(sys_add_key) /* 285 */ - CALL(sys_request_key) - CALL(sys_keyctl) - CALL(sys_ioprio_set) - CALL(sys_ioprio_get) /* 290 */ - CALL(sys_inotify_init) - CALL(sys_inotify_add_watch) - CALL(sys_inotify_rm_watch) - CALL(sys_migrate_pages) - CALL(sys_openat) /* 295 */ - CALL(sys_mkdirat) - CALL(sys_mknodat) - CALL(sys_fchownat) - CALL(sys_futimesat) - CALL(sys_fstatat64) /* 300 */ - CALL(sys_unlinkat) - CALL(sys_renameat) - CALL(sys_linkat) - CALL(sys_symlinkat) - CALL(sys_readlinkat) /* 305 */ - CALL(sys_fchmodat) - CALL(sys_faccessat) - CALL(sys_ni_syscall) /* sys_pselect6 */ - CALL(sys_ni_syscall) /* sys_ppoll */ - CALL(sys_unshare) /* 310 */ - CALL(sys_set_robust_list) - CALL(sys_get_robust_list) - CALL(sys_splice) - CALL(sys_sync_file_range) - CALL(sys_tee) /* 315 */ - CALL(sys_vmsplice) - CALL(sys_ni_syscall) /* sys_move_pages */ - CALL(sys_getcpu) - CALL(sys_ni_syscall) /* sys_epoll_pwait */ - CALL(sys_setns) /* 320 */ diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c deleted file mode 100644 index e0f74191d553..000000000000 --- a/arch/h8300/kernel/time.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * linux/arch/h8300/kernel/time.c - * - * Yoshinori Sato - * - * Copied/hacked from: - * - * linux/arch/m68k/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * - * This file contains the m68k-specific time handling details. - * Most of the stuff is located in the machine specific files. - * - * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 - * "A Kernel Model for Precision Timekeeping" by Dave Mills - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define TICK_SIZE (tick_nsec / 1000) - -void h8300_timer_tick(void) -{ - if (current->pid) - profile_tick(CPU_PROFILING); - xtime_update(1); - update_process_times(user_mode(get_irq_regs())); -} - -void read_persistent_clock(struct timespec *ts) -{ - unsigned int year, mon, day, hour, min, sec; - - /* FIX by dqg : Set to zero for platforms that don't have tod */ - /* without this time is undefined and can overflow time_t, causing */ - /* very strange errors */ - year = 1980; - mon = day = 1; - hour = min = sec = 0; -#ifdef CONFIG_H8300_GETTOD - h8300_gettod (&year, &mon, &day, &hour, &min, &sec); -#endif - if ((year += 1900) < 1970) - year += 100; - ts->tv_sec = mktime(year, mon, day, hour, min, sec); - ts->tv_nsec = 0; -} - -void __init time_init(void) -{ - - h8300_timer_setup(); -} diff --git a/arch/h8300/kernel/timer/Makefile b/arch/h8300/kernel/timer/Makefile deleted file mode 100644 index bef0510ea6ad..000000000000 --- a/arch/h8300/kernel/timer/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# h8300 internal timer handler - -obj-$(CONFIG_H8300_TIMER8) := timer8.o -obj-$(CONFIG_H8300_TIMER16) := timer16.o -obj-$(CONFIG_H8300_ITU) := itu.o -obj-$(CONFIG_H8300_TPU) := tpu.o diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c deleted file mode 100644 index 0a8b5cd5bf38..000000000000 --- a/arch/h8300/kernel/timer/itu.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * linux/arch/h8300/kernel/timer/itu.c - * - * Yoshinori Sato - * - * ITU Timer Handler - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if CONFIG_H8300_ITU_CH == 0 -#define ITUBASE 0xffff64 -#define ITUIRQ 24 -#elif CONFIG_H8300_ITU_CH == 1 -#define ITUBASE 0xffff6e -#define ITUIRQ 28 -#elif CONFIG_H8300_ITU_CH == 2 -#define ITUBASE 0xffff78 -#define ITUIRQ 32 -#elif CONFIG_H8300_ITU_CH == 3 -#define ITUBASE 0xffff82 -#define ITUIRQ 36 -#elif CONFIG_H8300_ITU_CH == 4 -#define ITUBASE 0xffff92 -#define ITUIRQ 40 -#else -#error Unknown timer channel. -#endif - -#define TCR 0 -#define TIOR 1 -#define TIER 2 -#define TSR 3 -#define TCNT 4 -#define GRA 6 -#define GRB 8 - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - h8300_timer_tick(); - ctrl_bclr(IMFA, ITUBASE + TSR); - return IRQ_HANDLED; -} - -static struct irqaction itu_irq = { - .name = "itu", - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, -}; - -static const int __initconst divide_rate[] = {1, 2, 4, 8}; - -void __init h8300_timer_setup(void) -{ - unsigned int div; - unsigned int cnt; - - calc_param(cnt, div, divide_rate, 0x10000); - - setup_irq(ITUIRQ, &itu_irq); - - /* initialize timer */ - ctrl_outb(0, TSTR); - ctrl_outb(CCLR0 | div, ITUBASE + TCR); - ctrl_outb(0x01, ITUBASE + TIER); - ctrl_outw(cnt, ITUBASE + GRA); - ctrl_bset(CONFIG_H8300_ITU_CH, TSTR); -} diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c deleted file mode 100644 index 462d9f581719..000000000000 --- a/arch/h8300/kernel/timer/timer16.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * linux/arch/h8300/kernel/timer/timer16.c - * - * Yoshinori Sato - * - * 16bit Timer Handler - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* 16bit timer */ -#if CONFIG_H8300_TIMER16_CH == 0 -#define _16BASE 0xffff78 -#define _16IRQ 24 -#elif CONFIG_H8300_TIMER16_CH == 1 -#define _16BASE 0xffff80 -#define _16IRQ 28 -#elif CONFIG_H8300_TIMER16_CH == 2 -#define _16BASE 0xffff88 -#define _16IRQ 32 -#else -#error Unknown timer channel. -#endif - -#define TCR 0 -#define TIOR 1 -#define TCNT 2 -#define GRA 4 -#define GRB 6 - -#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*10000 /* Timer input freq. */ - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - h8300_timer_tick(); - ctrl_bclr(CONFIG_H8300_TIMER16_CH, TISRA); - return IRQ_HANDLED; -} - -static struct irqaction timer16_irq = { - .name = "timer-16", - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, -}; - -static const int __initconst divide_rate[] = {1, 2, 4, 8}; - -void __init h8300_timer_setup(void) -{ - unsigned int div; - unsigned int cnt; - - calc_param(cnt, div, divide_rate, 0x10000); - - setup_irq(_16IRQ, &timer16_irq); - - /* initialize timer */ - ctrl_outb(0, TSTR); - ctrl_outb(CCLR0 | div, _16BASE + TCR); - ctrl_outw(cnt, _16BASE + GRA); - ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA); - ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR); -} diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c deleted file mode 100644 index 505f3415b40f..000000000000 --- a/arch/h8300/kernel/timer/timer8.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * linux/arch/h8300/kernel/cpu/timer/timer8.c - * - * Yoshinori Sato - * - * 8bit Timer Handler - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#if defined(CONFIG_CPU_H8300H) -#include -#endif -#if defined(CONFIG_CPU_H8S) -#include -#endif - -/* 8bit timer x2 */ -#define CMFA 6 - -#if defined(CONFIG_H8300_TIMER8_CH0) -#define _8BASE _8TCR0 -#ifdef CONFIG_CPU_H8300H -#define _8IRQ 36 -#endif -#ifdef CONFIG_CPU_H8S -#define _8IRQ 72 -#endif -#elif defined(CONFIG_H8300_TIMER8_CH2) -#ifdef CONFIG_CPU_H8300H -#define _8BASE _8TCR2 -#define _8IRQ 40 -#endif -#endif - -#ifndef _8BASE -#error Unknown timer channel. -#endif - -#define _8TCR 0 -#define _8TCSR 2 -#define TCORA 4 -#define TCORB 6 -#define _8TCNT 8 - -#define CMIEA 0x40 -#define CCLR_CMA 0x08 -#define CKS2 0x04 - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - h8300_timer_tick(); - ctrl_bclr(CMFA, _8BASE + _8TCSR); - return IRQ_HANDLED; -} - -static struct irqaction timer8_irq = { - .name = "timer-8", - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, -}; - -static const int __initconst divide_rate[] = {8, 64, 8192}; - -void __init h8300_timer_setup(void) -{ - unsigned int div; - unsigned int cnt; - - calc_param(cnt, div, divide_rate, 0x10000); - div++; - - setup_irq(_8IRQ, &timer8_irq); - -#if defined(CONFIG_CPU_H8S) - /* Timer module enable */ - ctrl_bclr(0, MSTPCRL) -#endif - - /* initialize timer */ - ctrl_outw(cnt, _8BASE + TCORA); - ctrl_outw(0x0000, _8BASE + _8TCSR); - ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div, - _8BASE + _8TCR); -} diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c deleted file mode 100644 index 0350f6204ecf..000000000000 --- a/arch/h8300/kernel/timer/tpu.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * linux/arch/h8300/kernel/timer/tpu.c - * - * Yoshinori Sato - * - * TPU Timer Handler - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* TPU */ -#if CONFIG_H8300_TPU_CH == 0 -#define TPUBASE 0xffffd0 -#define TPUIRQ 40 -#elif CONFIG_H8300_TPU_CH == 1 -#define TPUBASE 0xffffe0 -#define TPUIRQ 48 -#elif CONFIG_H8300_TPU_CH == 2 -#define TPUBASE 0xfffff0 -#define TPUIRQ 52 -#elif CONFIG_H8300_TPU_CH == 3 -#define TPUBASE 0xfffe80 -#define TPUIRQ 56 -#elif CONFIG_H8300_TPU_CH == 4 -#define TPUBASE 0xfffe90 -#define TPUIRQ 64 -#else -#error Unknown timer channel. -#endif - -#define _TCR 0 -#define _TMDR 1 -#define _TIOR 2 -#define _TIER 4 -#define _TSR 5 -#define _TCNT 6 -#define _GRA 8 -#define _GRB 10 - -#define CCLR0 0x20 - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - h8300_timer_tick(); - ctrl_bclr(0, TPUBASE + _TSR); - return IRQ_HANDLED; -} - -static struct irqaction tpu_irq = { - .name = "tpu", - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, -}; - -static const int __initconst divide_rate[] = { -#if CONFIG_H8300_TPU_CH == 0 - 1,4,16,64,0,0,0,0, -#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5) - 1,4,16,64,0,0,256,0, -#elif (CONFIG_H8300_TPU_CH == 2) || (CONFIG_H8300_TPU_CH == 4) - 1,4,16,64,0,0,0,1024, -#elif CONFIG_H8300_TPU_CH == 3 - 1,4,16,64,0,1024,256,4096, -#endif -}; - -void __init h8300_timer_setup(void) -{ - unsigned int cnt; - unsigned int div; - - calc_param(cnt, div, divide_rate, 0x10000); - - setup_irq(TPUIRQ, &tpu_irq); - - /* TPU module enabled */ - ctrl_bclr(3, MSTPCRH); - - ctrl_outb(0, TSTR); - ctrl_outb(CCLR0 | div, TPUBASE + _TCR); - ctrl_outb(0, TPUBASE + _TMDR); - ctrl_outw(0, TPUBASE + _TIOR); - ctrl_outb(0x01, TPUBASE + _TIER); - ctrl_outw(cnt, TPUBASE + _GRA); - ctrl_bset(CONFIG_H8300_TPU_CH, TSTR); -} diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c deleted file mode 100644 index cfe494dbe3da..000000000000 --- a/arch/h8300/kernel/traps.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * linux/arch/h8300/boot/traps.c -- general exception handling code - * H8/300 support Yoshinori Sato - * - * Cloned from Linux/m68k. - * - * No original Copyright holder listed, - * Probable original (C) Roman Zippel (assigned DJD, 1999) - * - * Copyright 1999-2000 D. Jeff Dionne, - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static DEFINE_SPINLOCK(die_lock); - -/* - * this must be called very early as the kernel might - * use some instruction that are emulated on the 060 - */ - -void __init base_trap_init(void) -{ -} - -void __init trap_init (void) -{ -} - -asmlinkage void set_esp0 (unsigned long ssp) -{ - current->thread.esp0 = ssp; -} - -/* - * Generic dumping code. Used for panic and debug. - */ - -static void dump(struct pt_regs *fp) -{ - unsigned long *sp; - unsigned char *tp; - int i; - - printk("\nCURRENT PROCESS:\n\n"); - printk("COMM=%s PID=%d\n", current->comm, current->pid); - if (current->mm) { - printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", - (int) current->mm->start_code, - (int) current->mm->end_code, - (int) current->mm->start_data, - (int) current->mm->end_data, - (int) current->mm->end_data, - (int) current->mm->brk); - printk("USER-STACK=%08x KERNEL-STACK=%08lx\n\n", - (int) current->mm->start_stack, - (int) PAGE_SIZE+(unsigned long)current); - } - - show_regs(fp); - printk("\nCODE:"); - tp = ((unsigned char *) fp->pc) - 0x20; - for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { - if ((i % 0x10) == 0) - printk("\n%08x: ", (int) (tp + i)); - printk("%08x ", (int) *sp++); - } - printk("\n"); - - printk("\nKERNEL STACK:"); - tp = ((unsigned char *) fp) - 0x40; - for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { - if ((i % 0x10) == 0) - printk("\n%08x: ", (int) (tp + i)); - printk("%08x ", (int) *sp++); - } - printk("\n"); - if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE)) - printk("(Possibly corrupted stack page??)\n"); - - printk("\n\n"); -} - -void die(const char *str, struct pt_regs *fp, unsigned long err) -{ - static int diecount; - - oops_enter(); - - console_verbose(); - spin_lock_irq(&die_lock); - report_bug(fp->pc, fp); - printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++diecount); - dump(fp); - - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); -} - -extern char _start, _etext; -#define check_kernel_text(addr) \ - ((addr >= (unsigned long)(&_start)) && \ - (addr < (unsigned long)(&_etext))) - -static int kstack_depth_to_print = 24; - -void show_stack(struct task_struct *task, unsigned long *esp) -{ - unsigned long *stack, addr; - int i; - - if (esp == NULL) - esp = (unsigned long *) &esp; - - stack = esp; - - printk("Stack from %08lx:", (unsigned long)stack); - for (i = 0; i < kstack_depth_to_print; i++) { - if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) - break; - if (i % 8 == 0) - printk("\n "); - printk(" %08lx", *stack++); - } - - printk("\nCall Trace:"); - i = 0; - stack = esp; - while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) { - addr = *stack++; - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ - if (check_kernel_text(addr)) { - if (i % 4 == 0) - printk("\n "); - printk(" [<%08lx>]", addr); - i++; - } - } - printk("\n"); -} - -void show_trace_task(struct task_struct *tsk) -{ - show_stack(tsk,(unsigned long *)tsk->thread.esp0); -} diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S deleted file mode 100644 index 3253fed42ac1..000000000000 --- a/arch/h8300/kernel/vmlinux.lds.S +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include - -/* target memory map */ -#ifdef CONFIG_H8300H_GENERIC -#define ROMTOP 0x000000 -#define ROMSIZE 0x400000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x400000 -#endif - -#ifdef CONFIG_H8300H_AKI3068NET -#define ROMTOP 0x000000 -#define ROMSIZE 0x080000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x200000 -#endif - -#ifdef CONFIG_H8300H_H8MAX -#define ROMTOP 0x000000 -#define ROMSIZE 0x080000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x200000 -#endif - -#ifdef CONFIG_H8300H_SIM -#define ROMTOP 0x000000 -#define ROMSIZE 0x400000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x400000 -#endif - -#ifdef CONFIG_H8S_SIM -#define ROMTOP 0x000000 -#define ROMSIZE 0x400000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x800000 -#endif - -#ifdef CONFIG_H8S_EDOSK2674 -#define ROMTOP 0x000000 -#define ROMSIZE 0x400000 -#define RAMTOP 0x400000 -#define RAMSIZE 0x800000 -#endif - -#if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM) -INPUT(romfs.o) -#endif - -_jiffies = _jiffies_64 + 4; - -ENTRY(__start) - -SECTIONS -{ -#if defined(CONFIG_ROMKERNEL) - . = ROMTOP; - .vectors : - { - __vector = . ; - *(.vectors*) - } -#else - . = RAMTOP; - .bootvec : - { - *(.bootvec) - } -#endif - .text : - { - _text = .; -#if defined(CONFIG_ROMKERNEL) - *(.int_redirect) -#endif - __stext = . ; - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - __etext = . ; - } - EXCEPTION_TABLE(16) - - RODATA -#if defined(CONFIG_ROMKERNEL) - SECURITY_INIT -#endif - ROEND = .; -#if defined(CONFIG_ROMKERNEL) - . = RAMTOP; - .data : AT(ROEND) -#else - .data : -#endif - { - __sdata = . ; - ___data_start = . ; - - INIT_TASK_DATA(0x2000) - . = ALIGN(0x4) ; - DATA_DATA - . = ALIGN(0x4) ; - *(.data.*) - - . = ALIGN(0x4) ; - ___init_begin = .; - __sinittext = .; - INIT_TEXT - __einittext = .; - INIT_DATA - . = ALIGN(0x4) ; - INIT_SETUP(0x4) - ___setup_start = .; - *(.init.setup) - . = ALIGN(0x4) ; - ___setup_end = .; - INIT_CALLS - CON_INITCALL - EXIT_TEXT - EXIT_DATA - INIT_RAM_FS - . = ALIGN(0x4) ; - ___init_end = .; - __edata = . ; - } -#if defined(CONFIG_RAMKERNEL) - SECURITY_INIT -#endif - __begin_data = LOADADDR(.data); - .bss : - { - . = ALIGN(0x4) ; - __sbss = . ; - ___bss_start = . ; - *(.bss*) - . = ALIGN(0x4) ; - *(COMMON) - . = ALIGN(0x4) ; - ___bss_stop = . ; - __ebss = . ; - __end = . ; - __ramstart = .; - } - .romfs : - { - *(.romfs*) - } - . = RAMTOP+RAMSIZE; - .dummy : - { - COMMAND_START = . - 0x200 ; - __ramend = . ; - } - - DISCARDS -} diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile deleted file mode 100644 index 1577f5075b10..000000000000 --- a/arch/h8300/lib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for H8/300-specific library files.. -# - -lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S deleted file mode 100644 index ddd1fb3d01ad..000000000000 --- a/arch/h8300/lib/abs.S +++ /dev/null @@ -1,21 +0,0 @@ -;;; abs.S - -#include - -#if defined(__H8300H__) - .h8300h -#endif -#if defined(__H8300S__) - .h8300s -#endif - .text -.global _abs - -;;; int abs(int n) -_abs: - mov.l er0,er0 - bpl 1f - neg.l er0 -1: - rts - diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c deleted file mode 100644 index 78efb65e315a..000000000000 --- a/arch/h8300/lib/ashrdi3.c +++ /dev/null @@ -1,63 +0,0 @@ -/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ -/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__ashrdi3 (DItype u, word_type b) -{ - DIunion w; - word_type bm; - DIunion uu; - - if (b == 0) - return u; - - uu.ll = u; - - bm = (sizeof (SItype) * BITS_PER_UNIT) - b; - if (bm <= 0) - { - /* w.s.high = 1..1 or 0..0 */ - w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); - w.s.low = uu.s.high >> -bm; - } - else - { - USItype carries = (USItype)uu.s.high << bm; - w.s.high = uu.s.high >> b; - w.s.low = ((USItype)uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c deleted file mode 100644 index bdc5b032acd6..000000000000 --- a/arch/h8300/lib/checksum.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, - * Arnt Gulbrandsen, - * Tom May, - * Andreas Schwab, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: - * Fixed some nasty bugs, causing some horrible crashes. - * A: At some points, the sum (%0) was used as - * length-counter instead of the length counter - * (%1). Thanks to Roman Hodek for pointing this out. - * B: GCC seems to mess up if one uses too many - * data-registers to hold input values and one tries to - * specify d0 and d1 as scratch registers. Letting gcc choose these - * registers itself solves the problem. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most - of the assembly has to go. */ - -#include -#include - -static inline unsigned short from32to16(unsigned long x) -{ - /* add up 16-bit and 16-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static unsigned long do_csum(const unsigned char * buff, int len) -{ - int odd, count; - unsigned long result = 0; - - if (len <= 0) - goto out; - odd = 1 & (unsigned long) buff; - if (odd) { - result = *buff; - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - count--; - buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffff) + (result >> 16); - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += (*buff << 8); - result = from32to16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); -out: - return result; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -__sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - return (__force __sum16)~do_csum(iph,ihl*4); -} - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -/* - * Egads... That thing apparently assumes that *all* checksums it ever sees will - * be folded. Very likely a bug. - */ -__wsum csum_partial(const void *buff, int len, __wsum sum) -{ - unsigned int result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += (__force u32)sum; - /* 16+c bits -> 16 bits */ - result = (result & 0xffff) + (result >> 16); - return (__force __wsum)result; -} - -EXPORT_SYMBOL(csum_partial); - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -__sum16 ip_compute_csum(const void *buff, int len) -{ - return (__force __sum16)~do_csum(buff,len); -} - -/* - * copy from fs while checksumming, otherwise like csum_partial - */ - -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *csum_err) -{ - if (csum_err) *csum_err = 0; - memcpy(dst, (__force const void *)src, len); - return csum_partial(dst, len, sum); -} - -/* - * copy from ds while checksumming, otherwise like csum_partial - */ - -__wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) -{ - memcpy(dst, src, len); - return csum_partial(dst, len, sum); -} diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S deleted file mode 100644 index cad325e2c0e8..000000000000 --- a/arch/h8300/lib/memcpy.S +++ /dev/null @@ -1,84 +0,0 @@ -;;; memcpy.S - -#include - -#if defined(__H8300H__) - .h8300h -#endif -#if defined(__H8300S__) - .h8300s -#endif - - .text -.global _memcpy - -;;; void *memcpy(void *to, void *from, size_t n) -_memcpy: - mov.l er2,er2 - bne 1f - rts -1: - ;; address check - bld #0,r0l - bxor #0,r1l - bcs 4f - mov.l er4,@-sp - mov.l er0,@-sp - btst #0,r0l - beq 1f - ;; (aligned even) odd address - mov.b @er1,r3l - mov.b r3l,@er0 - adds #1,er1 - adds #1,er0 - dec.l #1,er2 - beq 3f -1: - ;; n < sizeof(unsigned long) check - sub.l er4,er4 - adds #4,er4 ; loop count check value - cmp.l er4,er2 - blo 2f - ;; unsigned long copy -1: - mov.l @er1,er3 - mov.l er3,@er0 - adds #4,er0 - adds #4,er1 - subs #4,er2 - cmp.l er4,er2 - bcc 1b - ;; rest -2: - mov.l er2,er2 - beq 3f -1: - mov.b @er1,r3l - mov.b r3l,@er0 - adds #1,er1 - adds #1,er0 - dec.l #1,er2 - bne 1b -3: - mov.l @sp+,er0 - mov.l @sp+,er4 - rts - - ;; odd <- even / even <- odd -4: - mov.l er4,er3 - mov.l er2,er4 - mov.l er5,er2 - mov.l er1,er5 - mov.l er6,er1 - mov.l er0,er6 -1: - eepmov.w - mov.w r4,r4 - bne 1b - dec.w #1,e4 - bpl 1b - mov.l er1,er6 - mov.l er2,er5 - mov.l er3,er4 - rts diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S deleted file mode 100644 index 4549a64c5b79..000000000000 --- a/arch/h8300/lib/memset.S +++ /dev/null @@ -1,61 +0,0 @@ -/* memset.S */ - -#include - -#if defined(__H8300H__) - .h8300h -#endif -#if defined(__H8300S__) - .h8300s -#endif - .text - -.global _memset - -;;void *memset(*ptr, int c, size_t count) -;; ptr = er0 -;; c = er1(r1l) -;; count = er2 -_memset: - btst #0,r0l - beq 2f - - ;; odd address -1: - mov.b r1l,@er0 - adds #1,er0 - dec.l #1,er2 - beq 6f - - ;; even address -2: - mov.l er2,er3 - cmp.l #4,er2 - blo 4f - ;; count>=4 -> count/4 -#if defined(__H8300H__) - shlr.l er2 - shlr.l er2 -#endif -#if defined(__H8300S__) - shlr.l #2,er2 -#endif - ;; byte -> long - mov.b r1l,r1h - mov.w r1,e1 -3: - mov.l er1,@er0 - adds #4,er0 - dec.l #1,er2 - bne 3b -4: - ;; count % 4 - and.b #3,r3l - beq 6f -5: - mov.b r1l,@er0 - adds #1,er0 - dec.b r3l - bne 5b -6: - rts diff --git a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S deleted file mode 100644 index 68910d8e1ff4..000000000000 --- a/arch/h8300/lib/romfs.S +++ /dev/null @@ -1,57 +0,0 @@ -/* romfs move to __ebss */ - -#include - -#if defined(__H8300H__) - .h8300h -#endif -#if defined(__H8300S__) - .h8300s -#endif - -#define BLKOFFSET 512 - - .text -.globl __move_romfs -_romfs_sig_len = 8 - -__move_romfs: - mov.l #__sbss,er0 - mov.l #_romfs_sig,er1 - mov.b #_romfs_sig_len,r3l -1: /* check romfs image */ - mov.b @er0+,r2l - mov.b @er1+,r2h - cmp.b r2l,r2h - bne 2f - dec.b r3l - bne 1b - - /* find romfs image */ - mov.l @__sbss+8,er0 /* romfs length(be) */ - mov.l #__sbss,er1 - add.l er0,er1 /* romfs image end */ - mov.l #__ebss,er2 - add.l er0,er2 /* distination address */ -#if defined(CONFIG_INTELFLASH) - add.l #BLKOFFSET,er2 -#endif - adds #2,er0 - adds #1,er0 - shlr er0 - shlr er0 /* transfer length */ -1: - mov.l @er1,er3 /* copy image */ - mov.l er3,@er2 - subs #4,er1 - subs #4,er2 - dec.l #1,er0 - bpl 1b -2: - rts - - .section .rodata -_romfs_sig: - .ascii "-rom1fs-" - - .end diff --git a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile deleted file mode 100644 index 5f4bc42b6453..000000000000 --- a/arch/h8300/mm/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux m68k-specific parts of the memory manager. -# - -obj-y := init.o fault.o memory.o kmap.o diff --git a/arch/h8300/mm/fault.c b/arch/h8300/mm/fault.c deleted file mode 100644 index 472535977006..000000000000 --- a/arch/h8300/mm/fault.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * linux/arch/h8300/mm/fault.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) - * - * Based on: - * - * linux/arch/m68knommu/mm/fault.c - * linux/arch/m68k/mm/fault.c - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#include -#include -#include -#include - -#include - -/* - * This routine handles page faults. It determines the problem, and - * then passes it off to one of the appropriate routines. - * - * error_code: - * bit 0 == 0 means no page found, 1 means protection fault - * bit 1 == 0 means read, 1 means write - * - * If this routine detects a bad access, it returns 1, otherwise it - * returns 0. - */ -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code) -{ -#ifdef DEBUG - printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n", - regs->sr, regs->pc, address, error_code); -#endif - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - if ((unsigned long) address < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); - } else - printk(KERN_ALERT "Unable to handle kernel access"); - printk(" at virtual address %08lx\n",address); - if (!user_mode(regs)) - die("Oops", regs, error_code); - do_exit(SIGKILL); - - return 1; -} - diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c deleted file mode 100644 index 6c1251e491af..000000000000 --- a/arch/h8300/mm/init.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * linux/arch/h8300/mm/init.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Kenneth Albanowski , - * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) - * - * Based on: - * - * linux/arch/m68knommu/mm/init.c - * linux/arch/m68k/mm/init.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com) - * DEC/2000 -- linux 2.4 support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#undef DEBUG - -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving a inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -static unsigned long empty_bad_page_table; - -static unsigned long empty_bad_page; - -unsigned long empty_zero_page; - -extern unsigned long rom_length; - -extern unsigned long memory_start; -extern unsigned long memory_end; - -/* - * paging_init() continues the virtual memory environment setup which - * was begun by the code in arch/head.S. - * The parameters are pointers to where to stick the starting and ending - * addresses of available kernel virtual memory. - */ -void __init paging_init(void) -{ - /* - * Make sure start_mem is page aligned, otherwise bootmem and - * page_alloc get different views og the world. - */ -#ifdef DEBUG - unsigned long start_mem = PAGE_ALIGN(memory_start); -#endif - unsigned long end_mem = memory_end & PAGE_MASK; - -#ifdef DEBUG - printk ("start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); -#endif - - /* - * Initialize the bad page table and bad page to point - * to a couple of allocated pages. - */ - empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); - - /* - * Set up SFC/DFC registers (user data space). - */ - set_fs (USER_DS); - -#ifdef DEBUG - printk ("before free_area_init\n"); - - printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); -#endif - - { - unsigned long zones_size[MAX_NR_ZONES] = {0, }; - - zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT; - zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; -#ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = 0; -#endif - free_area_init(zones_size); - } -} - -void __init mem_init(void) -{ - unsigned long codesize = _etext - _stext; - - pr_devel("Mem_init: start=%lx, end=%lx\n", memory_start, memory_end); - - high_memory = (void *) (memory_end & PAGE_MASK); - max_mapnr = MAP_NR(high_memory); - - /* this will put all low memory onto the freelists */ - free_all_bootmem(); - - mem_init_print_info(NULL); - if (rom_length > 0 && rom_length > codesize) - pr_info("Memory available: %luK/%luK ROM\n", - (rom_length - codesize) >> 10, rom_length >> 10); -} - - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - free_reserved_area((void *)start, (void *)end, -1, "initrd"); -} -#endif - -void -free_initmem(void) -{ -#ifdef CONFIG_RAMKERNEL - free_initmem_default(-1); -#endif -} - diff --git a/arch/h8300/mm/kmap.c b/arch/h8300/mm/kmap.c deleted file mode 100644 index f79edcdadf39..000000000000 --- a/arch/h8300/mm/kmap.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * linux/arch/h8300/mm/kmap.c - * - * Based on - * linux/arch/m68knommu/mm/kmap.c - * - * Copyright (C) 2000 Lineo, - * Copyright (C) 2000-2002 David McCullough - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#undef DEBUG - -#define VIRT_OFFSET (0x01000000) - -/* - * Map some physical address range into the kernel address space. - */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) -{ - return (void *)(physaddr + VIRT_OFFSET); -} - -/* - * Unmap a ioremap()ed region again. - */ -void iounmap(void *addr) -{ -} - -/* - * __iounmap unmaps nearly everything, so be careful - * it doesn't free currently pointer/page tables anymore but it - * wans't used anyway and might be added later. - */ -void __iounmap(void *addr, unsigned long size) -{ -} - -/* - * Set new cache mode for some kernel address space. - * The caller must push data for that range itself, if such data may already - * be in the cache. - */ -void kernel_set_cachemode(void *addr, unsigned long size, int cmode) -{ -} diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c deleted file mode 100644 index 06e364641392..000000000000 --- a/arch/h8300/mm/memory.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * linux/arch/h8300/mm/memory.c - * - * Copyright (C) 2002 Yoshinori Sato , - * - * Based on: - * - * linux/arch/m68knommu/mm/memory.c - * - * Copyright (C) 1998 Kenneth Albanowski , - * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) - * - * Based on: - * - * linux/arch/m68k/mm/memory.c - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -void cache_clear (unsigned long paddr, int len) -{ -} - - -void cache_push (unsigned long paddr, int len) -{ -} - -void cache_push_v (unsigned long vaddr, int len) -{ -} - -/* - * Map some physical address range into the kernel address space. - */ - -unsigned long kernel_map(unsigned long paddr, unsigned long size, - int nocacheflag, unsigned long *memavailp ) -{ - return paddr; -} - diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile deleted file mode 100644 index 420f73b0d962..000000000000 --- a/arch/h8300/platform/h8300h/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the linux kernel. -# -# Reuse any files we can from the H8/300H -# - -obj-y := irq.o ptrace_h8300h.o diff --git a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile deleted file mode 100644 index b7ff78050b7f..000000000000 --- a/arch/h8300/platform/h8300h/aki3068net/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := crt0_ram.o diff --git a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S deleted file mode 100644 index b2ad0f2d0417..000000000000 --- a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S +++ /dev/null @@ -1,110 +0,0 @@ -/* - * linux/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: AE-3068 (aka. aki3068net) - * Memory Layout : RAM - */ - -#define ASSEMBLY - -#include - -#if !defined(CONFIG_BLKDEV_RESERVE) -#if defined(CONFIG_GDB_DEBUG) -#define RAMEND (__ramend - 0xc000) -#else -#define RAMEND __ramend -#endif -#else -#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS -#endif - - .global __start - .global _command_line - .global __platform_gpio_table - .global __target_name - - .h8300h - - .section .text - .file "crt0_ram.S" - - /* CPU Reset entry */ -__start: - mov.l #RAMEND,sp - ldc #0x80,ccr - - /* Peripheral Setup */ - -#if defined(CONFIG_MTD_UCLINUX) - /* move romfs image */ - jsr @__move_romfs -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #_command_line,er6 - mov.w #512,r4 - eepmov.w - - /* uClinux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - .byte 0xff,0xff - ;; P2DDR - .byte 0xff,0xff - ;; P3DDR - .byte 0xff,0x00 - ;; P4DDR - .byte 0x00,0x00 - ;; P5DDR - .byte 0x01,0x01 - ;; P6DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P8DDR - .byte 0x0c,0x0c - ;; P9DDR - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x30,0x30 - -__target_name: - .asciz "AE-3068" - - .section .bootvec,"ax" - jmp @__start diff --git a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile deleted file mode 100644 index 2b12a170209e..000000000000 --- a/arch/h8300/platform/h8300h/generic/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := crt0_$(MODEL).o diff --git a/arch/h8300/platform/h8300h/generic/crt0_ram.S b/arch/h8300/platform/h8300h/generic/crt0_ram.S deleted file mode 100644 index 5ab7d9c12910..000000000000 --- a/arch/h8300/platform/h8300h/generic/crt0_ram.S +++ /dev/null @@ -1,107 +0,0 @@ -/* - * linux/arch/h8300/platform/h8300h/generic/crt0_ram.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: AE-3068 (aka. aki3068net) - * Memory Layout : RAM - */ - -#define ASSEMBLY - -#include - -#if !defined(CONFIG_BLKDEV_RESERVE) -#if defined(CONFIG_GDB_DEBUG) -#define RAMEND (__ramend - 0xc000) -#else -#define RAMEND __ramend -#endif -#else -#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS -#endif - - .global __start - .global _command_line - .global __platform_gpio_table - .global __target_name - - .h8300h - - .section .text - .file "crt0_ram.S" - - /* CPU Reset entry */ -__start: - mov.l #RAMEND,sp - ldc #0x80,ccr - - /* Peripheral Setup */ - -#if defined(CONFIG_BLK_DEV_BLKMEM) - /* move romfs image */ - jsr @__move_romfs -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #_command_line,er6 - mov.w #512,r4 - eepmov.w - - /* uClinux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x00,0x00 - ;; P4DDR - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; P9DDR - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x00,0x00 - -__target_name: - .asciz "generic" diff --git a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S deleted file mode 100644 index dda1dfa15a5e..000000000000 --- a/arch/h8300/platform/h8300h/generic/crt0_rom.S +++ /dev/null @@ -1,122 +0,0 @@ -/* - * linux/arch/h8300/platform/h8300h/generic/crt0_rom.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: generic - * Memory Layout : ROM - */ - -#define ASSEMBLY - -#include - - .global __start - .global __command_line - .global __platform_gpio_table - .global __target_name - - .h8300h - .section .text - .file "crt0_rom.S" - - /* CPU Reset entry */ -__start: - mov.l #__ramend,sp - ldc #0x80,ccr - - /* Peripheral Setup */ - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy .data */ -#if !defined(CONFIG_H8300H_SIM) - /* copy .data */ - mov.l #__begin_data,er5 - mov.l #__sdata,er6 - mov.l #__edata,er4 - sub.l er6,er4 - shlr.l er4 - shlr.l er4 -1: - mov.l @er5+,er0 - mov.l er0,@er6 - adds #4,er6 - dec.l #1,er4 - bne 1b -#endif - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #__command_line,er6 - mov.w #512,r4 - eepmov.w - - /* linux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x00,0x00 - ;; P4DDR - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; P9DDR - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x00,0x00 - - .section .rodata -__target_name: - .asciz "generic" - - .section .bss -__command_line: - .space 512 - - /* interrupt vector */ - .section .vectors,"ax" - .long __start -vector = 1 - .rept 64-1 - .long _interrupt_redirect_table+vector*4 -vector = vector + 1 - .endr diff --git a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile deleted file mode 100644 index b7ff78050b7f..000000000000 --- a/arch/h8300/platform/h8300h/h8max/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := crt0_ram.o diff --git a/arch/h8300/platform/h8300h/h8max/crt0_ram.S b/arch/h8300/platform/h8300h/h8max/crt0_ram.S deleted file mode 100644 index 6a0d4e2d9ec6..000000000000 --- a/arch/h8300/platform/h8300h/h8max/crt0_ram.S +++ /dev/null @@ -1,110 +0,0 @@ -/* - * linux/arch/h8300/platform/h8300h/h8max/crt0_ram.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: H8MAX - * Memory Layout : RAM - */ - -#define ASSEMBLY - -#include - -#if !defined(CONFIG_BLKDEV_RESERVE) -#if defined(CONFIG_GDB_DEBUG) -#define RAMEND (__ramend - 0xc000) -#else -#define RAMEND __ramend -#endif -#else -#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS -#endif - - .global __start - .global _command_line - .global __platform_gpio_table - .global __target_name - - .h8300h - - .section .text - .file "crt0_ram.S" - - /* CPU Reset entry */ -__start: - mov.l #RAMEND,sp - ldc #0x80,ccr - - /* Peripheral Setup */ - -#if defined(CONFIG_MTD_UCLINUX) - /* move romfs image */ - jsr @__move_romfs -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #_command_line,er6 - mov.w #512,r4 - eepmov.w - - /* uClinux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - .byte 0xff,0xff - ;; P2DDR - .byte 0xff,0xff - ;; P3DDR - .byte 0x00,0x00 - ;; P4DDR - .byte 0x00,0x00 - ;; P5DDR - .byte 0x01,0x01 - ;; P6DDR - .byte 0xf6,0xf6 - ;; dummy - .byte 0x00,0x00 - ;; P8DDR - .byte 0xee,0xee - ;; P9DDR - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x30,0x30 - -__target_name: - .asciz "H8MAX" - - .section .bootvec,"ax" - jmp @__start diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c deleted file mode 100644 index 0a50353e09d5..000000000000 --- a/arch/h8300/platform/h8300h/irq.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Interrupt handling H8/300H depend. - * Yoshinori Sato - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -const int __initconst h8300_saved_vectors[] = { -#if defined(CONFIG_GDB_DEBUG) - TRAP3_VEC, /* TRAPA #3 is GDB breakpoint */ -#endif - -1, -}; - -const h8300_vector __initconst h8300_trap_table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - system_call, - 0, - 0, - trace_break, -}; - -int h8300_enable_irq_pin(unsigned int irq) -{ - int bitmask; - if (irq < EXT_IRQ0 || irq > EXT_IRQ5) - return 0; - - /* initialize IRQ pin */ - bitmask = 1 << (irq - EXT_IRQ0); - switch(irq) { - case EXT_IRQ0: - case EXT_IRQ1: - case EXT_IRQ2: - case EXT_IRQ3: - if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0) - return -EBUSY; - H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT); - break; - case EXT_IRQ4: - case EXT_IRQ5: - if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0) - return -EBUSY; - H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT); - break; - } - - return 0; -} - -void h8300_disable_irq_pin(unsigned int irq) -{ - int bitmask; - if (irq < EXT_IRQ0 || irq > EXT_IRQ5) - return; - - /* disable interrupt & release IRQ pin */ - bitmask = 1 << (irq - EXT_IRQ0); - switch(irq) { - case EXT_IRQ0: - case EXT_IRQ1: - case EXT_IRQ2: - case EXT_IRQ3: - *(volatile unsigned char *)IER &= ~bitmask; - H8300_GPIO_FREE(H8300_GPIO_P8, bitmask); - break ; - case EXT_IRQ4: - case EXT_IRQ5: - *(volatile unsigned char *)IER &= ~bitmask; - H8300_GPIO_FREE(H8300_GPIO_P9, bitmask); - break; - } -} diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c deleted file mode 100644 index 4f1ed0279633..000000000000 --- a/arch/h8300/platform/h8300h/ptrace_h8300h.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * linux/arch/h8300/platform/h8300h/ptrace_h8300h.c - * ptrace cpu depend helper functions - * - * Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include - -#define CCR_MASK 0x6f /* mode/imask not set */ -#define BREAKINST 0x5730 /* trapa #3 */ - -/* Mapping from PT_xxx to the stack offset at which the register is - saved. Notice that usp has no stack-slot and needs to be treated - specially (see get_reg/put_reg below). */ -static const int h8300_register_offset[] = { - PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), - PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0), - PT_REG(ccr), PT_REG(pc) -}; - -/* read register */ -long h8300_get_reg(struct task_struct *task, int regno) -{ - switch (regno) { - case PT_USP: - return task->thread.usp + sizeof(long)*2; - case PT_CCR: - return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); - default: - return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]); - } -} - -/* write register */ -int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) -{ - unsigned short oldccr; - switch (regno) { - case PT_USP: - task->thread.usp = data - sizeof(long)*2; - case PT_CCR: - oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); - oldccr &= ~CCR_MASK; - data &= CCR_MASK; - data |= oldccr; - *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data; - break; - default: - *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data; - break; - } - return 0; -} - -/* disable singlestep */ -void user_disable_single_step(struct task_struct *child) -{ - if((long)child->thread.breakinfo.addr != -1L) { - *child->thread.breakinfo.addr = child->thread.breakinfo.inst; - child->thread.breakinfo.addr = (unsigned short *)-1L; - } -} - -/* calculate next pc */ -enum jump_type {none, /* normal instruction */ - jabs, /* absolute address jump */ - ind, /* indirect address jump */ - ret, /* return to subrutine */ - reg, /* register indexed jump */ - relb, /* pc relative jump (byte offset) */ - relw, /* pc relative jump (word offset) */ - }; - -/* opcode decode table define - ptn: opcode pattern - msk: opcode bitmask - len: instruction length (<0 next table index) - jmp: jump operation mode */ -struct optable { - unsigned char bitpattern; - unsigned char bitmask; - signed char length; - signed char type; -} __attribute__((aligned(1),packed)); - -#define OPTABLE(ptn,msk,len,jmp) \ - { \ - .bitpattern = ptn, \ - .bitmask = msk, \ - .length = len, \ - .type = jmp, \ - } - -static const struct optable optable_0[] = { - OPTABLE(0x00,0xff, 1,none), /* 0x00 */ - OPTABLE(0x01,0xff,-1,none), /* 0x01 */ - OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */ - OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */ - OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */ - OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */ - OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */ - OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */ - OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */ - OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */ - OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */ - OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */ - OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */ - OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */ - OPTABLE(0x55,0xff, 1,relb), /* 0x55 */ - OPTABLE(0x57,0xff, 1,none), /* 0x57 */ - OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */ - OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */ - OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */ - OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */ - OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */ - OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */ - OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */ - OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */ - OPTABLE(0x78,0xff, 4,none), /* 0x78 */ - OPTABLE(0x79,0xff, 2,none), /* 0x79 */ - OPTABLE(0x7a,0xff, 3,none), /* 0x7a */ - OPTABLE(0x7b,0xff, 2,none), /* 0x7b */ - OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */ - OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */ -}; - -static const struct optable optable_1[] = { - OPTABLE(0x00,0xff,-3,none), /* 0x0100 */ - OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */ - OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */ - OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */ -}; - -static const struct optable optable_2[] = { - OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */ - OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */ -}; - -static const struct optable optable_3[] = { - OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */ - OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */ - OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */ - OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */ -}; - -static const struct optable optable_4[] = { - OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */ - OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */ -}; - -static const struct optables_list { - const struct optable *ptr; - int size; -} optables[] = { -#define OPTABLES(no) \ - { \ - .ptr = optable_##no, \ - .size = sizeof(optable_##no) / sizeof(struct optable), \ - } - OPTABLES(0), - OPTABLES(1), - OPTABLES(2), - OPTABLES(3), - OPTABLES(4), - -}; - -const unsigned char condmask[] = { - 0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20 -}; - -static int isbranch(struct task_struct *task,int reson) -{ - unsigned char cond = h8300_get_reg(task, PT_CCR); - /* encode complex conditions */ - /* B4: N^V - B5: Z|(N^V) - B6: C|Z */ - __asm__("bld #3,%w0\n\t" - "bxor #1,%w0\n\t" - "bst #4,%w0\n\t" - "bor #2,%w0\n\t" - "bst #5,%w0\n\t" - "bld #2,%w0\n\t" - "bor #0,%w0\n\t" - "bst #6,%w0\n\t" - :"=&r"(cond)::"cc"); - cond &= condmask[reson >> 1]; - if (!(reson & 1)) - return cond == 0; - else - return cond != 0; -} - -static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc) -{ - const struct optable *op; - unsigned char *fetch_p; - unsigned char inst; - unsigned long addr; - unsigned long *sp; - int op_len,regno; - op = optables[0].ptr; - op_len = optables[0].size; - fetch_p = (unsigned char *)pc; - inst = *fetch_p++; - do { - if ((inst & op->bitmask) == op->bitpattern) { - if (op->length < 0) { - op = optables[-op->length].ptr; - op_len = optables[-op->length].size + 1; - inst = *fetch_p++; - } else { - switch (op->type) { - case none: - return pc + op->length; - case jabs: - addr = *(unsigned long *)pc; - return (unsigned short *)(addr & 0x00ffffff); - case ind: - addr = *pc & 0xff; - return (unsigned short *)(*(unsigned long *)addr); - case ret: - sp = (unsigned long *)h8300_get_reg(child, PT_USP); - /* user stack frames - | er0 | temporary saved - +--------+ - | exp | exception stack frames - +--------+ - | ret pc | userspace return address - */ - return (unsigned short *)(*(sp+2) & 0x00ffffff); - case reg: - regno = (*pc >> 4) & 0x07; - if (regno == 0) - addr = h8300_get_reg(child, PT_ER0); - else - addr = h8300_get_reg(child, regno-1+PT_ER1); - return (unsigned short *)addr; - case relb: - if (inst == 0x55 || isbranch(child,inst & 0x0f)) - pc = (unsigned short *)((unsigned long)pc + - ((signed char)(*fetch_p))); - return pc+1; /* skip myself */ - case relw: - if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4)) - pc = (unsigned short *)((unsigned long)pc + - ((signed short)(*(pc+1)))); - return pc+2; /* skip myself */ - } - } - } else - op++; - } while(--op_len > 0); - return NULL; -} - -/* Set breakpoint(s) to simulate a single step from the current PC. */ - -void user_enable_single_step(struct task_struct *child) -{ - unsigned short *nextpc; - nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC)); - child->thread.breakinfo.addr = nextpc; - child->thread.breakinfo.inst = *nextpc; - *nextpc = BREAKINST; -} - -asmlinkage void trace_trap(unsigned long bp) -{ - if ((unsigned long)current->thread.breakinfo.addr == bp) { - user_disable_single_step(current); - force_sig(SIGTRAP,current); - } else - force_sig(SIGILL,current); -} - diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile deleted file mode 100644 index bf1241883766..000000000000 --- a/arch/h8300/platform/h8s/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the linux kernel. -# -# Reuse any files we can from the H8S -# - -obj-y := ints_h8s.o ptrace_h8s.o diff --git a/arch/h8300/platform/h8s/edosk2674/Makefile b/arch/h8300/platform/h8s/edosk2674/Makefile deleted file mode 100644 index 8e349723bb4f..000000000000 --- a/arch/h8300/platform/h8s/edosk2674/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := crt0_$(MODEL).o diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S b/arch/h8300/platform/h8s/edosk2674/crt0_ram.S deleted file mode 100644 index 5ed191b37cde..000000000000 --- a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S +++ /dev/null @@ -1,130 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: EDOSK-2674 - * Memory Layout : RAM - */ - -#define ASSEMBLY - -#include -#include - -#if !defined(CONFIG_BLKDEV_RESERVE) -#if defined(CONFIG_GDB_DEBUG) -#define RAMEND (__ramend - 0xc000) -#else -#define RAMEND __ramend -#endif -#else -#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS -#endif - - .global __start - .global __command_line - .global __platform_gpio_table - .global __target_name - - .h8300s - - .section .text - .file "crt0_ram.S" - - /* CPU Reset entry */ -__start: - mov.l #RAMEND,sp - ldc #0x80,ccr - ldc #0x00,exr - - /* Peripheral Setup */ - bclr #4,@INTCR:8 /* interrupt mode 2 */ - bset #5,@INTCR:8 - bclr #0,@IER+1:16 - bset #1,@ISCRL+1:16 /* IRQ0 Positive Edge */ - bclr #0,@ISCRL+1:16 - -#if defined(CONFIG_MTD_UCLINUX) - /* move romfs image */ - jsr @__move_romfs -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l er5,er6 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr #2,er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #_command_line,er6 - mov.w #512,r4 - eepmov.w - - /* uClinux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - ;; used,ddr - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x3f,0x3a - ;; dummy - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; P7DDR - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; PADDR - .byte 0xff,0xff - ;; PBDDR - .byte 0xff,0x00 - ;; PCDDR - .byte 0xff,0x00 - ;; PDDDR - .byte 0xff,0x00 - ;; PEDDR - .byte 0xff,0x00 - ;; PFDDR - .byte 0xff,0xff - ;; PGDDR - .byte 0x0f,0x0f - ;; PHDDR - .byte 0x0f,0x0f - -__target_name: - .asciz "EDOSK-2674" - - .section .bootvec,"ax" - jmp @__start diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S deleted file mode 100644 index 06d1d7f324ca..000000000000 --- a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S +++ /dev/null @@ -1,186 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/edosk2674/crt0_rom.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: EDOSK-2674 - * Memory Layout : ROM - */ - -#define ASSEMBLY - -#include -#include - - .global __start - .global __command_line - .global __platform_gpio_table - .global __target_name - - .h8300s - .section .text - .file "crt0_rom.S" - - /* CPU Reset entry */ -__start: - mov.l #__ramend,sp - ldc #0x80,ccr - ldc #0,exr - - /* Peripheral Setup */ -;BSC/GPIO setup - mov.l #init_regs,er0 - mov.w #0xffff,e2 -1: - mov.w @er0+,r2 - beq 2f - mov.w @er0+,r1 - mov.b r1l,@er2 - bra 1b - -2: -;SDRAM setup -#define SDRAM_SMR 0x400040 - - mov.b #0,r0l - mov.b r0l,@DRACCR:16 - mov.w #0x188,r0 - mov.w r0,@REFCR:16 - mov.w #0x85b4,r0 - mov.w r0,@DRAMCR:16 - mov.b #0,r1l - mov.b r1l,@SDRAM_SMR - mov.w #0x84b4,r0 - mov.w r0,@DRAMCR:16 -;special thanks to Arizona Cooperative Power - - /* copy .data */ - mov.l #__begin_data,er5 - mov.l #__sdata,er6 - mov.l #__edata,er4 - sub.l er6,er4 - shlr.l #2,er4 -1: - mov.l @er5+,er0 - mov.l er0,@er6 - adds #4,er6 - dec.l #1,er4 - bne 1b - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr.l #2,er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #__command_line,er6 - mov.w #512,r4 - eepmov.w - - /* linux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -#define INIT_REGS_DATA(REGS,DATA) \ - .word ((REGS) & 0xffff),DATA - -init_regs: -INIT_REGS_DATA(ASTCR,0xff) -INIT_REGS_DATA(RDNCR,0x00) -INIT_REGS_DATA(ABWCR,0x80) -INIT_REGS_DATA(WTCRAH,0x27) -INIT_REGS_DATA(WTCRAL,0x77) -INIT_REGS_DATA(WTCRBH,0x71) -INIT_REGS_DATA(WTCRBL,0x22) -INIT_REGS_DATA(CSACRH,0x80) -INIT_REGS_DATA(CSACRL,0x80) -INIT_REGS_DATA(BROMCRH,0xa0) -INIT_REGS_DATA(BROMCRL,0xa0) -INIT_REGS_DATA(P3DDR,0x3a) -INIT_REGS_DATA(P3ODR,0x06) -INIT_REGS_DATA(PADDR,0xff) -INIT_REGS_DATA(PFDDR,0xfe) -INIT_REGS_DATA(PGDDR,0x0f) -INIT_REGS_DATA(PHDDR,0x0f) -INIT_REGS_DATA(PFCR0,0xff) -INIT_REGS_DATA(PFCR2,0x0d) -INIT_REGS_DATA(ITSR, 0x00) -INIT_REGS_DATA(ITSR+1,0x3f) -INIT_REGS_DATA(INTCR,0x20) - - .word 0 - -gpio_table: - ;; P1DDR - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; P7DDR - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x00,0x00 - ;; PCDDR - .byte 0x00,0x00 - ;; PDDDR - .byte 0x00,0x00 - ;; PEDDR - .byte 0x00,0x00 - ;; PFDDR - .byte 0x00,0x00 - ;; PGDDR - .byte 0x00,0x00 - ;; PHDDR - .byte 0x00,0x00 - - .section .rodata -__target_name: - .asciz "EDOSK-2674" - - .section .bss -__command_line: - .space 512 - - /* interrupt vector */ - .section .vectors,"ax" - .long __start - .long __start -vector = 2 - .rept 126 - .long _interrupt_redirect_table+vector*4 -vector = vector + 1 - .endr diff --git a/arch/h8300/platform/h8s/generic/Makefile b/arch/h8300/platform/h8s/generic/Makefile deleted file mode 100644 index 44b4685c664c..000000000000 --- a/arch/h8300/platform/h8s/generic/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y = crt0_$(MODEL).o diff --git a/arch/h8300/platform/h8s/generic/crt0_ram.S b/arch/h8300/platform/h8s/generic/crt0_ram.S deleted file mode 100644 index 7018915de74f..000000000000 --- a/arch/h8300/platform/h8s/generic/crt0_ram.S +++ /dev/null @@ -1,127 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: generic - * Memory Layout : RAM - */ - -#define ASSEMBLY - -#include -#include - -#if !defined(CONFIG_BLKDEV_RESERVE) -#if defined(CONFIG_GDB_DEBUG) -#define RAMEND (__ramend - 0xc000) -#else -#define RAMEND __ramend -#endif -#else -#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS -#endif - - .global __start - .global __command_line - .global __platform_gpio_table - .global __target_name - - .h8300s - - .section .text - .file "crt0_ram.S" - - /* CPU Reset entry */ -__start: - mov.l #RAMEND,sp - ldc #0x80,ccr - ldc #0x00,exr - - /* Peripheral Setup */ - bclr #4,@INTCR:8 /* interrupt mode 2 */ - bset #5,@INTCR:8 - -#if defined(CONFIG_MTD_UCLINUX) - /* move romfs image */ - jsr @__move_romfs -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l er5,er6 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr #2,er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* copy kernel commandline */ - mov.l #COMMAND_START,er5 - mov.l #_command_line,er6 - mov.w #512,r4 - eepmov.w - - /* uClinux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - ;; used,ddr - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; P7DDR - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x00,0x00 - ;; PCDDR - .byte 0x00,0x00 - ;; PDDDR - .byte 0x00,0x00 - ;; PEDDR - .byte 0x00,0x00 - ;; PFDDR - .byte 0x00,0x00 - ;; PGDDR - .byte 0x00,0x00 - ;; PHDDR - .byte 0x00,0x00 - -__target_name: - .asciz "generic" - - .section .bootvec,"ax" - jmp @__start diff --git a/arch/h8300/platform/h8s/generic/crt0_rom.S b/arch/h8300/platform/h8s/generic/crt0_rom.S deleted file mode 100644 index 623ba7828193..000000000000 --- a/arch/h8300/platform/h8s/generic/crt0_rom.S +++ /dev/null @@ -1,128 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/generic/crt0_rom.S - * - * Yoshinori Sato - * - * Platform depend startup - * Target Archtecture: generic - * Memory Layout : ROM - */ - -#define ASSEMBLY - -#include -#include - - .global __start - .global __command_line - .global __platform_gpio_table - .global __target_name - - .h8300s - .section .text - .file "crt0_rom.S" - - /* CPU Reset entry */ -__start: - mov.l #__ramend,sp - ldc #0x80,ccr - ldc #0,exr - bclr #4,@INTCR:8 - bset #5,@INTCR:8 /* Interrupt mode 2 */ - - /* Peripheral Setup */ - - /* copy .data */ -#if !defined(CONFIG_H8S_SIM) - mov.l #__begin_data,er5 - mov.l #__sdata,er6 - mov.l #__edata,er4 - sub.l er6,er4 - shlr.l #2,er4 -1: - mov.l @er5+,er0 - mov.l er0,@er6 - adds #4,er6 - dec.l #1,er4 - bne 1b -#endif - - /* .bss clear */ - mov.l #__sbss,er5 - mov.l #__ebss,er4 - sub.l er5,er4 - shlr.l #2,er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - - /* linux kernel start */ - ldc #0x90,ccr /* running kernel */ - mov.l #_init_thread_union,sp - add.l #0x2000,sp - jsr @_start_kernel -_exit: - - jmp _exit - - rts - - /* I/O port assign information */ -__platform_gpio_table: - mov.l #gpio_table,er0 - rts - -gpio_table: - ;; P1DDR - .byte 0x00,0x00 - ;; P2DDR - .byte 0x00,0x00 - ;; P3DDR - .byte 0x00,0x00 - ;; P4DDR - .byte 0x00,0x00 - ;; P5DDR - .byte 0x00,0x00 - ;; P6DDR - .byte 0x00,0x00 - ;; dummy - .byte 0x00,0x00 - ;; P8DDR - .byte 0x00,0x00 - ;; PADDR - .byte 0x00,0x00 - ;; PBDDR - .byte 0x00,0x00 - ;; PCDDR - .byte 0x00,0x00 - ;; PDDDR - .byte 0x00,0x00 - ;; PEDDR - .byte 0x00,0x00 - ;; PFDDR - .byte 0x00,0x00 - ;; PGDDR - .byte 0x00,0x00 - ;; PHDDR - .byte 0x00,0x00 - - .section .rodata -__target_name: - .asciz "generic" - - .section .bss -__command_line: - .space 512 - - /* interrupt vector */ - .section .vectors,"ax" - .long __start - .long __start -vector = 2 - .rept 126-1 - .long _interrupt_redirect_table+vector*4 -vector = vector + 1 - .endr diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c deleted file mode 100644 index f3a5511c16b1..000000000000 --- a/arch/h8300/platform/h8s/irq.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/ints_h8s.c - * Interrupt handling CPU variants - * - * Yoshinori Sato - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* saved vector list */ -const int __initconst h8300_saved_vectors[] = { -#if defined(CONFIG_GDB_DEBUG) - TRACE_VEC, - TRAP3_VEC, -#endif - -1 -}; - -/* trap entry table */ -const H8300_VECTOR __initconst h8300_trap_table[] = { - 0,0,0,0,0, - trace_break, /* TRACE */ - 0,0, - system_call, /* TRAPA #0 */ - 0,0,0,0,0,0,0 -}; - -/* IRQ pin assignment */ -struct irq_pins { - unsigned char port_no; - unsigned char bit_no; -} __attribute__((aligned(1),packed)); -/* ISTR = 0 */ -static const struct irq_pins irq_assign_table0[16]={ - {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, - {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, - {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, - {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7}, - {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1}, - {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3}, - {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5}, - {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, -}; -/* ISTR = 1 */ -static const struct irq_pins irq_assign_table1[16]={ - {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, - {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, - {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, - {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3}, - {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1}, - {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3}, - {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5}, - {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7}, -}; - -/* IRQ to GPIO pin translation */ -#define IRQ_GPIO_MAP(irqbit,irq,port,bit) \ -do { \ - if (*(volatile unsigned short *)ITSR & irqbit) { \ - port = irq_assign_table1[irq - EXT_IRQ0].port_no; \ - bit = irq_assign_table1[irq - EXT_IRQ0].bit_no; \ - } else { \ - port = irq_assign_table0[irq - EXT_IRQ0].port_no; \ - bit = irq_assign_table0[irq - EXT_IRQ0].bit_no; \ - } \ -} while(0) - -int h8300_enable_irq_pin(unsigned int irq) -{ - if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { - unsigned short ptn = 1 << (irq - EXT_IRQ0); - unsigned int port_no,bit_no; - IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); - if (H8300_GPIO_RESERVE(port_no, bit_no) == 0) - return -EBUSY; /* pin already use */ - H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT); - *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */ - } - - return 0; -} - -void h8300_disable_irq_pin(unsigned int irq) -{ - if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { - /* disable interrupt & release IRQ pin */ - unsigned short ptn = 1 << (irq - EXT_IRQ0); - unsigned short port_no,bit_no; - *(volatile unsigned short *)ISR &= ~ptn; - *(volatile unsigned short *)IER &= ~ptn; - IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); - H8300_GPIO_FREE(port_no, bit_no); - } -} diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c deleted file mode 100644 index c058ab1a8495..000000000000 --- a/arch/h8300/platform/h8s/ptrace_h8s.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * linux/arch/h8300/platform/h8s/ptrace_h8s.c - * ptrace cpu depend helper functions - * - * Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include -#include - -#define CCR_MASK 0x6f -#define EXR_TRACE 0x80 - -/* Mapping from PT_xxx to the stack offset at which the register is - saved. Notice that usp has no stack-slot and needs to be treated - specially (see get_reg/put_reg below). */ -static const int h8300_register_offset[] = { - PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), - PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0), - PT_REG(ccr), PT_REG(pc), 0, PT_REG(exr) -}; - -/* read register */ -long h8300_get_reg(struct task_struct *task, int regno) -{ - switch (regno) { - case PT_USP: - return task->thread.usp + sizeof(long)*2 + 2; - case PT_CCR: - case PT_EXR: - return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); - default: - return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]); - } -} - -/* write register */ -int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) -{ - unsigned short oldccr; - switch (regno) { - case PT_USP: - task->thread.usp = data - sizeof(long)*2 - 2; - case PT_CCR: - oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); - oldccr &= ~CCR_MASK; - data &= CCR_MASK; - data |= oldccr; - *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data; - break; - case PT_EXR: - /* exr modify not support */ - return -EIO; - default: - *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data; - break; - } - return 0; -} - -/* disable singlestep */ -void user_disable_single_step(struct task_struct *child) -{ - *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE; -} - -/* enable singlestep */ -void user_enable_single_step(struct task_struct *child) -{ - *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE; -} - -asmlinkage void trace_trap(unsigned long bp) -{ - (void)bp; - force_sig(SIGTRAP,current); -} - diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index d34049712a4d..50fe651da965 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -5,7 +5,7 @@ #include /* - * Generic header for SuperH (H)SCI(F) (used by sh/sh64/h8300 and related parts) + * Generic header for SuperH (H)SCI(F) (used by sh/sh64 and related parts) */ #define SCIx_NOT_SUPPORTED (-1) diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf index 46736604c26c..a1203148dfa1 100644 --- a/tools/testing/ktest/examples/crosstests.conf +++ b/tools/testing/ktest/examples/crosstests.conf @@ -133,12 +133,6 @@ CROSS = frv-linux ARCH = frv GCC_VER = 4.5.1 -# h8300 - failed make defconfig?? -TEST_START IF ${RUN} == h8300 || ${DO_FAILED} -CROSS = h8300-elf -ARCH = h8300 -GCC_VER = 4.5.1 - # m68k fails with error? TEST_START IF ${RUN} == m68k || ${DO_DEFAULT} CROSS = m68k-linux -- cgit From 6f6f467eaaa0ac4fb77714d0172d65c781dabb8c Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 30 Aug 2013 06:12:40 -0700 Subject: Drop remaining references to H8/300 architecture With the architecture gone, any references to it are no longer needed. Cc: Yoshinori Sato Acked-by: Greg Kroah-Hartman Signed-off-by: Guenter Roeck --- include/uapi/linux/audit.h | 1 - include/uapi/linux/elf-em.h | 1 - 2 files changed, 2 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 75cef3fd97ad..db0b825b4810 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -329,7 +329,6 @@ enum { #define AUDIT_ARCH_ARMEB (EM_ARM) #define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) #define AUDIT_ARCH_FRV (EM_FRV) -#define AUDIT_ARCH_H8300 (EM_H8_300) #define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) #define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_M32R (EM_M32R) diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h index 59c17a2d38ad..01529bd96438 100644 --- a/include/uapi/linux/elf-em.h +++ b/include/uapi/linux/elf-em.h @@ -31,7 +31,6 @@ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Renesas M32R */ -#define EM_H8_300 46 /* Renesas H8/300,300H,H8S */ #define EM_MN10300 89 /* Panasonic/MEI MN10300, AM33 */ #define EM_BLACKFIN 106 /* ADI Blackfin Processor */ #define EM_TI_C6000 140 /* TI C6X DSPs */ -- cgit From 4aa806b771d16b810771d86ce23c4c3160888db3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Jun 2013 13:49:44 +0100 Subject: DMA-API: provide a helper to set both DMA and coherent DMA masks Provide a helper to set both the DMA and coherent DMA masks to the same value - this avoids duplicated code in a number of drivers, sometimes with buggy error handling, and also allows us identify which drivers do things differently. Signed-off-by: Russell King --- Documentation/DMA-API-HOWTO.txt | 37 ++++++++++++++++++++++--------------- Documentation/DMA-API.txt | 8 ++++++++ include/linux/dma-mapping.h | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index 14129f149a75..5e983031cc11 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt @@ -101,14 +101,23 @@ style to do this even if your device holds the default setting, because this shows that you did think about these issues wrt. your device. -The query is performed via a call to dma_set_mask(): +The query is performed via a call to dma_set_mask_and_coherent(): - int dma_set_mask(struct device *dev, u64 mask); + int dma_set_mask_and_coherent(struct device *dev, u64 mask); -The query for consistent allocations is performed via a call to -dma_set_coherent_mask(): +which will query the mask for both streaming and coherent APIs together. +If you have some special requirements, then the following two separate +queries can be used instead: - int dma_set_coherent_mask(struct device *dev, u64 mask); + The query for streaming mappings is performed via a call to + dma_set_mask(): + + int dma_set_mask(struct device *dev, u64 mask); + + The query for consistent allocations is performed via a call + to dma_set_coherent_mask(): + + int dma_set_coherent_mask(struct device *dev, u64 mask); Here, dev is a pointer to the device struct of your device, and mask is a bit mask describing which bits of an address your device @@ -137,7 +146,7 @@ exactly why. The standard 32-bit addressing device would do something like this: - if (dma_set_mask(dev, DMA_BIT_MASK(32))) { + if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { printk(KERN_WARNING "mydev: No suitable DMA available.\n"); goto ignore_this_device; @@ -171,22 +180,20 @@ the case would look like this: int using_dac, consistent_using_dac; - if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { + if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { using_dac = 1; consistent_using_dac = 1; - dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); - } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { + } else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { using_dac = 0; consistent_using_dac = 0; - dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); } else { printk(KERN_WARNING "mydev: No suitable DMA available.\n"); goto ignore_this_device; } -dma_set_coherent_mask() will always be able to set the same or a -smaller mask as dma_set_mask(). However for the rare case that a +The coherent coherent mask will always be able to set the same or a +smaller mask as the streaming mask. However for the rare case that a device driver only uses consistent allocations, one would have to check the return value from dma_set_coherent_mask(). @@ -199,9 +206,9 @@ address you might do something like: goto ignore_this_device; } -When dma_set_mask() is successful, and returns zero, the kernel saves -away this mask you have provided. The kernel will use this -information later when you make DMA mappings. +When dma_set_mask() or dma_set_mask_and_coherent() is successful, and +returns zero, the kernel saves away this mask you have provided. The +kernel will use this information later when you make DMA mappings. There is a case which we are aware of at this time, which is worth mentioning in this documentation. If your device supports multiple diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 78a6c569d204..e865279cec58 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -141,6 +141,14 @@ won't change the current mask settings. It is more intended as an internal API for use by the platform than an external API for use by driver writers. +int +dma_set_mask_and_coherent(struct device *dev, u64 mask) + +Checks to see if the mask is possible and updates the device +streaming and coherent DMA mask parameters if it is. + +Returns: 0 if successful and a negative error if not. + int dma_set_mask(struct device *dev, u64 mask) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 3a8d0a2af607..ec951f98e3d9 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -97,6 +97,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) } #endif +/* + * Set both the DMA mask and the coherent DMA mask to the same thing. + * Note that we don't check the return value from dma_set_coherent_mask() + * as the DMA API guarantees that the coherent DMA mask can be set to + * the same or smaller than the streaming DMA mask. + */ +static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) +{ + int rc = dma_set_mask(dev, mask); + if (rc == 0) + dma_set_coherent_mask(dev, mask); + return rc; +} + extern u64 dma_get_required_mask(struct device *dev); static inline unsigned int dma_get_max_seg_size(struct device *dev) -- cgit From c7ccde6eac6d3c4bc6110cc3fd76ef3823bc0831 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 3 Sep 2013 13:58:43 -0400 Subject: USB: see if URB comes from a completion handler Now that URBs can be completed inside tasklets, we need a way of determining whether a completion handler for a given endpoint is currently running. Otherwise it's not possible to maintain the API guarantee about keeping isochronous streams synchronous when an underrun occurs. This patch adds a field and a routine to check whether a completion handler for a periodic endpoint is running. At the moment no analogous routine appears to be necessary for async endpoints, but one can always be added. Signed-off-by: Alan Stern CC: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 ++ include/linux/usb/hcd.h | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d6a8d23f047b..3a2e82a9c115 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1703,7 +1703,9 @@ static void usb_giveback_urb_bh(unsigned long param) urb = list_entry(local_list.next, struct urb, urb_list); list_del_init(&urb->urb_list); + bh->completing_ep = urb->ep; __usb_hcd_giveback_urb(urb); + bh->completing_ep = NULL; } /* check if there are new URBs to giveback */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 75efc45eaa2f..8c865134c881 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -73,6 +73,7 @@ struct giveback_urb_bh { spinlock_t lock; struct list_head head; struct tasklet_struct bh; + struct usb_host_endpoint *completing_ep; }; struct usb_hcd { @@ -378,6 +379,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd) return hcd->driver->flags & HCD_BH; } +static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + return hcd->high_prio_bh.completing_ep == ep; +} + extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, int status); -- cgit From 6c74dada4f5a37037dee1da6a8a7aeb56c558bca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 30 Aug 2013 14:03:59 +0200 Subject: usb-core: Make usb_free_streams return an error The hcd-driver free_streams method can return an error, so lets properly propagate that. Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 11 +++++++---- include/linux/usb.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3a2e82a9c115..ab54999da2bf 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2075,8 +2075,11 @@ EXPORT_SYMBOL_GPL(usb_alloc_streams); * * Reverts a group of bulk endpoints back to not using stream IDs. * Can fail if we are given bad arguments, or HCD is broken. + * + * Return: On success, the number of allocated streams. On failure, a negative + * error code. */ -void usb_free_streams(struct usb_interface *interface, +int usb_free_streams(struct usb_interface *interface, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags) { @@ -2087,14 +2090,14 @@ void usb_free_streams(struct usb_interface *interface, dev = interface_to_usbdev(interface); hcd = bus_to_hcd(dev->bus); if (dev->speed != USB_SPEED_SUPER) - return; + return -EINVAL; /* Streams only apply to bulk endpoints. */ for (i = 0; i < num_eps; i++) if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) - return; + return -EINVAL; - hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); + return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); } EXPORT_SYMBOL_GPL(usb_free_streams); diff --git a/include/linux/usb.h b/include/linux/usb.h index 001629cd1a97..f726c39097e0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -702,7 +702,7 @@ extern int usb_alloc_streams(struct usb_interface *interface, unsigned int num_streams, gfp_t mem_flags); /* Reverts a group of bulk endpoints back to not using stream IDs. */ -extern void usb_free_streams(struct usb_interface *interface, +extern int usb_free_streams(struct usb_interface *interface, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags); -- cgit From 00c877c69ba315d6c565a4df51c71b11e82cdeb8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 18 Sep 2013 18:18:02 +0530 Subject: regulator: core: add support for configuring turn-on time through constraints The turn-on time of the regulator depends on the regulator device's electrical characteristics. Sometimes regulator turn-on time also depends on the capacitive load on the given platform and it can be more than the datasheet value. The driver provides the enable-time as per datasheet. Add support for configure the enable ramp time through regulator constraints so that regulator core can take this value for enable time for that regulator. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/regulator.txt | 5 +++++ drivers/regulator/core.c | 2 ++ drivers/regulator/of_regulator.c | 6 ++++++ include/linux/regulator/machine.h | 2 ++ 4 files changed, 15 insertions(+) (limited to 'include') diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 2bd8f0978765..e2c7f1e7251a 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -14,6 +14,11 @@ Optional properties: - regulator-ramp-delay: ramp delay for regulator(in uV/uS) For hardwares which support disabling ramp rate, it should be explicitly intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay. +- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply + rail to reach the target voltage, plus/minus whatever tolerance the board + design requires. This property describes the total system ramp time + required due to the combination of internal ramping of the regulator itself, + and board design issues such as trace capacitance and load on the supply. Deprecated properties: - regulator-compatible: If a regulator chip contains multiple diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a01b8b3b70ca..5217c1964c32 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1186,6 +1186,8 @@ overflow_err: static int _regulator_get_enable_time(struct regulator_dev *rdev) { + if (rdev->constraints && rdev->constraints->enable_time) + return rdev->constraints->enable_time; if (!rdev->desc->ops->enable_time) return rdev->desc->enable_time; return rdev->desc->ops->enable_time(rdev); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 7827384680d6..ea4f36f2cbe2 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -23,6 +23,8 @@ static void of_get_regulation_constraints(struct device_node *np, const __be32 *min_uA, *max_uA, *ramp_delay; struct property *prop; struct regulation_constraints *constraints = &(*init_data)->constraints; + int ret; + u32 pval; constraints->name = of_get_property(np, "regulator-name", NULL); @@ -73,6 +75,10 @@ static void of_get_regulation_constraints(struct device_node *np, else constraints->ramp_disable = true; } + + ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); + if (!ret) + constraints->enable_time = pval; } /** diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 999b20ce06cf..8108751acb86 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -95,6 +95,7 @@ struct regulator_state { * @initial_state: Suspend state to set by default. * @initial_mode: Mode to set at startup. * @ramp_delay: Time to settle down after voltage change (unit: uV/us) + * @enable_time: Turn-on time of the rails (unit: microseconds) */ struct regulation_constraints { @@ -129,6 +130,7 @@ struct regulation_constraints { unsigned int initial_mode; unsigned int ramp_delay; + unsigned int enable_time; /* constraint flags */ unsigned always_on:1; /* regulator never off when system is on */ -- cgit From 0af784dcbc44e3cf21a1bda3ce14df5fcc2bfe93 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 16 Sep 2013 13:05:12 +0300 Subject: Bluetooth: Remove unused event mask struct The struct for HCI_Set_Event_Mask is never used. Instead a local 8-byte array is used for sending this command. Therefore, remove the unnecessary struct definition. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 30c88b585c1b..52bd2488ff4a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -694,9 +694,6 @@ struct hci_cp_sniff_subrate { } __packed; #define HCI_OP_SET_EVENT_MASK 0x0c01 -struct hci_cp_set_event_mask { - __u8 mask[8]; -} __packed; #define HCI_OP_RESET 0x0c03 -- cgit From e793dcf082c847bd2b742c781252c20cbec37986 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 16 Sep 2013 13:05:19 +0300 Subject: Bluetooth: Fix waiting for clearing of BT_SK_SUSPEND flag In the case of blocking sockets we should not proceed with sendmsg() if the socket has the BT_SK_SUSPEND flag set. So far the code was only ensuring that POLLOUT doesn't get set for non-blocking sockets using poll() but there was no code in place to ensure that blocking sockets do the right thing when writing to them. This patch adds a new bt_sock_wait_ready helper function to sleep in the sendmsg call if the BT_SK_SUSPEND flag is set, and wake up as soon as it is unset. It also updates the L2CAP and RFCOMM sendmsg callbacks to take advantage of this new helper function. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/bluetooth.h | 1 + net/bluetooth/af_bluetooth.c | 40 +++++++++++++++++++++++++++++++++++++++ net/bluetooth/l2cap_sock.c | 6 ++++++ net/bluetooth/rfcomm/sock.c | 7 ++++++- 4 files changed, 53 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 10d43d8c7037..afbc711ba37a 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -249,6 +249,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); +int bt_sock_wait_ready(struct sock *sk, unsigned long flags); void bt_accept_enqueue(struct sock *parent, struct sock *sk); void bt_accept_unlink(struct sock *sk); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 9096137c889c..c600631cd19e 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -525,6 +525,46 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) } EXPORT_SYMBOL(bt_sock_wait_state); +/* This function expects the sk lock to be held when called */ +int bt_sock_wait_ready(struct sock *sk, unsigned long flags) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo; + int err = 0; + + BT_DBG("sk %p", sk); + + timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + + add_wait_queue(sk_sleep(sk), &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) { + if (!timeo) { + err = -EAGAIN; + break; + } + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + set_current_state(TASK_INTERRUPTIBLE); + + err = sock_error(sk); + if (err) + break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk_sleep(sk), &wait); + + return err; +} +EXPORT_SYMBOL(bt_sock_wait_ready); + #ifdef CONFIG_PROC_FS struct bt_seq_state { struct bt_sock_list *l; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 0098af80b213..ad95b426b09c 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -777,6 +777,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_state != BT_CONNECTED) return -ENOTCONN; + lock_sock(sk); + err = bt_sock_wait_ready(sk, msg->msg_flags); + release_sock(sk); + if (err) + return err; + l2cap_chan_lock(chan); err = l2cap_chan_send(chan, msg, len, sk->sk_priority); l2cap_chan_unlock(chan); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 30b3721dc6d7..072938dc527d 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -544,7 +544,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; struct sk_buff *skb; - int sent = 0; + int sent; if (test_bit(RFCOMM_DEFER_SETUP, &d->flags)) return -ENOTCONN; @@ -559,6 +559,10 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, lock_sock(sk); + sent = bt_sock_wait_ready(sk, msg->msg_flags); + if (sent) + goto done; + while (len) { size_t size = min_t(size_t, len, d->mtu); int err; @@ -594,6 +598,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, len -= size; } +done: release_sock(sk); return sent; -- cgit From e9a03add0c6ed5341fc59ff9c76843c2888a33fa Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 3 Sep 2013 16:28:59 +0800 Subject: pinctrl: ADI PIN control driver for the GPIO controller on bf54x and bf60x. The new ADI GPIO2 controller was introduced since the BF548 and BF60x processors. It differs a lot from the old one on BF5xx processors. So, create a pinctrl driver under the pinctrl framework. - Define gpio ports and pin interrupt controllers as individual platform devices. - Register a pinctrl driver for the whole GPIO ports and pin interrupt devices. - Probe pint devices before port devices. Put device instances into the global gpio and pint lists. - Define peripheral, irq and gpio reservation bit masks for each gpio port as runtime resources. - Save and restore gpio port and pint status MMRs in syscore PM functions. - Create the plug-in subdrivers to hold the pinctrl soc data for bf54x and bf60x. Add soc data into struct adi_pinctrl. Initialize the soc data in pin controller probe function. Get the pin groups and functions via the soc data reference. - Call gpiochip_add_pin_range() in gpio device probe function to register range cross reference between gpio device and pin control device. - Get range by pinctrl_find_gpio_range_from_pin(), find gpio_port object by container_of() and find adi_pinctrl by pin control device name. - Handle peripheral and gpio requests in pinctrl operation functions. - Demux gpio IRQs via the irq_domain created by each GPIO port. v2-changes: - Remove unlinke() directive. v3-changes: - Rename struct adi_pmx to adi_pinctrl. - Fix the comments of struct gpio_pint. - Remove unused pin_base in struct gpio_port. - Change pint_assign into bool type. - Add comments about the relationship between pint device and port device to the driver header. - Use BIT macro to shift bit. - Remove all bitmap reservation help functions. Inline reservation functions into the actual code. - Remove gpio and offset mutual reference help functions. - Remove all help functions to find gpio_port and adi_pinctrl structs. Get range by pinctrl_find_gpio_range_from_pin(), find gpio_port object by container_of() and find adi_pinctrl by pin control device name. - Pass bool type usage variable to port_setup help function. - Separate long bit operations into several lines and add comments. - Use debugfs to output all GPIO request information. - Avoid to set drvdata to NULL - Add explanation to function adi_gpio_init_int() - Call gpiochip_add_pin_range() in gpio device probe function to register range cross reference between gpio device and pin control device. - Remove the reference to pin control device from the gpio_port struct. Remove the reference list to gpio device from the adi_pinctrl struct. Replace the global adi_pinctrl list with adi_gpio_port_list. Walk through the gpio list to do power suspend and resume operations. - Remove the global GPIO base from struct adi_pinctrl, define pin base in the platform data for each GPIO port device. - Initialize adi_pinctrl_setup in arch_initcall(). - print the status of triggers, whether it is in GPIO mode, if it is flagged to be used as IRQ, etc in adi_pin_dbg_show(). - Create the plug-in subdrivers to hold the pinctrl soc data for bf54x and bf60x. Add soc data into struct adi_pinctrl. Initialize the soc data in pin controller probe function. Get the pin groups and functions via the soc data reference. v4-changes: - remove useless system_state checking. - replace dev_err with dev_warn in both irq and gpio pin cases. - comment on relationship between irq type and invert operation. - It is not necessary to check the reservation mode of the requested pin in IRQ chip operation. Remove the reservation map. - Use existing gpio/pinctrl subsystem debugfs files. Remove pinctrl-adi2 driver specific debugfs output. - Add linkport group and function information for bf60x. - Separate uart and ctsrts pins into 2 groups. - Separate APAPI and alternative ATAPI pins into 2 groups. Signed-off-by: Sonic Zhang Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 17 + drivers/pinctrl/Makefile | 3 + drivers/pinctrl/pinctrl-adi2-bf54x.c | 592 ++++++++++++++ drivers/pinctrl/pinctrl-adi2-bf60x.c | 522 ++++++++++++ drivers/pinctrl/pinctrl-adi2.c | 1183 ++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-adi2.h | 75 ++ include/linux/platform_data/pinctrl-adi2.h | 40 + 7 files changed, 2432 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-adi2-bf54x.c create mode 100644 drivers/pinctrl/pinctrl-adi2-bf60x.c create mode 100644 drivers/pinctrl/pinctrl-adi2.c create mode 100644 drivers/pinctrl/pinctrl-adi2.h create mode 100644 include/linux/platform_data/pinctrl-adi2.h (limited to 'include') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index b6e864e8c9e8..f45a21c57e0e 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -49,6 +49,23 @@ config PINCTRL_AB8505 bool "AB8505 pin controller driver" depends on PINCTRL_ABX500 && ARCH_U8500 +config PINCTRL_ADI2 + bool "ADI pin controller driver" + select PINMUX + select IRQ_DOMAIN + help + This is the pin controller and gpio driver for ADI BF54x, BF60x and + future processors. This option is selected automatically when specific + machine and arch are selected to build. + +config PINCTRL_BF54x + def_bool y if BF54x + select PINCTRL_ADI2 + +config PINCTRL_BF60x + def_bool y if BF60x + select PINCTRL_ADI2 + config PINCTRL_AT91 bool "AT91 pinctrl driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 496d9bf9e1b9..bbeb98086495 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -14,6 +14,9 @@ obj-$(CONFIG_PINCTRL_AB8500) += pinctrl-ab8500.o obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o +obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o +obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o +obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o diff --git a/drivers/pinctrl/pinctrl-adi2-bf54x.c b/drivers/pinctrl/pinctrl-adi2-bf54x.c new file mode 100644 index 000000000000..ea9d9ab9cda1 --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi2-bf54x.c @@ -0,0 +1,592 @@ +/* + * Pinctrl Driver for ADI GPIO2 controller + * + * Copyright 2007-2013 Analog Devices Inc. + * + * Licensed under the GPLv2 or later + */ + +#include +#include "pinctrl-adi2.h" + +static const struct pinctrl_pin_desc adi_pads[] = { + PINCTRL_PIN(0, "PA0"), + PINCTRL_PIN(1, "PA1"), + PINCTRL_PIN(2, "PA2"), + PINCTRL_PIN(3, "PG3"), + PINCTRL_PIN(4, "PA4"), + PINCTRL_PIN(5, "PA5"), + PINCTRL_PIN(6, "PA6"), + PINCTRL_PIN(7, "PA7"), + PINCTRL_PIN(8, "PA8"), + PINCTRL_PIN(9, "PA9"), + PINCTRL_PIN(10, "PA10"), + PINCTRL_PIN(11, "PA11"), + PINCTRL_PIN(12, "PA12"), + PINCTRL_PIN(13, "PA13"), + PINCTRL_PIN(14, "PA14"), + PINCTRL_PIN(15, "PA15"), + PINCTRL_PIN(16, "PB0"), + PINCTRL_PIN(17, "PB1"), + PINCTRL_PIN(18, "PB2"), + PINCTRL_PIN(19, "PB3"), + PINCTRL_PIN(20, "PB4"), + PINCTRL_PIN(21, "PB5"), + PINCTRL_PIN(22, "PB6"), + PINCTRL_PIN(23, "PB7"), + PINCTRL_PIN(24, "PB8"), + PINCTRL_PIN(25, "PB9"), + PINCTRL_PIN(26, "PB10"), + PINCTRL_PIN(27, "PB11"), + PINCTRL_PIN(28, "PB12"), + PINCTRL_PIN(29, "PB13"), + PINCTRL_PIN(30, "PB14"), + PINCTRL_PIN(32, "PC0"), + PINCTRL_PIN(33, "PC1"), + PINCTRL_PIN(34, "PC2"), + PINCTRL_PIN(35, "PC3"), + PINCTRL_PIN(36, "PC4"), + PINCTRL_PIN(37, "PC5"), + PINCTRL_PIN(38, "PC6"), + PINCTRL_PIN(39, "PC7"), + PINCTRL_PIN(40, "PC8"), + PINCTRL_PIN(41, "PC9"), + PINCTRL_PIN(42, "PC10"), + PINCTRL_PIN(43, "PC11"), + PINCTRL_PIN(44, "PC12"), + PINCTRL_PIN(45, "PC13"), + PINCTRL_PIN(48, "PD0"), + PINCTRL_PIN(49, "PD1"), + PINCTRL_PIN(50, "PD2"), + PINCTRL_PIN(51, "PD3"), + PINCTRL_PIN(52, "PD4"), + PINCTRL_PIN(53, "PD5"), + PINCTRL_PIN(54, "PD6"), + PINCTRL_PIN(55, "PD7"), + PINCTRL_PIN(56, "PD8"), + PINCTRL_PIN(57, "PD9"), + PINCTRL_PIN(58, "PD10"), + PINCTRL_PIN(59, "PD11"), + PINCTRL_PIN(60, "PD12"), + PINCTRL_PIN(61, "PD13"), + PINCTRL_PIN(62, "PD14"), + PINCTRL_PIN(63, "PD15"), + PINCTRL_PIN(64, "PE0"), + PINCTRL_PIN(65, "PE1"), + PINCTRL_PIN(66, "PE2"), + PINCTRL_PIN(67, "PE3"), + PINCTRL_PIN(68, "PE4"), + PINCTRL_PIN(69, "PE5"), + PINCTRL_PIN(70, "PE6"), + PINCTRL_PIN(71, "PE7"), + PINCTRL_PIN(72, "PE8"), + PINCTRL_PIN(73, "PE9"), + PINCTRL_PIN(74, "PE10"), + PINCTRL_PIN(75, "PE11"), + PINCTRL_PIN(76, "PE12"), + PINCTRL_PIN(77, "PE13"), + PINCTRL_PIN(78, "PE14"), + PINCTRL_PIN(79, "PE15"), + PINCTRL_PIN(80, "PF0"), + PINCTRL_PIN(81, "PF1"), + PINCTRL_PIN(82, "PF2"), + PINCTRL_PIN(83, "PF3"), + PINCTRL_PIN(84, "PF4"), + PINCTRL_PIN(85, "PF5"), + PINCTRL_PIN(86, "PF6"), + PINCTRL_PIN(87, "PF7"), + PINCTRL_PIN(88, "PF8"), + PINCTRL_PIN(89, "PF9"), + PINCTRL_PIN(90, "PF10"), + PINCTRL_PIN(91, "PF11"), + PINCTRL_PIN(92, "PF12"), + PINCTRL_PIN(93, "PF13"), + PINCTRL_PIN(94, "PF14"), + PINCTRL_PIN(95, "PF15"), + PINCTRL_PIN(96, "PG0"), + PINCTRL_PIN(97, "PG1"), + PINCTRL_PIN(98, "PG2"), + PINCTRL_PIN(99, "PG3"), + PINCTRL_PIN(100, "PG4"), + PINCTRL_PIN(101, "PG5"), + PINCTRL_PIN(102, "PG6"), + PINCTRL_PIN(103, "PG7"), + PINCTRL_PIN(104, "PG8"), + PINCTRL_PIN(105, "PG9"), + PINCTRL_PIN(106, "PG10"), + PINCTRL_PIN(107, "PG11"), + PINCTRL_PIN(108, "PG12"), + PINCTRL_PIN(109, "PG13"), + PINCTRL_PIN(110, "PG14"), + PINCTRL_PIN(111, "PG15"), + PINCTRL_PIN(112, "PH0"), + PINCTRL_PIN(113, "PH1"), + PINCTRL_PIN(114, "PH2"), + PINCTRL_PIN(115, "PH3"), + PINCTRL_PIN(116, "PH4"), + PINCTRL_PIN(117, "PH5"), + PINCTRL_PIN(118, "PH6"), + PINCTRL_PIN(119, "PH7"), + PINCTRL_PIN(120, "PH8"), + PINCTRL_PIN(121, "PH9"), + PINCTRL_PIN(122, "PH10"), + PINCTRL_PIN(123, "PH11"), + PINCTRL_PIN(124, "PH12"), + PINCTRL_PIN(125, "PH13"), + PINCTRL_PIN(128, "PI0"), + PINCTRL_PIN(129, "PI1"), + PINCTRL_PIN(130, "PI2"), + PINCTRL_PIN(131, "PI3"), + PINCTRL_PIN(132, "PI4"), + PINCTRL_PIN(133, "PI5"), + PINCTRL_PIN(134, "PI6"), + PINCTRL_PIN(135, "PI7"), + PINCTRL_PIN(136, "PI8"), + PINCTRL_PIN(137, "PI9"), + PINCTRL_PIN(138, "PI10"), + PINCTRL_PIN(139, "PI11"), + PINCTRL_PIN(140, "PI12"), + PINCTRL_PIN(141, "PI13"), + PINCTRL_PIN(142, "PI14"), + PINCTRL_PIN(143, "PI15"), + PINCTRL_PIN(144, "PJ0"), + PINCTRL_PIN(145, "PJ1"), + PINCTRL_PIN(146, "PJ2"), + PINCTRL_PIN(147, "PJ3"), + PINCTRL_PIN(148, "PJ4"), + PINCTRL_PIN(149, "PJ5"), + PINCTRL_PIN(150, "PJ6"), + PINCTRL_PIN(151, "PJ7"), + PINCTRL_PIN(152, "PJ8"), + PINCTRL_PIN(153, "PJ9"), + PINCTRL_PIN(154, "PJ10"), + PINCTRL_PIN(155, "PJ11"), + PINCTRL_PIN(156, "PJ12"), + PINCTRL_PIN(157, "PJ13"), +}; + +static const unsigned uart0_pins[] = { + GPIO_PE7, GPIO_PE8, +}; + +static const unsigned uart1_pins[] = { + GPIO_PH0, GPIO_PH1, +}; + +static const unsigned uart1_ctsrts_pins[] = { + GPIO_PE9, GPIO_PE10, +}; + +static const unsigned uart2_pins[] = { + GPIO_PB4, GPIO_PB5, +}; + +static const unsigned uart3_pins[] = { + GPIO_PB6, GPIO_PB7, +}; + +static const unsigned uart3_ctsrts_pins[] = { + GPIO_PB2, GPIO_PB3, +}; + +static const unsigned rsi0_pins[] = { + GPIO_PC8, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, GPIO_PC13, +}; + +static const unsigned spi0_pins[] = { + GPIO_PE0, GPIO_PE1, GPIO_PE2, +}; + +static const unsigned spi1_pins[] = { + GPIO_PG8, GPIO_PG9, GPIO_PG10, +}; + +static const unsigned twi0_pins[] = { + GPIO_PE14, GPIO_PE15, +}; + +static const unsigned twi1_pins[] = { + GPIO_PB0, GPIO_PB1, +}; + +static const unsigned rotary_pins[] = { + GPIO_PH4, GPIO_PH3, GPIO_PH5, +}; + +static const unsigned can0_pins[] = { + GPIO_PG13, GPIO_PG12, +}; + +static const unsigned can1_pins[] = { + GPIO_PG14, GPIO_PG15, +}; + +static const unsigned smc0_pins[] = { + GPIO_PH8, GPIO_PH9, GPIO_PH10, GPIO_PH11, GPIO_PH12, GPIO_PH13, + GPIO_PI0, GPIO_PI1, GPIO_PI2, GPIO_PI3, GPIO_PI4, GPIO_PI5, GPIO_PI6, + GPIO_PI7, GPIO_PI8, GPIO_PI9, GPIO_PI10, GPIO_PI11, + GPIO_PI12, GPIO_PI13, GPIO_PI14, GPIO_PI15, +}; + +static const unsigned sport0_pins[] = { + GPIO_PC0, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC6, GPIO_PC7, +}; + +static const unsigned sport1_pins[] = { + GPIO_PD0, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD6, GPIO_PD7, +}; + +static const unsigned sport2_pins[] = { + GPIO_PA0, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA6, GPIO_PA7, +}; + +static const unsigned sport3_pins[] = { + GPIO_PA8, GPIO_PA10, GPIO_PA11, GPIO_PA12, GPIO_PA14, GPIO_PA15, +}; + +static const unsigned ppi0_8b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF13, GPIO_PG0, GPIO_PG1, GPIO_PG2, +}; + +static const unsigned ppi0_16b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, + GPIO_PF13, GPIO_PF14, GPIO_PF15, + GPIO_PG0, GPIO_PG1, GPIO_PG2, +}; + +static const unsigned ppi0_24b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, + GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PD0, GPIO_PD1, GPIO_PD2, + GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PG3, GPIO_PG4, + GPIO_PG0, GPIO_PG1, GPIO_PG2, +}; + +static const unsigned ppi1_8b_pins[] = { + GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6, + GPIO_PD7, GPIO_PE11, GPIO_PE12, GPIO_PE13, +}; + +static const unsigned ppi1_16b_pins[] = { + GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6, + GPIO_PD7, GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12, + GPIO_PD13, GPIO_PD14, GPIO_PD15, + GPIO_PE11, GPIO_PE12, GPIO_PE13, +}; + +static const unsigned ppi2_8b_pins[] = { + GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12, + GPIO_PD13, GPIO_PD14, GPIO_PD15, + GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3, +}; + +static const unsigned atapi_pins[] = { + GPIO_PH2, GPIO_PJ3, GPIO_PJ4, GPIO_PJ5, GPIO_PJ6, + GPIO_PJ7, GPIO_PJ8, GPIO_PJ9, GPIO_PJ10, +}; + +static const unsigned atapi_alter_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, + GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PG2, GPIO_PG3, GPIO_PG4, +}; + +static const unsigned nfc0_pins[] = { + GPIO_PJ1, GPIO_PJ2, +}; + +static const unsigned keys_4x4_pins[] = { + GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, + GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15, +}; + +static const unsigned keys_8x8_pins[] = { + GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, + GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15, + GPIO_PE0, GPIO_PE1, GPIO_PE2, GPIO_PE3, + GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, +}; + +static const struct adi_pin_group adi_pin_groups[] = { + ADI_PIN_GROUP("uart0grp", uart0_pins), + ADI_PIN_GROUP("uart1grp", uart1_pins), + ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins), + ADI_PIN_GROUP("uart2grp", uart2_pins), + ADI_PIN_GROUP("uart3grp", uart3_pins), + ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins), + ADI_PIN_GROUP("rsi0grp", rsi0_pins), + ADI_PIN_GROUP("spi0grp", spi0_pins), + ADI_PIN_GROUP("spi1grp", spi1_pins), + ADI_PIN_GROUP("twi0grp", twi0_pins), + ADI_PIN_GROUP("twi1grp", twi1_pins), + ADI_PIN_GROUP("rotarygrp", rotary_pins), + ADI_PIN_GROUP("can0grp", can0_pins), + ADI_PIN_GROUP("can1grp", can1_pins), + ADI_PIN_GROUP("smc0grp", smc0_pins), + ADI_PIN_GROUP("sport0grp", sport0_pins), + ADI_PIN_GROUP("sport1grp", sport1_pins), + ADI_PIN_GROUP("sport2grp", sport2_pins), + ADI_PIN_GROUP("sport3grp", sport3_pins), + ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins), + ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins), + ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins), + ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins), + ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins), + ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins), + ADI_PIN_GROUP("atapigrp", atapi_pins), + ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins), + ADI_PIN_GROUP("nfc0grp", nfc0_pins), + ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins), + ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins), +}; + +static const unsigned short uart0_mux[] = { + P_UART0_TX, P_UART0_RX, + 0 +}; + +static const unsigned short uart1_mux[] = { + P_UART1_TX, P_UART1_RX, + 0 +}; + +static const unsigned short uart1_ctsrts_mux[] = { + P_UART1_RTS, P_UART1_CTS, + 0 +}; + +static const unsigned short uart2_mux[] = { + P_UART2_TX, P_UART2_RX, + 0 +}; + +static const unsigned short uart3_mux[] = { + P_UART3_TX, P_UART3_RX, + 0 +}; + +static const unsigned short uart3_ctsrts_mux[] = { + P_UART3_RTS, P_UART3_CTS, + 0 +}; + +static const unsigned short rsi0_mux[] = { + P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD, + 0 +}; + +static const unsigned short spi0_mux[] = { + P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0 +}; + +static const unsigned short spi1_mux[] = { + P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0 +}; + +static const unsigned short twi0_mux[] = { + P_TWI0_SCL, P_TWI0_SDA, 0 +}; + +static const unsigned short twi1_mux[] = { + P_TWI1_SCL, P_TWI1_SDA, 0 +}; + +static const unsigned short rotary_mux[] = { + P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0 +}; + +static const unsigned short sport0_mux[] = { + P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, + P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0 +}; + +static const unsigned short sport1_mux[] = { + P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, + P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0 +}; + +static const unsigned short sport2_mux[] = { + P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, + P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0 +}; + +static const unsigned short sport3_mux[] = { + P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, + P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0 +}; + +static const unsigned short can0_mux[] = { + P_CAN0_RX, P_CAN0_TX, 0 +}; + +static const unsigned short can1_mux[] = { + P_CAN1_RX, P_CAN1_TX, 0 +}; + +static const unsigned short smc0_mux[] = { + P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12, + P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21, + P_A22, P_A23, P_A24, P_A25, P_NOR_CLK, 0, +}; + +static const unsigned short ppi0_8b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi0_16b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, + P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi0_24b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, + P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, + P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19, + P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi1_8b_mux[] = { + P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, + P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, + P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, + 0, +}; + +static const unsigned short ppi1_16b_mux[] = { + P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, + P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, + P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11, + P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15, + P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, + 0, +}; + +static const unsigned short ppi2_8b_mux[] = { + P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, + P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, + P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, + 0, +}; + +static const unsigned short atapi_mux[] = { + P_ATAPI_RESET, P_ATAPI_DIOR, P_ATAPI_DIOW, P_ATAPI_CS0, P_ATAPI_CS1, + P_ATAPI_DMACK, P_ATAPI_DMARQ, P_ATAPI_INTRQ, P_ATAPI_IORDY, +}; + +static const unsigned short atapi_alter_mux[] = { + P_ATAPI_D0A, P_ATAPI_D1A, P_ATAPI_D2A, P_ATAPI_D3A, P_ATAPI_D4A, + P_ATAPI_D5A, P_ATAPI_D6A, P_ATAPI_D7A, P_ATAPI_D8A, P_ATAPI_D9A, + P_ATAPI_D10A, P_ATAPI_D11A, P_ATAPI_D12A, P_ATAPI_D13A, P_ATAPI_D14A, + P_ATAPI_D15A, P_ATAPI_A0A, P_ATAPI_A1A, P_ATAPI_A2A, + 0 +}; + +static const unsigned short nfc0_mux[] = { + P_NAND_CE, P_NAND_RB, + 0 +}; + +static const unsigned short keys_4x4_mux[] = { + P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0, + P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0, + 0 +}; + +static const unsigned short keys_8x8_mux[] = { + P_KEY_ROW7, P_KEY_ROW6, P_KEY_ROW5, P_KEY_ROW4, + P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0, + P_KEY_COL7, P_KEY_COL6, P_KEY_COL5, P_KEY_COL4, + P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0, + 0 +}; + +static const char * const uart0grp[] = { "uart0grp" }; +static const char * const uart1grp[] = { "uart1grp" }; +static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" }; +static const char * const uart2grp[] = { "uart2grp" }; +static const char * const uart3grp[] = { "uart3grp" }; +static const char * const uart3ctsrtsgrp[] = { "uart3ctsrtsgrp" }; +static const char * const rsi0grp[] = { "rsi0grp" }; +static const char * const spi0grp[] = { "spi0grp" }; +static const char * const spi1grp[] = { "spi1grp" }; +static const char * const twi0grp[] = { "twi0grp" }; +static const char * const twi1grp[] = { "twi1grp" }; +static const char * const rotarygrp[] = { "rotarygrp" }; +static const char * const can0grp[] = { "can0grp" }; +static const char * const can1grp[] = { "can1grp" }; +static const char * const smc0grp[] = { "smc0grp" }; +static const char * const sport0grp[] = { "sport0grp" }; +static const char * const sport1grp[] = { "sport1grp" }; +static const char * const sport2grp[] = { "sport2grp" }; +static const char * const sport3grp[] = { "sport3grp" }; +static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" }; +static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" }; +static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" }; +static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" }; +static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" }; +static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" }; +static const char * const atapigrp[] = { "atapigrp" }; +static const char * const atapialtergrp[] = { "atapialtergrp" }; +static const char * const nfc0grp[] = { "nfc0grp" }; +static const char * const keys_4x4grp[] = { "keys_4x4grp" }; +static const char * const keys_8x8grp[] = { "keys_8x8grp" }; + +static const struct adi_pmx_func adi_pmx_functions[] = { + ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux), + ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux), + ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux), + ADI_PMX_FUNCTION("uart2", uart2grp, uart2_mux), + ADI_PMX_FUNCTION("uart3", uart3grp, uart3_mux), + ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp, uart3_ctsrts_mux), + ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux), + ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux), + ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux), + ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux), + ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux), + ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux), + ADI_PMX_FUNCTION("can0", can0grp, can0_mux), + ADI_PMX_FUNCTION("can1", can1grp, can1_mux), + ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux), + ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux), + ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux), + ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux), + ADI_PMX_FUNCTION("sport3", sport3grp, sport3_mux), + ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux), + ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux), + ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux), + ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux), + ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux), + ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux), + ADI_PMX_FUNCTION("atapi", atapigrp, atapi_mux), + ADI_PMX_FUNCTION("atapi_alter", atapialtergrp, atapi_alter_mux), + ADI_PMX_FUNCTION("nfc0", nfc0grp, nfc0_mux), + ADI_PMX_FUNCTION("keys_4x4", keys_4x4grp, keys_4x4_mux), + ADI_PMX_FUNCTION("keys_8x8", keys_8x8grp, keys_8x8_mux), +}; + +static const struct adi_pinctrl_soc_data adi_bf54x_soc = { + .functions = adi_pmx_functions, + .nfunctions = ARRAY_SIZE(adi_pmx_functions), + .groups = adi_pin_groups, + .ngroups = ARRAY_SIZE(adi_pin_groups), + .pins = adi_pads, + .npins = ARRAY_SIZE(adi_pads), +}; + +void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc) +{ + *soc = &adi_bf54x_soc; +} diff --git a/drivers/pinctrl/pinctrl-adi2-bf60x.c b/drivers/pinctrl/pinctrl-adi2-bf60x.c new file mode 100644 index 000000000000..e90cb80c8d0b --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi2-bf60x.c @@ -0,0 +1,522 @@ +/* + * Pinctrl Driver for ADI GPIO2 controller + * + * Copyright 2007-2013 Analog Devices Inc. + * + * Licensed under the GPLv2 or later + */ + +#include +#include "pinctrl-adi2.h" + +static const struct pinctrl_pin_desc adi_pads[] = { + PINCTRL_PIN(0, "PA0"), + PINCTRL_PIN(1, "PA1"), + PINCTRL_PIN(2, "PA2"), + PINCTRL_PIN(3, "PG3"), + PINCTRL_PIN(4, "PA4"), + PINCTRL_PIN(5, "PA5"), + PINCTRL_PIN(6, "PA6"), + PINCTRL_PIN(7, "PA7"), + PINCTRL_PIN(8, "PA8"), + PINCTRL_PIN(9, "PA9"), + PINCTRL_PIN(10, "PA10"), + PINCTRL_PIN(11, "PA11"), + PINCTRL_PIN(12, "PA12"), + PINCTRL_PIN(13, "PA13"), + PINCTRL_PIN(14, "PA14"), + PINCTRL_PIN(15, "PA15"), + PINCTRL_PIN(16, "PB0"), + PINCTRL_PIN(17, "PB1"), + PINCTRL_PIN(18, "PB2"), + PINCTRL_PIN(19, "PB3"), + PINCTRL_PIN(20, "PB4"), + PINCTRL_PIN(21, "PB5"), + PINCTRL_PIN(22, "PB6"), + PINCTRL_PIN(23, "PB7"), + PINCTRL_PIN(24, "PB8"), + PINCTRL_PIN(25, "PB9"), + PINCTRL_PIN(26, "PB10"), + PINCTRL_PIN(27, "PB11"), + PINCTRL_PIN(28, "PB12"), + PINCTRL_PIN(29, "PB13"), + PINCTRL_PIN(30, "PB14"), + PINCTRL_PIN(31, "PB15"), + PINCTRL_PIN(32, "PC0"), + PINCTRL_PIN(33, "PC1"), + PINCTRL_PIN(34, "PC2"), + PINCTRL_PIN(35, "PC3"), + PINCTRL_PIN(36, "PC4"), + PINCTRL_PIN(37, "PC5"), + PINCTRL_PIN(38, "PC6"), + PINCTRL_PIN(39, "PC7"), + PINCTRL_PIN(40, "PC8"), + PINCTRL_PIN(41, "PC9"), + PINCTRL_PIN(42, "PC10"), + PINCTRL_PIN(43, "PC11"), + PINCTRL_PIN(44, "PC12"), + PINCTRL_PIN(45, "PC13"), + PINCTRL_PIN(46, "PC14"), + PINCTRL_PIN(47, "PC15"), + PINCTRL_PIN(48, "PD0"), + PINCTRL_PIN(49, "PD1"), + PINCTRL_PIN(50, "PD2"), + PINCTRL_PIN(51, "PD3"), + PINCTRL_PIN(52, "PD4"), + PINCTRL_PIN(53, "PD5"), + PINCTRL_PIN(54, "PD6"), + PINCTRL_PIN(55, "PD7"), + PINCTRL_PIN(56, "PD8"), + PINCTRL_PIN(57, "PD9"), + PINCTRL_PIN(58, "PD10"), + PINCTRL_PIN(59, "PD11"), + PINCTRL_PIN(60, "PD12"), + PINCTRL_PIN(61, "PD13"), + PINCTRL_PIN(62, "PD14"), + PINCTRL_PIN(63, "PD15"), + PINCTRL_PIN(64, "PE0"), + PINCTRL_PIN(65, "PE1"), + PINCTRL_PIN(66, "PE2"), + PINCTRL_PIN(67, "PE3"), + PINCTRL_PIN(68, "PE4"), + PINCTRL_PIN(69, "PE5"), + PINCTRL_PIN(70, "PE6"), + PINCTRL_PIN(71, "PE7"), + PINCTRL_PIN(72, "PE8"), + PINCTRL_PIN(73, "PE9"), + PINCTRL_PIN(74, "PE10"), + PINCTRL_PIN(75, "PE11"), + PINCTRL_PIN(76, "PE12"), + PINCTRL_PIN(77, "PE13"), + PINCTRL_PIN(78, "PE14"), + PINCTRL_PIN(79, "PE15"), + PINCTRL_PIN(80, "PF0"), + PINCTRL_PIN(81, "PF1"), + PINCTRL_PIN(82, "PF2"), + PINCTRL_PIN(83, "PF3"), + PINCTRL_PIN(84, "PF4"), + PINCTRL_PIN(85, "PF5"), + PINCTRL_PIN(86, "PF6"), + PINCTRL_PIN(87, "PF7"), + PINCTRL_PIN(88, "PF8"), + PINCTRL_PIN(89, "PF9"), + PINCTRL_PIN(90, "PF10"), + PINCTRL_PIN(91, "PF11"), + PINCTRL_PIN(92, "PF12"), + PINCTRL_PIN(93, "PF13"), + PINCTRL_PIN(94, "PF14"), + PINCTRL_PIN(95, "PF15"), + PINCTRL_PIN(96, "PG0"), + PINCTRL_PIN(97, "PG1"), + PINCTRL_PIN(98, "PG2"), + PINCTRL_PIN(99, "PG3"), + PINCTRL_PIN(100, "PG4"), + PINCTRL_PIN(101, "PG5"), + PINCTRL_PIN(102, "PG6"), + PINCTRL_PIN(103, "PG7"), + PINCTRL_PIN(104, "PG8"), + PINCTRL_PIN(105, "PG9"), + PINCTRL_PIN(106, "PG10"), + PINCTRL_PIN(107, "PG11"), + PINCTRL_PIN(108, "PG12"), + PINCTRL_PIN(109, "PG13"), + PINCTRL_PIN(110, "PG14"), + PINCTRL_PIN(111, "PG15"), +}; + +static const unsigned uart0_pins[] = { + GPIO_PD7, GPIO_PD8, +}; + +static const unsigned uart0_ctsrts_pins[] = { + GPIO_PD9, GPIO_PD10, +}; + +static const unsigned uart1_pins[] = { + GPIO_PG15, GPIO_PG14, +}; + +static const unsigned uart1_ctsrts_pins[] = { + GPIO_PG10, GPIO_PG13, +}; + +static const unsigned rsi0_pins[] = { + GPIO_PG3, GPIO_PG2, GPIO_PG0, GPIO_PE15, GPIO_PG5, GPIO_PG6, +}; + +static const unsigned eth0_pins[] = { + GPIO_PC6, GPIO_PC7, GPIO_PC2, GPIO_PC0, GPIO_PC3, GPIO_PC1, + GPIO_PB13, GPIO_PD6, GPIO_PC5, GPIO_PC4, GPIO_PB14, GPIO_PB15, +}; + +static const unsigned eth1_pins[] = { + GPIO_PE10, GPIO_PE11, GPIO_PG3, GPIO_PG0, GPIO_PG2, GPIO_PE15, + GPIO_PG5, GPIO_PE12, GPIO_PE13, GPIO_PE14, GPIO_PG6, GPIO_PC9, +}; + +static const unsigned spi0_pins[] = { + GPIO_PD4, GPIO_PD2, GPIO_PD3, +}; + +static const unsigned spi1_pins[] = { + GPIO_PD5, GPIO_PD14, GPIO_PD13, +}; + +static const unsigned twi0_pins[] = { +}; + +static const unsigned twi1_pins[] = { +}; + +static const unsigned rotary_pins[] = { + GPIO_PG7, GPIO_PG11, GPIO_PG12, +}; + +static const unsigned can0_pins[] = { + GPIO_PG1, GPIO_PG4, +}; + +static const unsigned smc0_pins[] = { + GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, + GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PB2, GPIO_PA10, GPIO_PA11, + GPIO_PB3, GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB6, + GPIO_PB7, GPIO_PB8, GPIO_PB10, GPIO_PB11, GPIO_PB0, +}; + +static const unsigned sport0_pins[] = { + GPIO_PB5, GPIO_PB4, GPIO_PB9, GPIO_PB8, GPIO_PB7, GPIO_PB11, +}; + +static const unsigned sport1_pins[] = { + GPIO_PE2, GPIO_PE5, GPIO_PD15, GPIO_PE4, GPIO_PE3, GPIO_PE1, +}; + +static const unsigned sport2_pins[] = { + GPIO_PG4, GPIO_PG1, GPIO_PG9, GPIO_PG10, GPIO_PG7, GPIO_PB12, +}; + +static const unsigned ppi0_8b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF13, GPIO_PF14, GPIO_PF15, + GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9, +}; + +static const unsigned ppi0_16b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, + GPIO_PF13, GPIO_PF14, GPIO_PF15, + GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9, +}; + +static const unsigned ppi0_24b_pins[] = { + GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, + GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, + GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PE0, GPIO_PE1, GPIO_PE2, + GPIO_PE3, GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, GPIO_PE8, + GPIO_PE9, GPIO_PD12, GPIO_PD15, +}; + +static const unsigned ppi1_8b_pins[] = { + GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6, + GPIO_PC7, GPIO_PC8, GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6, +}; + +static const unsigned ppi1_16b_pins[] = { + GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6, + GPIO_PC7, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, + GPIO_PC13, GPIO_PC14, GPIO_PC15, + GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6, +}; + +static const unsigned ppi2_8b_pins[] = { + GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, + GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3, +}; + +static const unsigned ppi2_16b_pins[] = { + GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, + GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, GPIO_PA12, + GPIO_PA13, GPIO_PA14, GPIO_PA15, + GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3, +}; + +static const unsigned lp0_pins[] = { + GPIO_PB0, GPIO_PB1, GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, + GPIO_PA4, GPIO_PA5, GPIO_PA6, GPIO_PA7, +}; + +static const unsigned lp1_pins[] = { + GPIO_PB3, GPIO_PB2, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, + GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, +}; + +static const unsigned lp2_pins[] = { + GPIO_PE6, GPIO_PE7, GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, + GPIO_PF4, GPIO_PF5, GPIO_PF6, GPIO_PF7, +}; + +static const unsigned lp3_pins[] = { + GPIO_PE9, GPIO_PE8, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, + GPIO_PF12, GPIO_PF13, GPIO_PF14, GPIO_PF15, +}; + +static const struct adi_pin_group adi_pin_groups[] = { + ADI_PIN_GROUP("uart0grp", uart0_pins), + ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins), + ADI_PIN_GROUP("uart1grp", uart1_pins), + ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins), + ADI_PIN_GROUP("rsi0grp", rsi0_pins), + ADI_PIN_GROUP("eth0grp", eth0_pins), + ADI_PIN_GROUP("eth1grp", eth1_pins), + ADI_PIN_GROUP("spi0grp", spi0_pins), + ADI_PIN_GROUP("spi1grp", spi1_pins), + ADI_PIN_GROUP("twi0grp", twi0_pins), + ADI_PIN_GROUP("twi1grp", twi1_pins), + ADI_PIN_GROUP("rotarygrp", rotary_pins), + ADI_PIN_GROUP("can0grp", can0_pins), + ADI_PIN_GROUP("smc0grp", smc0_pins), + ADI_PIN_GROUP("sport0grp", sport0_pins), + ADI_PIN_GROUP("sport1grp", sport1_pins), + ADI_PIN_GROUP("sport2grp", sport2_pins), + ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins), + ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins), + ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins), + ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins), + ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins), + ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins), + ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins), + ADI_PIN_GROUP("lp0grp", lp0_pins), + ADI_PIN_GROUP("lp1grp", lp1_pins), + ADI_PIN_GROUP("lp2grp", lp2_pins), + ADI_PIN_GROUP("lp3grp", lp3_pins), +}; + +static const unsigned short uart0_mux[] = { + P_UART0_TX, P_UART0_RX, + 0 +}; + +static const unsigned short uart0_ctsrts_mux[] = { + P_UART0_RTS, P_UART0_CTS, + 0 +}; + +static const unsigned short uart1_mux[] = { + P_UART1_TX, P_UART1_RX, + 0 +}; + +static const unsigned short uart1_ctsrts_mux[] = { + P_UART1_RTS, P_UART1_CTS, + 0 +}; + +static const unsigned short rsi0_mux[] = { + P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, + P_RSI_CMD, P_RSI_CLK, 0 +}; + +static const unsigned short eth0_mux[] = P_RMII0; +static const unsigned short eth1_mux[] = P_RMII1; + +static const unsigned short spi0_mux[] = { + P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0 +}; + +static const unsigned short spi1_mux[] = { + P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0 +}; + +static const unsigned short twi0_mux[] = { + P_TWI0_SCL, P_TWI0_SDA, 0 +}; + +static const unsigned short twi1_mux[] = { + P_TWI1_SCL, P_TWI1_SDA, 0 +}; + +static const unsigned short rotary_mux[] = { + P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0 +}; + +static const unsigned short sport0_mux[] = { + P_SPORT0_ACLK, P_SPORT0_AFS, P_SPORT0_AD0, P_SPORT0_BCLK, + P_SPORT0_BFS, P_SPORT0_BD0, 0, +}; + +static const unsigned short sport1_mux[] = { + P_SPORT1_ACLK, P_SPORT1_AFS, P_SPORT1_AD0, P_SPORT1_BCLK, + P_SPORT1_BFS, P_SPORT1_BD0, 0, +}; + +static const unsigned short sport2_mux[] = { + P_SPORT2_ACLK, P_SPORT2_AFS, P_SPORT2_AD0, P_SPORT2_BCLK, + P_SPORT2_BFS, P_SPORT2_BD0, 0, +}; + +static const unsigned short can0_mux[] = { + P_CAN0_RX, P_CAN0_TX, 0 +}; + +static const unsigned short smc0_mux[] = { + P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12, + P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21, + P_A22, P_A23, P_A24, P_A25, P_NORCK, 0, +}; + +static const unsigned short ppi0_8b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi0_16b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, + P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi0_24b_mux[] = { + P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, + P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, + P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, + P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, + P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19, + P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, + P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, + 0, +}; + +static const unsigned short ppi1_8b_mux[] = { + P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, + P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, + P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, + 0, +}; + +static const unsigned short ppi1_16b_mux[] = { + P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, + P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, + P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11, + P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15, + P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, + 0, +}; + +static const unsigned short ppi2_8b_mux[] = { + P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, + P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, + P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, + 0, +}; + +static const unsigned short ppi2_16b_mux[] = { + P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, + P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, + P_PPI2_D8, P_PPI2_D9, P_PPI2_D10, P_PPI2_D11, + P_PPI2_D12, P_PPI2_D13, P_PPI2_D14, P_PPI2_D15, + P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, + 0, +}; + +static const unsigned short lp0_mux[] = { + P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2, + P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7, + 0 +}; + +static const unsigned short lp1_mux[] = { + P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2, + P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7, + 0 +}; + +static const unsigned short lp2_mux[] = { + P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2, + P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7, + 0 +}; + +static const unsigned short lp3_mux[] = { + P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2, + P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7, + 0 +}; + +static const char * const uart0grp[] = { "uart0grp" }; +static const char * const uart0ctsrtsgrp[] = { "uart0ctsrtsgrp" }; +static const char * const uart1grp[] = { "uart1grp" }; +static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" }; +static const char * const rsi0grp[] = { "rsi0grp" }; +static const char * const eth0grp[] = { "eth0grp" }; +static const char * const eth1grp[] = { "eth1grp" }; +static const char * const spi0grp[] = { "spi0grp" }; +static const char * const spi1grp[] = { "spi1grp" }; +static const char * const twi0grp[] = { "twi0grp" }; +static const char * const twi1grp[] = { "twi1grp" }; +static const char * const rotarygrp[] = { "rotarygrp" }; +static const char * const can0grp[] = { "can0grp" }; +static const char * const smc0grp[] = { "smc0grp" }; +static const char * const sport0grp[] = { "sport0grp" }; +static const char * const sport1grp[] = { "sport1grp" }; +static const char * const sport2grp[] = { "sport2grp" }; +static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" }; +static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" }; +static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" }; +static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" }; +static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" }; +static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" }; +static const char * const ppi2_16bgrp[] = { "ppi2_16bgrp" }; +static const char * const lp0grp[] = { "lp0grp" }; +static const char * const lp1grp[] = { "lp1grp" }; +static const char * const lp2grp[] = { "lp2grp" }; +static const char * const lp3grp[] = { "lp3grp" }; + +static const struct adi_pmx_func adi_pmx_functions[] = { + ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux), + ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp, uart0_ctsrts_mux), + ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux), + ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux), + ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux), + ADI_PMX_FUNCTION("eth0", eth0grp, eth0_mux), + ADI_PMX_FUNCTION("eth1", eth1grp, eth1_mux), + ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux), + ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux), + ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux), + ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux), + ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux), + ADI_PMX_FUNCTION("can0", can0grp, can0_mux), + ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux), + ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux), + ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux), + ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux), + ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux), + ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux), + ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux), + ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux), + ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux), + ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux), + ADI_PMX_FUNCTION("ppi2_16b", ppi2_16bgrp, ppi2_16b_mux), + ADI_PMX_FUNCTION("lp0", lp0grp, lp0_mux), + ADI_PMX_FUNCTION("lp1", lp1grp, lp1_mux), + ADI_PMX_FUNCTION("lp2", lp2grp, lp2_mux), + ADI_PMX_FUNCTION("lp3", lp3grp, lp3_mux), +}; + +static const struct adi_pinctrl_soc_data adi_bf60x_soc = { + .functions = adi_pmx_functions, + .nfunctions = ARRAY_SIZE(adi_pmx_functions), + .groups = adi_pin_groups, + .ngroups = ARRAY_SIZE(adi_pin_groups), + .pins = adi_pads, + .npins = ARRAY_SIZE(adi_pads), +}; + +void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc) +{ + *soc = &adi_bf60x_soc; +} diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c new file mode 100644 index 000000000000..7a24e59b4138 --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi2.c @@ -0,0 +1,1183 @@ +/* + * Pinctrl Driver for ADI GPIO2 controller + * + * Copyright 2007-2013 Analog Devices Inc. + * + * Licensed under the GPLv2 or later + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pinctrl-adi2.h" +#include "core.h" + +/* +According to the BF54x HRM, pint means "pin interrupt". +http://www.analog.com/static/imported-files/processor_manuals/ADSP-BF54x_hwr_rev1.2.pdf + +ADSP-BF54x processor Blackfin processors have four SIC interrupt chan- +nels dedicated to pin interrupt purposes. These channels are managed by +four hardware blocks, called PINT0, PINT1, PINT2, and PINT3. Every PINTx +block can sense to up to 32 pins. While PINT0 and PINT1 can sense the +pins of port A and port B, PINT2 and PINT3 manage all the pins from port +C to port J as shown in Figure 9-2. + +n BF54x HRM: +The ten GPIO ports are subdivided into 8-bit half ports, resulting in lower and +upper half 8-bit units. The PINTx_ASSIGN registers control the 8-bit multi- +plexers shown in Figure 9-3. Lower half units of eight pins can be +forwarded to either byte 0 or byte 2 of either associated PINTx block. +Upper half units can be forwarded to either byte 1 or byte 3 of the pin +interrupt blocks, without further restrictions. + +All MMR registers in the pin interrupt module are 32 bits wide. To simply the +mapping logic, this driver only maps a 16-bit gpio port to the upper or lower +16 bits of a PINTx block. You can find the Figure 9-3 on page 583. + +Each IRQ domain is binding to a GPIO bank device. 2 GPIO bank devices can map +to one PINT device. Two in "struct gpio_pint" are used to ease the PINT +interrupt handler. + +The GPIO bank mapping to the lower 16 bits of the PINT device set its IRQ +domain pointer in domain[0]. The IRQ domain pointer of the other bank is set +to domain[1]. PINT interrupt handler adi_gpio_handle_pint_irq() finds out +the current domain pointer according to whether the interrupt request mask +is in lower 16 bits (domain[0]) or upper 16bits (domain[1]). + +A PINT device is not part of a GPIO port device in Blackfin. Multiple GPIO +port devices can be mapped to the same PINT device. + +*/ + +static LIST_HEAD(adi_pint_list); +static LIST_HEAD(adi_gpio_port_list); + +#define DRIVER_NAME "pinctrl-adi2" + +#define PINT_HI_OFFSET 16 + +/** + * struct gpio_port_saved - GPIO port registers that should be saved between + * power suspend and resume operations. + * + * @fer: PORTx_FER register + * @data: PORTx_DATA register + * @dir: PORTx_DIR register + * @inen: PORTx_INEN register + * @mux: PORTx_MUX register + */ +struct gpio_port_saved { + u16 fer; + u16 data; + u16 dir; + u16 inen; + u32 mux; +}; + +/** + * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO + * banks can be mapped into one Pin interrupt controller. + * + * @node: All gpio_pint instances are added to a global list. + * @base: PINT device register base address + * @irq: IRQ of the PINT device, it is the parent IRQ of all + * GPIO IRQs mapping to this device. + * @domain: [0] irq domain of the gpio port, whose hardware interrupts are + * mapping to the low 16-bit of the pint registers. + * [1] irq domain of the gpio port, whose hardware interrupts are + * mapping to the high 16-bit of the pint registers. + * @regs: address pointer to the PINT device + * @map_count: No more than 2 GPIO banks can be mapped to this PINT device. + * @lock: This lock make sure the irq_chip operations to one PINT device + * for different GPIO interrrupts are atomic. + * @pint_map_port: Set up the mapping between one PINT device and + * multiple GPIO banks. + */ +struct gpio_pint { + struct list_head node; + void __iomem *base; + int irq; + struct irq_domain *domain[2]; + struct gpio_pint_regs *regs; + struct adi_pm_pint_save saved_data; + int map_count; + spinlock_t lock; + + int (*pint_map_port)(struct gpio_pint *pint, bool assign, + u8 map, struct irq_domain *domain); +}; + +/** + * ADI pin controller + * + * @dev: a pointer back to containing device + * @pctl: the pinctrl device + * @soc: SoC data for this specific chip + */ +struct adi_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl; + const struct adi_pinctrl_soc_data *soc; +}; + +/** + * struct gpio_port - GPIO bank device. Multiple ADI GPIO banks can be mapped + * into one pin interrupt controller. + * + * @node: All gpio_port instances are added to a list. + * @base: GPIO bank device register base address + * @irq_base: base IRQ of the GPIO bank device + * @width: PIN number of the GPIO bank device + * @regs: address pointer to the GPIO bank device + * @saved_data: registers that should be saved between PM operations. + * @dev: device structure of this GPIO bank + * @pint: GPIO PINT device that this GPIO bank mapped to + * @pint_map: GIOP bank mapping code in PINT device + * @pint_assign: The 32-bit PINT registers can be divided into 2 parts. A + * GPIO bank can be mapped into either low 16 bits[0] or high 16 + * bits[1] of each PINT register. + * @lock: This lock make sure the irq_chip operations to one PINT device + * for different GPIO interrrupts are atomic. + * @chip: abstract a GPIO controller + * @domain: The irq domain owned by the GPIO port. + * @rsvmap: Reservation map array for each pin in the GPIO bank + */ +struct gpio_port { + struct list_head node; + void __iomem *base; + unsigned int irq_base; + unsigned int width; + struct gpio_port_t *regs; + struct gpio_port_saved saved_data; + struct device *dev; + + struct gpio_pint *pint; + u8 pint_map; + bool pint_assign; + + spinlock_t lock; + struct gpio_chip chip; + struct irq_domain *domain; +}; + +static inline u8 pin_to_offset(struct pinctrl_gpio_range *range, unsigned pin) +{ + return pin - range->pin_base; +} + +static inline u32 hwirq_to_pintbit(struct gpio_port *port, int hwirq) +{ + return port->pint_assign ? BIT(hwirq) << PINT_HI_OFFSET : BIT(hwirq); +} + +static struct gpio_pint *find_gpio_pint(unsigned id) +{ + struct gpio_pint *pint; + int i = 0; + + list_for_each_entry(pint, &adi_pint_list, node) { + if (id == i) + return pint; + i++; + } + + return NULL; +} + +static inline void port_setup(struct gpio_port *port, unsigned offset, + bool use_for_gpio) +{ + struct gpio_port_t *regs = port->regs; + + if (use_for_gpio) + writew(readw(®s->port_fer) & ~BIT(offset), + ®s->port_fer); + else + writew(readw(®s->port_fer) | BIT(offset), ®s->port_fer); +} + +static inline void portmux_setup(struct gpio_port *port, unsigned offset, + unsigned short function) +{ + struct gpio_port_t *regs = port->regs; + u32 pmux; + + pmux = readl(®s->port_mux); + + /* The function field of each pin has 2 consecutive bits in + * the mux register. + */ + pmux &= ~(0x3 << (2 * offset)); + pmux |= (function & 0x3) << (2 * offset); + + writel(pmux, ®s->port_mux); +} + +static inline u16 get_portmux(struct gpio_port *port, unsigned offset) +{ + struct gpio_port_t *regs = port->regs; + u32 pmux = readl(®s->port_mux); + + /* The function field of each pin has 2 consecutive bits in + * the mux register. + */ + return pmux >> (2 * offset) & 0x3; +} + +static void adi_gpio_ack_irq(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { + if (readl(®s->invert_set) & pintbit) + writel(pintbit, ®s->invert_clear); + else + writel(pintbit, ®s->invert_set); + } + + writel(pintbit, ®s->request); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void adi_gpio_mask_ack_irq(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { + if (readl(®s->invert_set) & pintbit) + writel(pintbit, ®s->invert_clear); + else + writel(pintbit, ®s->invert_set); + } + + writel(pintbit, ®s->request); + writel(pintbit, ®s->mask_clear); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void adi_gpio_mask_irq(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void adi_gpio_unmask_irq(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); +} + +static unsigned int adi_gpio_irq_startup(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + + if (!port) { + dev_err(port->dev, "GPIO IRQ %d :Not exist\n", d->irq); + return -ENODEV; + } + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + port_setup(port, d->hwirq, true); + writew(BIT(d->hwirq), &port->regs->dir_clear); + writew(readw(&port->regs->inen) | BIT(d->hwirq), &port->regs->inen); + + writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); + + return 0; +} + +static void adi_gpio_irq_shutdown(struct irq_data *d) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *regs = port->pint->regs; + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); + + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); +} + +static int adi_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + unsigned long flags; + struct gpio_port *port = irq_data_get_irq_chip_data(d); + struct gpio_pint_regs *pint_regs = port->pint->regs; + unsigned pintmask; + unsigned int irq = d->irq; + int ret = 0; + char buf[16]; + + if (!port) { + dev_err(port->dev, "GPIO IRQ %d :Not exist\n", irq); + return -ENODEV; + } + + pintmask = hwirq_to_pintbit(port, d->hwirq); + + spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->pint->lock, flags); + + /* In case of interrupt autodetect, set irq type to edge sensitive. */ + if (type == IRQ_TYPE_PROBE) + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + snprintf(buf, 16, "gpio-irq%d", irq); + port_setup(port, d->hwirq, true); + } else + goto out; + + /* The GPIO interrupt is triggered only when its input value + * transfer from 0 to 1. So, invert the input value if the + * irq type is low or falling + */ + if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) + writel(pintmask, &pint_regs->invert_set); + else + writel(pintmask, &pint_regs->invert_clear); + + /* In edge sensitive case, if the input value of the requested irq + * is already 1, invert it. + */ + if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { + if (gpio_get_value(port->chip.base + d->hwirq)) + writel(pintmask, &pint_regs->invert_set); + else + writel(pintmask, &pint_regs->invert_clear); + } + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + writel(pintmask, &pint_regs->edge_set); + __irq_set_handler_locked(irq, handle_edge_irq); + } else { + writel(pintmask, &pint_regs->edge_clear); + __irq_set_handler_locked(irq, handle_level_irq); + } + +out: + spin_unlock_irqrestore(&port->pint->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); + + return ret; +} + +#ifdef CONFIG_PM +static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) +{ + struct gpio_port *port = irq_data_get_irq_chip_data(d); + + if (!port || !port->pint || port->pint->irq != d->irq) + return -EINVAL; + +#ifndef SEC_GCTL + adi_internal_set_wake(port->pint->irq, state); +#endif + + return 0; +} + +static int adi_pint_suspend(void) +{ + struct gpio_pint *pint; + + list_for_each_entry(pint, &adi_pint_list, node) { + writel(0xffffffff, &pint->regs->mask_clear); + pint->saved_data.assign = readl(&pint->regs->assign); + pint->saved_data.edge_set = readl(&pint->regs->edge_set); + pint->saved_data.invert_set = readl(&pint->regs->invert_set); + } + + return 0; +} + +static void adi_pint_resume(void) +{ + struct gpio_pint *pint; + + list_for_each_entry(pint, &adi_pint_list, node) { + writel(pint->saved_data.assign, &pint->regs->assign); + writel(pint->saved_data.edge_set, &pint->regs->edge_set); + writel(pint->saved_data.invert_set, &pint->regs->invert_set); + } +} + +static int adi_gpio_suspend(void) +{ + struct gpio_port *port; + + list_for_each_entry(port, &adi_gpio_port_list, node) { + port->saved_data.fer = readw(&port->regs->port_fer); + port->saved_data.mux = readl(&port->regs->port_mux); + port->saved_data.data = readw(&port->regs->data); + port->saved_data.inen = readw(&port->regs->inen); + port->saved_data.dir = readw(&port->regs->dir_set); + } + + return adi_pint_suspend(); +} + +static void adi_gpio_resume(void) +{ + struct gpio_port *port; + + adi_pint_resume(); + + list_for_each_entry(port, &adi_gpio_port_list, node) { + writel(port->saved_data.mux, &port->regs->port_mux); + writew(port->saved_data.fer, &port->regs->port_fer); + writew(port->saved_data.inen, &port->regs->inen); + writew(port->saved_data.data & port->saved_data.dir, + &port->regs->data_set); + writew(port->saved_data.dir, &port->regs->dir_set); + } + +} + +static struct syscore_ops gpio_pm_syscore_ops = { + .suspend = adi_gpio_suspend, + .resume = adi_gpio_resume, +}; +#else /* CONFIG_PM */ +#define adi_gpio_set_wake NULL +#endif /* CONFIG_PM */ + +#ifdef CONFIG_IRQ_PREFLOW_FASTEOI +static inline void preflow_handler(struct irq_desc *desc) +{ + if (desc->preflow_handler) + desc->preflow_handler(&desc->irq_data); +} +#else +static inline void preflow_handler(struct irq_desc *desc) { } +#endif + +static void adi_gpio_handle_pint_irq(unsigned int inta_irq, + struct irq_desc *desc) +{ + u32 request; + u32 level_mask, hwirq; + bool umask = false; + struct gpio_pint *pint = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct gpio_pint_regs *regs = pint->regs; + struct irq_domain *domain; + + preflow_handler(desc); + chained_irq_enter(chip, desc); + + request = readl(®s->request); + level_mask = readl(®s->edge_set) & request; + + hwirq = 0; + domain = pint->domain[0]; + while (request) { + /* domain pointer need to be changed only once at IRQ 16 when + * we go through IRQ requests from bit 0 to bit 31. + */ + if (hwirq == PINT_HI_OFFSET) + domain = pint->domain[1]; + + if (request & 1) { + if (level_mask & BIT(hwirq)) { + umask = true; + chained_irq_exit(chip, desc); + } + generic_handle_irq(irq_find_mapping(domain, + hwirq % PINT_HI_OFFSET)); + } + + hwirq++; + request >>= 1; + } + + if (!umask) + chained_irq_exit(chip, desc); +} + +static struct irq_chip adi_gpio_irqchip = { + .name = "GPIO", + .irq_ack = adi_gpio_ack_irq, + .irq_mask = adi_gpio_mask_irq, + .irq_mask_ack = adi_gpio_mask_ack_irq, + .irq_unmask = adi_gpio_unmask_irq, + .irq_disable = adi_gpio_mask_irq, + .irq_enable = adi_gpio_unmask_irq, + .irq_set_type = adi_gpio_irq_type, + .irq_startup = adi_gpio_irq_startup, + .irq_shutdown = adi_gpio_irq_shutdown, + .irq_set_wake = adi_gpio_set_wake, +}; + +static int adi_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->soc->ngroups; +} + +static const char *adi_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->soc->groups[selector].name; +} + +static int adi_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + const unsigned **pins, + unsigned *num_pins) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + *pins = pinctrl->soc->groups[selector].pins; + *num_pins = pinctrl->soc->groups[selector].num; + return 0; +} + +static struct pinctrl_ops adi_pctrl_ops = { + .get_groups_count = adi_get_groups_count, + .get_group_name = adi_get_group_name, + .get_group_pins = adi_get_group_pins, +}; + +static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + struct gpio_port *port; + struct pinctrl_gpio_range *range; + unsigned long flags; + unsigned short *mux, pin; + + mux = (unsigned short *)pinctrl->soc->functions[selector].mux; + + while (*mux) { + pin = P_IDENT(*mux); + + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + if (range == NULL) /* should not happen */ + return -ENODEV; + + port = container_of(range->gc, struct gpio_port, chip); + + spin_lock_irqsave(&port->lock, flags); + + portmux_setup(port, pin_to_offset(range, pin), + P_FUNCT2MUX(*mux)); + port_setup(port, pin_to_offset(range, pin), false); + mux++; + + spin_unlock_irqrestore(&port->lock, flags); + } + + return 0; +} + +static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + struct gpio_port *port; + struct pinctrl_gpio_range *range; + unsigned long flags; + unsigned short *mux, pin; + + mux = (unsigned short *)pinctrl->soc->functions[selector].mux; + + while (*mux) { + pin = P_IDENT(*mux); + + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + if (range == NULL) /* should not happen */ + return; + + port = container_of(range->gc, struct gpio_port, chip); + + spin_lock_irqsave(&port->lock, flags); + + port_setup(port, pin_to_offset(range, pin), true); + mux++; + + spin_unlock_irqrestore(&port->lock, flags); + } +} + +static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->soc->nfunctions; +} + +static const char *adi_pinmux_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->soc->functions[selector].name; +} + +static int adi_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pinctrl->soc->functions[selector].groups; + *num_groups = pinctrl->soc->functions[selector].num_groups; + return 0; +} + +static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned pin) +{ + struct gpio_port *port; + unsigned long flags; + u8 offset; + + port = container_of(range->gc, struct gpio_port, chip); + offset = pin_to_offset(range, pin); + + spin_lock_irqsave(&port->lock, flags); + + port_setup(port, offset, true); + + spin_unlock_irqrestore(&port->lock, flags); + + return 0; +} + +static struct pinmux_ops adi_pinmux_ops = { + .enable = adi_pinmux_enable, + .disable = adi_pinmux_disable, + .get_functions_count = adi_pinmux_get_funcs_count, + .get_function_name = adi_pinmux_get_func_name, + .get_function_groups = adi_pinmux_get_groups, + .gpio_request_enable = adi_pinmux_request_gpio, +}; + + +static struct pinctrl_desc adi_pinmux_desc = { + .name = DRIVER_NAME, + .pctlops = &adi_pctrl_ops, + .pmxops = &adi_pinmux_ops, + .owner = THIS_MODULE, +}; + +static int adi_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(chip->base + offset); +} + +static void adi_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(chip->base + offset); +} + +static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_port *port; + unsigned long flags; + + port = container_of(chip, struct gpio_port, chip); + + spin_lock_irqsave(&port->lock, flags); + + writew(BIT(offset), &port->regs->dir_clear); + writew(readw(&port->regs->inen) | BIT(offset), &port->regs->inen); + + spin_unlock_irqrestore(&port->lock, flags); + + return 0; +} + +static void adi_gpio_set_value(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct gpio_port *port = container_of(chip, struct gpio_port, chip); + struct gpio_port_t *regs = port->regs; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + if (value) + writew(1 << offset, ®s->data_set); + else + writew(1 << offset, ®s->data_clear); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static int adi_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct gpio_port *port = container_of(chip, struct gpio_port, chip); + struct gpio_port_t *regs = port->regs; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + writew(readw(®s->inen) & ~(1 << offset), ®s->inen); + adi_gpio_set_value(chip, offset, value); + writew(1 << offset, ®s->dir_set); + + spin_unlock_irqrestore(&port->lock, flags); + + return 0; +} + +static int adi_gpio_get_value(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_port *port = container_of(chip, struct gpio_port, chip); + struct gpio_port_t *regs = port->regs; + unsigned long flags; + int ret; + + spin_lock_irqsave(&port->lock, flags); + + ret = !!(readw(®s->data) & BIT(offset)); + + spin_unlock_irqrestore(&port->lock, flags); + + return ret; +} + +static int adi_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_port *port = container_of(chip, struct gpio_port, chip); + + if (port->irq_base >= 0) + return irq_find_mapping(port->domain, offset); + else + return irq_create_mapping(port->domain, offset); +} + +static int adi_pint_map_port(struct gpio_pint *pint, bool assign, u8 map, + struct irq_domain *domain) +{ + struct gpio_pint_regs *regs = pint->regs; + u32 map_mask; + + if (pint->map_count > 1) + return -EINVAL; + + pint->map_count++; + + /* The map_mask of each gpio port is a 16-bit duplicate + * of the 8-bit map. It can be set to either high 16 bits or low + * 16 bits of the pint assignment register. + */ + map_mask = (map << 8) | map; + if (assign) { + map_mask <<= PINT_HI_OFFSET; + writel((readl(®s->assign) & 0xFFFF) | map_mask, + ®s->assign); + } else + writel((readl(®s->assign) & 0xFFFF0000) | map_mask, + ®s->assign); + + pint->domain[assign] = domain; + + return 0; +} + +static int adi_gpio_pint_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct gpio_pint *pint; + + pint = devm_kzalloc(dev, sizeof(struct gpio_pint), GFP_KERNEL); + if (!pint) { + dev_err(dev, "Memory alloc failed\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Invalid mem resource\n"); + return -ENODEV; + } + + if (!devm_request_mem_region(dev, res->start, resource_size(res), + pdev->name)) { + dev_err(dev, "Region already claimed\n"); + return -EBUSY; + } + + pint->base = devm_ioremap(dev, res->start, resource_size(res)); + if (!pint->base) { + dev_err(dev, "Could not ioremap\n"); + return -ENOMEM; + } + + pint->regs = (struct gpio_pint_regs *)pint->base; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "Invalid IRQ resource\n"); + return -ENODEV; + } + + spin_lock_init(&pint->lock); + + pint->irq = res->start; + pint->pint_map_port = adi_pint_map_port; + platform_set_drvdata(pdev, pint); + + irq_set_chained_handler(pint->irq, adi_gpio_handle_pint_irq); + irq_set_handler_data(pint->irq, pint); + + list_add_tail(&pint->node, &adi_pint_list); + + return 0; +} + +static int adi_gpio_pint_remove(struct platform_device *pdev) +{ + struct gpio_pint *pint = platform_get_drvdata(pdev); + + list_del(&pint->node); + irq_set_handler(pint->irq, handle_simple_irq); + + return 0; +} + +static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct gpio_port *port = d->host_data; + + if (!port) + return -EINVAL; + + irq_set_chip_data(irq, port); + irq_set_chip_and_handler(irq, &adi_gpio_irqchip, + handle_level_irq); + + return 0; +} + +const struct irq_domain_ops adi_gpio_irq_domain_ops = { + .map = adi_gpio_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int adi_gpio_init_int(struct gpio_port *port) +{ + struct device_node *node = port->dev->of_node; + struct gpio_pint *pint = port->pint; + int ret; + + port->domain = irq_domain_add_linear(node, port->width, + &adi_gpio_irq_domain_ops, port); + if (!port->domain) { + dev_err(port->dev, "Failed to create irqdomain\n"); + return -ENOSYS; + } + + /* According to BF54x and BF60x HRM, pin interrupt devices are not + * part of the GPIO port device. in GPIO interrupt mode, the GPIO + * pins of multiple port devices can be routed into one pin interrupt + * device. The mapping can be configured by setting pint assignment + * register with the mapping value of different GPIO port. This is + * done via function pint_map_port(). + */ + ret = pint->pint_map_port(port->pint, port->pint_assign, + port->pint_map, port->domain); + if (ret) + return ret; + + if (port->irq_base >= 0) { + ret = irq_create_strict_mappings(port->domain, port->irq_base, + 0, port->width); + if (ret) { + dev_err(port->dev, "Couldn't associate to domain\n"); + return ret; + } + } + + return 0; +} + +#define DEVNAME_SIZE 16 + +static int adi_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct adi_pinctrl_gpio_platform_data *pdata; + struct resource *res; + struct gpio_port *port; + char pinctrl_devname[DEVNAME_SIZE]; + static int gpio; + int ret = 0, ret1; + + pdata = dev->platform_data; + if (!pdata) + return -EINVAL; + + port = devm_kzalloc(dev, sizeof(struct gpio_port), GFP_KERNEL); + if (!port) { + dev_err(dev, "Memory alloc failed\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Invalid mem resource\n"); + return -ENODEV; + } + + if (!devm_request_mem_region(dev, res->start, resource_size(res), + pdev->name)) { + dev_err(dev, "Region already claimed\n"); + return -EBUSY; + } + + port->base = devm_ioremap(dev, res->start, resource_size(res)); + if (!port->base) { + dev_err(dev, "Could not ioremap\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) + port->irq_base = -1; + else + port->irq_base = res->start; + + port->width = pdata->port_width; + port->dev = dev; + port->regs = (struct gpio_port_t *)port->base; + port->pint_assign = pdata->pint_assign; + port->pint_map = pdata->pint_map; + + port->pint = find_gpio_pint(pdata->pint_id); + if (port->pint) { + ret = adi_gpio_init_int(port); + if (ret) + return ret; + } + + spin_lock_init(&port->lock); + + platform_set_drvdata(pdev, port); + + port->chip.label = "adi-gpio"; + port->chip.direction_input = adi_gpio_direction_input; + port->chip.get = adi_gpio_get_value; + port->chip.direction_output = adi_gpio_direction_output; + port->chip.set = adi_gpio_set_value; + port->chip.request = adi_gpio_request; + port->chip.free = adi_gpio_free; + port->chip.to_irq = adi_gpio_to_irq; + if (pdata->port_gpio_base > 0) + port->chip.base = pdata->port_gpio_base; + else + port->chip.base = gpio; + port->chip.ngpio = port->width; + gpio = port->chip.base + port->width; + + ret = gpiochip_add(&port->chip); + if (ret) { + dev_err(&pdev->dev, "Fail to add GPIO chip.\n"); + goto out_remove_domain; + } + + /* Add gpio pin range */ + snprintf(pinctrl_devname, DEVNAME_SIZE, "pinctrl-adi2.%d", + pdata->pinctrl_id); + pinctrl_devname[DEVNAME_SIZE - 1] = 0; + ret = gpiochip_add_pin_range(&port->chip, pinctrl_devname, + 0, pdata->port_pin_base, port->width); + if (ret) { + dev_err(&pdev->dev, "Fail to add pin range to %s.\n", + pinctrl_devname); + goto out_remove_gpiochip; + } + + list_add_tail(&port->node, &adi_gpio_port_list); + + return 0; + +out_remove_gpiochip: + ret1 = gpiochip_remove(&port->chip); +out_remove_domain: + if (port->pint) + irq_domain_remove(port->domain); + + return ret; +} + +static int adi_gpio_remove(struct platform_device *pdev) +{ + struct gpio_port *port = platform_get_drvdata(pdev); + int ret; + u8 offset; + + list_del(&port->node); + gpiochip_remove_pin_ranges(&port->chip); + ret = gpiochip_remove(&port->chip); + if (port->pint) { + for (offset = 0; offset < port->width; offset++) + irq_dispose_mapping(irq_find_mapping(port->domain, + offset)); + irq_domain_remove(port->domain); + } + + return ret; +} + +static int adi_pinctrl_probe(struct platform_device *pdev) +{ + struct adi_pinctrl *pinctrl; + + pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL); + if (!pinctrl) + return -ENOMEM; + + pinctrl->dev = &pdev->dev; + + adi_pinctrl_soc_init(&pinctrl->soc); + + adi_pinmux_desc.pins = pinctrl->soc->pins; + adi_pinmux_desc.npins = pinctrl->soc->npins; + + /* Now register the pin controller and all pins it handles */ + pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl); + if (!pinctrl->pctl) { + dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n"); + return -EINVAL; + } + + platform_set_drvdata(pdev, pinctrl); + + return 0; +} + +static int adi_pinctrl_remove(struct platform_device *pdev) +{ + struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev); + + pinctrl_unregister(pinctrl->pctl); + + return 0; +} + +static struct platform_driver adi_pinctrl_driver = { + .probe = adi_pinctrl_probe, + .remove = adi_pinctrl_remove, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static struct platform_driver adi_gpio_pint_driver = { + .probe = adi_gpio_pint_probe, + .remove = adi_gpio_pint_remove, + .driver = { + .name = "adi-gpio-pint", + }, +}; + +static struct platform_driver adi_gpio_driver = { + .probe = adi_gpio_probe, + .remove = adi_gpio_remove, + .driver = { + .name = "adi-gpio", + }, +}; + +static int __init adi_pinctrl_setup(void) +{ + int ret; + + ret = platform_driver_register(&adi_pinctrl_driver); + if (ret) + return ret; + + ret = platform_driver_register(&adi_gpio_pint_driver); + if (ret) + goto pint_error; + + ret = platform_driver_register(&adi_gpio_driver); + if (ret) + goto gpio_error; + +#ifdef CONFIG_PM + register_syscore_ops(&gpio_pm_syscore_ops); +#endif + return ret; +gpio_error: + platform_driver_unregister(&adi_gpio_pint_driver); +pint_error: + platform_driver_unregister(&adi_pinctrl_driver); + + return ret; +} +arch_initcall(adi_pinctrl_setup); + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("ADI gpio2 pin control driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-adi2.h b/drivers/pinctrl/pinctrl-adi2.h new file mode 100644 index 000000000000..1f06f8df1fa3 --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi2.h @@ -0,0 +1,75 @@ +/* + * Pinctrl Driver for ADI GPIO2 controller + * + * Copyright 2007-2013 Analog Devices Inc. + * + * Licensed under the GPLv2 or later + */ + +#ifndef PINCTRL_PINCTRL_ADI2_H +#define PINCTRL_PINCTRL_ADI2_H + +#include + + /** + * struct adi_pin_group - describes a pin group + * @name: the name of this pin group + * @pins: an array of pins + * @num: the number of pins in this array + */ +struct adi_pin_group { + const char *name; + const unsigned *pins; + const unsigned num; +}; + +#define ADI_PIN_GROUP(n, p) \ + { \ + .name = n, \ + .pins = p, \ + .num = ARRAY_SIZE(p), \ + } + + /** + * struct adi_pmx_func - describes function mux setting of pin groups + * @name: the name of this function mux setting + * @groups: an array of pin groups + * @num_groups: the number of pin groups in this array + * @mux: the function mux setting array, end by zero + */ +struct adi_pmx_func { + const char *name; + const char * const *groups; + const unsigned num_groups; + const unsigned short *mux; +}; + +#define ADI_PMX_FUNCTION(n, g, m) \ + { \ + .name = n, \ + .groups = g, \ + .num_groups = ARRAY_SIZE(g), \ + .mux = m, \ + } + +/** + * struct adi_pinctrl_soc_data - ADI pin controller per-SoC configuration + * @functions: The functions supported on this SoC. + * @nfunction: The number of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The number of entries in @groups. + * @pins: An array describing all pins the pin controller affects. + * @npins: The number of entries in @pins. + */ +struct adi_pinctrl_soc_data { + const struct adi_pmx_func *functions; + int nfunctions; + const struct adi_pin_group *groups; + int ngroups; + const struct pinctrl_pin_desc *pins; + int npins; +}; + +void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc); + +#endif /* PINCTRL_PINCTRL_ADI2_H */ diff --git a/include/linux/platform_data/pinctrl-adi2.h b/include/linux/platform_data/pinctrl-adi2.h new file mode 100644 index 000000000000..8f91300617ec --- /dev/null +++ b/include/linux/platform_data/pinctrl-adi2.h @@ -0,0 +1,40 @@ +/* + * Pinctrl Driver for ADI GPIO2 controller + * + * Copyright 2007-2013 Analog Devices Inc. + * + * Licensed under the GPLv2 or later + */ + + +#ifndef PINCTRL_ADI2_H +#define PINCTRL_ADI2_H + +#include +#include + +/** + * struct adi_pinctrl_gpio_platform_data - Pinctrl gpio platform data + * for ADI GPIO2 device. + * + * @port_gpio_base: Optional global GPIO index of the GPIO bank. + * 0 means driver decides. + * @port_pin_base: Pin index of the pin controller device. + * @port_width: PIN number of the GPIO bank device + * @pint_id: GPIO PINT device id that this GPIO bank should map to. + * @pint_assign: The 32-bit GPIO PINT registers can be divided into 2 parts. A + * GPIO bank can be mapped into either low 16 bits[0] or high 16 + * bits[1] of each PINT register. + * @pint_map: GIOP bank mapping code in PINT device + */ +struct adi_pinctrl_gpio_platform_data { + unsigned int port_gpio_base; + unsigned int port_pin_base; + unsigned int port_width; + u8 pinctrl_id; + u8 pint_id; + bool pint_assign; + u8 pint_map; +}; + +#endif -- cgit From 5d4e7e8db0544ec53025383bac49a3328affdad3 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 13 Sep 2013 11:40:01 +0300 Subject: Bluetooth: Add synchronization train parameters reading support This patch adds support for reading the synchronization train parameters for controllers that support the feature. Since the feature is detectable through the local features page 2, which is retreived only in stage 3 of the HCI init sequence, there is no other option than to add a fourth stage to the init sequence. For now the patch doesn't yet add storing of the parameters, but it is nevertheless convenient to have around to see what kind of parameters various controllers use by default (analyzable e.g. with the btmon user space tool). Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 52bd2488ff4a..f7197a0ac759 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -835,6 +835,8 @@ struct hci_cp_write_le_host_supported { __u8 simul; } __packed; +#define HCI_OP_READ_SYNC_TRAIN_PARAMS 0x0c77 + #define HCI_OP_READ_LOCAL_VERSION 0x1001 struct hci_rp_read_local_version { __u8 status; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b24d2fa02c2f..ea542e07b2e9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -648,6 +648,15 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) } } +static void hci_init4_req(struct hci_request *req, unsigned long opt) +{ + struct hci_dev *hdev = req->hdev; + + /* Check for Synchronization Train support */ + if (hdev->features[2][0] & 0x04) + hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); +} + static int __hci_init(struct hci_dev *hdev) { int err; @@ -667,7 +676,11 @@ static int __hci_init(struct hci_dev *hdev) if (err < 0) return err; - return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); + err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); + if (err < 0) + return err; + + return __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); } static void hci_scan_req(struct hci_request *req, unsigned long opt) -- cgit From d62e6d67a776fe6a0a725e2835e4f9e16e8db512 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 13 Sep 2013 11:40:02 +0300 Subject: Bluetooth: Add event mask page 2 setting support For those controller that support the HCI_Set_Event_Mask_Page_2 command we should include it in the init sequence. This patch implements sending of the command and enables the events in it based on supported features (currently only CSB is checked). Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index f7197a0ac759..22d6e664612a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -823,6 +823,8 @@ struct hci_rp_read_inq_rsp_tx_power { __s8 tx_power; } __packed; +#define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63 + #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 struct hci_rp_read_flow_control_mode { __u8 status; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ea542e07b2e9..3d9f02b2f010 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -607,6 +607,34 @@ static void hci_set_le_support(struct hci_request *req) &cp); } +static void hci_set_event_mask_page_2(struct hci_request *req) +{ + struct hci_dev *hdev = req->hdev; + u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + /* If Connectionless Slave Broadcast master role is supported + * enable all necessary events for it. + */ + if (hdev->features[2][0] & 0x01) { + events[1] |= 0x40; /* Triggered Clock Capture */ + events[1] |= 0x80; /* Synchronization Train Complete */ + events[2] |= 0x10; /* Slave Page Response Timeout */ + events[2] |= 0x20; /* CSB Channel Map Change */ + } + + /* If Connectionless Slave Broadcast slave role is supported + * enable all necessary events for it. + */ + if (hdev->features[2][0] & 0x02) { + events[2] |= 0x01; /* Synchronization Train Received */ + events[2] |= 0x02; /* CSB Receive */ + events[2] |= 0x04; /* CSB Timeout */ + events[2] |= 0x08; /* Truncated Page Complete */ + } + + hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); +} + static void hci_init3_req(struct hci_request *req, unsigned long opt) { struct hci_dev *hdev = req->hdev; @@ -652,6 +680,10 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) { struct hci_dev *hdev = req->hdev; + /* Set event mask page 2 if the HCI command for it is supported */ + if (hdev->commands[22] & 0x04) + hci_set_event_mask_page_2(req); + /* Check for Synchronization Train support */ if (hdev->features[2][0] & 0x04) hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); -- cgit From 35a85ac60618521d41cfdb14f3fbfc8ad7329e9e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 19 Sep 2013 11:13:41 -0700 Subject: drm/i915: Add second slice l3 remapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Certain HSW SKUs have a second bank of L3. This L3 remapping has a separate register set, and interrupt from the first "slice". A slice is simply a term to define some subset of the GPU's l3 cache. This patch implements both the interrupt handler, and ability to communicate with userspace about this second slice. v2: Remove redundant check about non-existent slice. Change warning about interrupts of unknown slices to WARN_ON_ONCE Handle the case where we get 2 slice interrupts concurrently, and switch the tracking of interrupts to be non-destructive (all Ville) Don't enable/mask the second slice parity interrupt for ivb/vlv (even though all docs I can find claim it's rsvd) (Ville + Bryan) Keep BYT excluded from L3 parity v3: Fix the slice = ffs to be decremented by one (found by Ville). When I initially did my testing on the series, I was using 1-based slice counting, so this code was correct. Not sure why my simpler tests that I've been running since then didn't pick it up sooner. Reviewed-by: Ville Syrjälä Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 ++- drivers/gpu/drm/i915/i915_gem.c | 26 +++++----- drivers/gpu/drm/i915/i915_irq.c | 89 +++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_reg.h | 7 +++ drivers/gpu/drm/i915/i915_sysfs.c | 34 ++++++++++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 ++- include/uapi/drm/i915_drm.h | 8 +-- 7 files changed, 117 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b16d47280f9..c6e8df737566 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -917,9 +917,11 @@ struct i915_ums_state { int mm_suspended; }; +#define MAX_L3_SLICES 2 struct intel_l3_parity { - u32 *remap_info; + u32 *remap_info[MAX_L3_SLICES]; struct work_struct error_work; + int which_slice; }; struct i915_gem_mm { @@ -1686,6 +1688,7 @@ struct drm_i915_file_private { #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) #define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) +#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_GPU_CACHE(dev)) #define GT_FREQUENCY_MULTIPLIER 50 @@ -1946,7 +1949,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); -void i915_gem_l3_remap(struct drm_device *dev); +void i915_gem_l3_remap(struct drm_device *dev, int slice); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d00d24f7a976..21a3d69679ee 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4222,16 +4222,15 @@ i915_gem_idle(struct drm_device *dev) return 0; } -void i915_gem_l3_remap(struct drm_device *dev) +void i915_gem_l3_remap(struct drm_device *dev, int slice) { drm_i915_private_t *dev_priv = dev->dev_private; + u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200); + u32 *remap_info = dev_priv->l3_parity.remap_info[slice]; u32 misccpctl; int i; - if (!HAS_L3_GPU_CACHE(dev)) - return; - - if (!dev_priv->l3_parity.remap_info) + if (!HAS_L3_GPU_CACHE(dev) || !remap_info) return; misccpctl = I915_READ(GEN7_MISCCPCTL); @@ -4239,17 +4238,17 @@ void i915_gem_l3_remap(struct drm_device *dev) POSTING_READ(GEN7_MISCCPCTL); for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { - u32 remap = I915_READ(GEN7_L3LOG_BASE + i); - if (remap && remap != dev_priv->l3_parity.remap_info[i/4]) + u32 remap = I915_READ(reg_base + i); + if (remap && remap != remap_info[i/4]) DRM_DEBUG("0x%x was already programmed to %x\n", - GEN7_L3LOG_BASE + i, remap); - if (remap && !dev_priv->l3_parity.remap_info[i/4]) + reg_base + i, remap); + if (remap && !remap_info[i/4]) DRM_DEBUG_DRIVER("Clearing remapped register\n"); - I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->l3_parity.remap_info[i/4]); + I915_WRITE(reg_base + i, remap_info[i/4]); } /* Make sure all the writes land before disabling dop clock gating */ - POSTING_READ(GEN7_L3LOG_BASE); + POSTING_READ(reg_base); I915_WRITE(GEN7_MISCCPCTL, misccpctl); } @@ -4343,7 +4342,7 @@ int i915_gem_init_hw(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret, i; if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) return -EIO; @@ -4362,7 +4361,8 @@ i915_gem_init_hw(struct drm_device *dev) I915_WRITE(GEN7_MSG_CTL, temp); } - i915_gem_l3_remap(dev); + for (i = 0; i < NUM_L3_SLICES(dev); i++) + i915_gem_l3_remap(dev, i); i915_gem_init_swizzling(dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a610f5abcc41..60a7bac4fc3b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -888,9 +888,10 @@ static void ivybridge_parity_work(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, l3_parity.error_work); u32 error_status, row, bank, subbank; - char *parity_event[5]; + char *parity_event[6]; uint32_t misccpctl; unsigned long flags; + uint8_t slice = 0; /* We must turn off DOP level clock gating to access the L3 registers. * In order to prevent a get/put style interface, acquire struct mutex @@ -898,45 +899,64 @@ static void ivybridge_parity_work(struct work_struct *work) */ mutex_lock(&dev_priv->dev->struct_mutex); + /* If we've screwed up tracking, just let the interrupt fire again */ + if (WARN_ON(!dev_priv->l3_parity.which_slice)) + goto out; + misccpctl = I915_READ(GEN7_MISCCPCTL); I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); POSTING_READ(GEN7_MISCCPCTL); - error_status = I915_READ(GEN7_L3CDERRST1); - row = GEN7_PARITY_ERROR_ROW(error_status); - bank = GEN7_PARITY_ERROR_BANK(error_status); - subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); + while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { + u32 reg; - I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | - GEN7_L3CDERRST1_ENABLE); - POSTING_READ(GEN7_L3CDERRST1); + slice--; + if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev))) + break; - I915_WRITE(GEN7_MISCCPCTL, misccpctl); + dev_priv->l3_parity.which_slice &= ~(1<irq_lock, flags); - ilk_enable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); - spin_unlock_irqrestore(&dev_priv->irq_lock, flags); + reg = GEN7_L3CDERRST1 + (slice * 0x200); - mutex_unlock(&dev_priv->dev->struct_mutex); + error_status = I915_READ(reg); + row = GEN7_PARITY_ERROR_ROW(error_status); + bank = GEN7_PARITY_ERROR_BANK(error_status); + subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); + + I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); + POSTING_READ(reg); + + parity_event[0] = I915_L3_PARITY_UEVENT "=1"; + parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); + parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); + parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); + parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); + parity_event[5] = NULL; + + kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, + KOBJ_CHANGE, parity_event); - parity_event[0] = I915_L3_PARITY_UEVENT "=1"; - parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); - parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); - parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); - parity_event[4] = NULL; + DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", + slice, row, bank, subbank); - kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, - KOBJ_CHANGE, parity_event); + kfree(parity_event[4]); + kfree(parity_event[3]); + kfree(parity_event[2]); + kfree(parity_event[1]); + } - DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", - row, bank, subbank); + I915_WRITE(GEN7_MISCCPCTL, misccpctl); - kfree(parity_event[3]); - kfree(parity_event[2]); - kfree(parity_event[1]); +out: + WARN_ON(dev_priv->l3_parity.which_slice); + spin_lock_irqsave(&dev_priv->irq_lock, flags); + ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev)); + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); + + mutex_unlock(&dev_priv->dev->struct_mutex); } -static void ivybridge_parity_error_irq_handler(struct drm_device *dev) +static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -944,9 +964,16 @@ static void ivybridge_parity_error_irq_handler(struct drm_device *dev) return; spin_lock(&dev_priv->irq_lock); - ilk_disable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); + ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev)); spin_unlock(&dev_priv->irq_lock); + iir &= GT_PARITY_ERROR(dev); + if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1) + dev_priv->l3_parity.which_slice |= 1 << 1; + + if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) + dev_priv->l3_parity.which_slice |= 1 << 0; + queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); } @@ -981,8 +1008,8 @@ static void snb_gt_irq_handler(struct drm_device *dev, i915_handle_error(dev, false); } - if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) - ivybridge_parity_error_irq_handler(dev); + if (gt_iir & GT_PARITY_ERROR(dev)) + ivybridge_parity_error_irq_handler(dev, gt_iir); } #define HPD_STORM_DETECT_PERIOD 1000 @@ -2221,8 +2248,8 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) dev_priv->gt_irq_mask = ~0; if (HAS_L3_GPU_CACHE(dev)) { /* L3 parity interrupt is always unmasked. */ - dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; + dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev); + gt_irqs |= GT_PARITY_ERROR(dev); } gt_irqs |= GT_RENDER_USER_INTERRUPT; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index af6f93ca7296..c4f9bef6d073 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -927,6 +927,7 @@ #define GT_BLT_USER_INTERRUPT (1 << 22) #define GT_BSD_CS_ERROR_INTERRUPT (1 << 15) #define GT_BSD_USER_INTERRUPT (1 << 12) +#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */ #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */ #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4) #define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3) @@ -937,6 +938,10 @@ #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ +#define GT_PARITY_ERROR(dev) \ + (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ + IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0) + /* These are all the "old" interrupts */ #define ILK_BSD_USER_INTERRUPT (1<<5) #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) @@ -4747,6 +4752,7 @@ /* IVYBRIDGE DPF */ #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ +#define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */ #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) #define GEN7_PARITY_ERROR_VALID (1<<13) #define GEN7_L3CDERRST1_BANK_MASK (3<<11) @@ -4760,6 +4766,7 @@ #define GEN7_L3CDERRST1_ENABLE (1<<7) #define GEN7_L3LOG_BASE 0xB070 +#define HSW_L3LOG_BASE_SLICE1 0xB270 #define GEN7_L3LOG_SIZE 0x80 #define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 71f6de24444e..3a8bf0c9b5ce 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -119,6 +119,7 @@ i915_l3_read(struct file *filp, struct kobject *kobj, struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; uint32_t misccpctl; + int slice = (int)(uintptr_t)attr->private; int i, ret; count = round_down(count, 4); @@ -134,9 +135,9 @@ i915_l3_read(struct file *filp, struct kobject *kobj, return ret; if (IS_HASWELL(drm_dev)) { - if (dev_priv->l3_parity.remap_info) + if (dev_priv->l3_parity.remap_info[slice]) memcpy(buf, - dev_priv->l3_parity.remap_info + (offset/4), + dev_priv->l3_parity.remap_info[slice] + (offset/4), count); else memset(buf, 0, count); @@ -168,6 +169,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; u32 *temp = NULL; /* Just here to make handling failures easy */ + int slice = (int)(uintptr_t)attr->private; int ret; ret = l3_access_valid(drm_dev, offset); @@ -178,7 +180,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, if (ret) return ret; - if (!dev_priv->l3_parity.remap_info) { + if (!dev_priv->l3_parity.remap_info[slice]) { temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); if (!temp) { mutex_unlock(&drm_dev->struct_mutex); @@ -198,11 +200,11 @@ i915_l3_write(struct file *filp, struct kobject *kobj, * at this point it is left as a TODO. */ if (temp) - dev_priv->l3_parity.remap_info = temp; + dev_priv->l3_parity.remap_info[slice] = temp; - memcpy(dev_priv->l3_parity.remap_info + (offset/4), buf, count); + memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); - i915_gem_l3_remap(drm_dev); + i915_gem_l3_remap(drm_dev, slice); mutex_unlock(&drm_dev->struct_mutex); @@ -214,7 +216,17 @@ static struct bin_attribute dpf_attrs = { .size = GEN7_L3LOG_SIZE, .read = i915_l3_read, .write = i915_l3_write, - .mmap = NULL + .mmap = NULL, + .private = (void *)0 +}; + +static struct bin_attribute dpf_attrs_1 = { + .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)}, + .size = GEN7_L3LOG_SIZE, + .read = i915_l3_read, + .write = i915_l3_write, + .mmap = NULL, + .private = (void *)1 }; static ssize_t gt_cur_freq_mhz_show(struct device *kdev, @@ -525,6 +537,13 @@ void i915_setup_sysfs(struct drm_device *dev) ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); if (ret) DRM_ERROR("l3 parity sysfs setup failed\n"); + + if (NUM_L3_SLICES(dev) > 1) { + ret = device_create_bin_file(&dev->primary->kdev, + &dpf_attrs_1); + if (ret) + DRM_ERROR("l3 parity slice 1 setup failed\n"); + } } ret = 0; @@ -548,6 +567,7 @@ void i915_teardown_sysfs(struct drm_device *dev) sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs); else sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs); + device_remove_bin_file(&dev->primary->kdev, &dpf_attrs_1); device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); #ifdef CONFIG_PM sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 686e5b23481d..958b7d8fea8b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -570,7 +570,7 @@ static int init_render_ring(struct intel_ring_buffer *ring) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); if (HAS_L3_GPU_CACHE(dev)) - I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); + I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); return ret; } @@ -1000,7 +1000,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | - GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); + GT_PARITY_ERROR(dev))); else I915_WRITE_IMR(ring, ~ring->irq_enable_mask); ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); @@ -1020,8 +1020,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, - ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); + I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); else I915_WRITE_IMR(ring, ~0); ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 55bb5729bd78..3a4e97bd8607 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -38,10 +38,10 @@ * * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch * event from the gpu l3 cache. Additional information supplied is ROW, - * BANK, SUBBANK of the affected cacheline. Userspace should keep track of - * these events and if a specific cache-line seems to have a persistent - * error remap it with the l3 remapping tool supplied in intel-gpu-tools. - * The value supplied with the event is always 1. + * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep + * track of these events and if a specific cache-line seems to have a + * persistent error remap it with the l3 remapping tool supplied in + * intel-gpu-tools. The value supplied with the event is always 1. * * I915_ERROR_UEVENT - Generated upon error detection, currently only via * hangcheck. The error detection event is a good indicator of when things -- cgit From 9a27d5916b1d0338f76a4a8cb6fabc5320664453 Mon Sep 17 00:00:00 2001 From: Guoqing Li Date: Fri, 13 Sep 2013 14:59:45 +0800 Subject: video: mmp: rb swap setting update for mmp display We could set rb swap in two modules: DMA controler input part and dsi interface output part. DMA input part is based on pix_fmt to set rbswap, dsi output interface part will set rbswap based on platform dsi_rbswap configuration. This patch include below change and enhancement: 1) The input format which support rbswap is based on RGB format, eg. RGB565 indicates the source data in memory is that Red is [15~11], Green is [10~5], Blue is [4:0], Red is MSB, Blue is LSB, but for the display dma input default setting(rbswap = 0), it only support Blue is [15~11], Green is [10~5], Red is [4:0], Red is LSB, Blue is MSB, so for this format(RGB565), display controller need to set rbswap = 1 and it can support the MSB/LSB correctly. BGR/YUV format will not set it in mmp display driver. 2) The dsi output part of rbswap is depend on dsi_rbswap which is defined in specific platfrom. For output dsi interface, it has this feature to do rbswap again if it needs specifc byte sequence of RGB byte for DSI panel. eg. If display content is set RGB565 in memory and DMA input part set rbswap in driver to support Red as MSB , Blue LSB, but dsi panel only support Red as LSB, Blue as MSB, then it can use this feature. If there is no this requirement of panel, this dsi output part is not needed. Signed-off-by: Guoqing Li Signed-off-by: Jett.Zhou Signed-off-by: Zhou Zhu Reviewed-by: Daniel Drake Signed-off-by: Tomi Valkeinen --- drivers/video/mmp/hw/mmp_ctrl.c | 19 +++++++++++-------- drivers/video/mmp/hw/mmp_ctrl.h | 5 +++++ include/video/mmp_disp.h | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c index 75dca19bf214..a40d95a54eec 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.c +++ b/drivers/video/mmp/hw/mmp_ctrl.c @@ -60,8 +60,7 @@ static irqreturn_t ctrl_handle_irq(int irq, void *dev_id) static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt) { - u32 link_config = path_to_path_plat(overlay->path)->link_config; - u32 rbswap, uvswap = 0, yuvswap = 0, + u32 rbswap = 0, uvswap = 0, yuvswap = 0, csc_en = 0, val = 0, vid = overlay_is_vid(overlay); @@ -71,27 +70,23 @@ static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt) case PIXFMT_RGB888PACK: case PIXFMT_RGB888UNPACK: case PIXFMT_RGBA888: - rbswap = !(link_config & 0x1); + rbswap = 1; break; case PIXFMT_VYUY: case PIXFMT_YVU422P: case PIXFMT_YVU420P: - rbswap = link_config & 0x1; uvswap = 1; break; case PIXFMT_YUYV: - rbswap = link_config & 0x1; yuvswap = 1; break; default: - rbswap = link_config & 0x1; break; } switch (pix_fmt) { case PIXFMT_RGB565: case PIXFMT_BGR565: - val = 0; break; case PIXFMT_RGB1555: case PIXFMT_BGR1555: @@ -248,7 +243,8 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) { struct lcd_regs *regs = path_regs(path); u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div, - link_config = path_to_path_plat(path)->link_config; + link_config = path_to_path_plat(path)->link_config, + dsi_rbswap = path_to_path_plat(path)->link_config; /* FIXME: assert videomode supported */ memcpy(&path->mode, mode, sizeof(struct mmp_mode)); @@ -263,6 +259,12 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) tmp |= CFG_DUMB_ENA(1); writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id)); + /* interface rb_swap setting */ + tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) & + (~(CFG_INTFRBSWAP_MASK)); + tmp |= dsi_rbswap & CFG_INTFRBSWAP_MASK; + writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id)); + writel_relaxed((mode->yres << 16) | mode->xres, ®s->screen_active); writel_relaxed((mode->left_margin << 16) | mode->right_margin, ®s->screen_h_porch); @@ -419,6 +421,7 @@ static int path_init(struct mmphw_path_plat *path_plat, path_plat->path = path; path_plat->path_config = config->path_config; path_plat->link_config = config->link_config; + path_plat->dsi_rbswap = config->dsi_rbswap; path_set_default(path); kfree(path_info); diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h index edd2002b0e99..53301cfdb1ae 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.h +++ b/drivers/video/mmp/hw/mmp_ctrl.h @@ -163,6 +163,8 @@ struct lcd_regs { #define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\ ((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV)) +#define intf_rbswap_ctrl(id) ((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \ + PN2_IOPAD_CONTROL) : LCD_TOP_CTRL) /* dither configure */ #ifdef CONFIG_CPU_PXA988 @@ -615,6 +617,8 @@ struct lcd_regs { #define LCD_SPU_DUMB_CTRL 0x01B8 #define CFG_DUMBMODE(mode) ((mode)<<28) #define CFG_DUMBMODE_MASK 0xF0000000 +#define CFG_INTFRBSWAP(mode) ((mode)<<24) +#define CFG_INTFRBSWAP_MASK 0x0F000000 #define CFG_LCDGPIO_O(data) ((data)<<20) #define CFG_LCDGPIO_O_MASK 0x0FF00000 #define CFG_LCDGPIO_ENA(gpio) ((gpio)<<12) @@ -1427,6 +1431,7 @@ struct mmphw_path_plat { struct mmp_path *path; u32 path_config; u32 link_config; + u32 dsi_rbswap; }; /* mmp ctrl describes mmp controller related info */ diff --git a/include/video/mmp_disp.h b/include/video/mmp_disp.h index b9dd1fbb0082..32094c052deb 100644 --- a/include/video/mmp_disp.h +++ b/include/video/mmp_disp.h @@ -334,6 +334,7 @@ struct mmp_mach_path_config { int output_type; u32 path_config; u32 link_config; + u32 dsi_rbswap; }; struct mmp_mach_plat_info { -- cgit From 24586d8342ab27bc75e4560d71e98f3e5dc67d8e Mon Sep 17 00:00:00 2001 From: Jing Xiang Date: Fri, 13 Sep 2013 14:59:49 +0800 Subject: video: mmp: add pitch info in mmp_win structure Add pitch length info of graphics/video layer, pitch is used to represent line length in byte, the usage depends on pix_fmt. If the fmt is YUV, the pitch[0] will be Y length,pitch[1] will be U length, pitch[2] will be V lenth. If the fmt is RGB, the picth[0] will be line lenth, and pitch[1]/pitch[2] will be 0 and not be used. Signed-off-by: Jing Xiang Signed-off-by: Jett.Zhou Signed-off-by: Zhou Zhu Reviewed-by: Daniel Drake Signed-off-by: Tomi Valkeinen --- drivers/video/mmp/fb/mmpfb.c | 6 ++++++ drivers/video/mmp/hw/mmp_ctrl.c | 30 +++++++++++++++++++++++------- include/video/mmp_disp.h | 5 +++++ 3 files changed, 34 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c index 19fd913f462d..7ab31eb76a8c 100644 --- a/drivers/video/mmp/fb/mmpfb.c +++ b/drivers/video/mmp/fb/mmpfb.c @@ -395,12 +395,18 @@ static int var_update(struct fb_info *info) static void mmpfb_set_win(struct fb_info *info) { struct mmpfb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; struct mmp_win win; + u32 stride; memset(&win, 0, sizeof(win)); win.xsrc = win.xdst = fbi->mode.xres; win.ysrc = win.ydst = fbi->mode.yres; win.pix_fmt = fbi->pix_fmt; + stride = pixfmt_to_stride(win.pix_fmt); + win.pitch[0] = var->xres_virtual * stride; + win.pitch[1] = win.pitch[2] = + (stride == 1) ? (var->xres_virtual >> 1) : 0; mmp_overlay_set_win(fbi->overlay, &win); } diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c index c0eb8bccfb87..ae724aaaad47 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.c +++ b/drivers/video/mmp/hw/mmp_ctrl.c @@ -142,17 +142,27 @@ static void dmafetch_set_fmt(struct mmp_overlay *overlay) static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win) { struct lcd_regs *regs = path_regs(overlay->path); - u32 pitch; /* assert win supported */ memcpy(&overlay->win, win, sizeof(struct mmp_win)); mutex_lock(&overlay->access_ok); - pitch = win->xsrc * pixfmt_to_stride(win->pix_fmt); - writel_relaxed(pitch, ®s->g_pitch); - writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->g_size); - writel_relaxed((win->ydst << 16) | win->xdst, ®s->g_size_z); - writel_relaxed(0, ®s->g_start); + + if (overlay_is_vid(overlay)) { + writel_relaxed(win->pitch[0], ®s->v_pitch_yc); + writel_relaxed(win->pitch[2] << 16 | + win->pitch[1], ®s->v_pitch_uv); + + writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->v_size); + writel_relaxed((win->ydst << 16) | win->xdst, ®s->v_size_z); + writel_relaxed(win->ypos << 16 | win->xpos, ®s->v_start); + } else { + writel_relaxed(win->pitch[0], ®s->g_pitch); + + writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->g_size); + writel_relaxed((win->ydst << 16) | win->xdst, ®s->g_size_z); + writel_relaxed(win->ypos << 16 | win->xpos, ®s->g_start); + } dmafetch_set_fmt(overlay); mutex_unlock(&overlay->access_ok); @@ -234,7 +244,13 @@ static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr) /* FIXME: assert addr supported */ memcpy(&overlay->addr, addr, sizeof(struct mmp_addr)); - writel(addr->phys[0], ®s->g_0); + + if (overlay_is_vid(overlay)) { + writel_relaxed(addr->phys[0], ®s->v_y0); + writel_relaxed(addr->phys[1], ®s->v_u0); + writel_relaxed(addr->phys[2], ®s->v_v0); + } else + writel_relaxed(addr->phys[0], ®s->g_0); return overlay->addr.phys[0]; } diff --git a/include/video/mmp_disp.h b/include/video/mmp_disp.h index 32094c052deb..9fd9398368d5 100644 --- a/include/video/mmp_disp.h +++ b/include/video/mmp_disp.h @@ -91,6 +91,11 @@ struct mmp_win { u16 up_crop; u16 bottom_crop; int pix_fmt; + /* + * pitch[0]: graphics/video layer line length or y pitch + * pitch[1]/pitch[2]: video u/v pitch if non-zero + */ + u32 pitch[3]; }; struct mmp_addr { -- cgit From 9bd721c55c8a886b938a45198aab0ccb52f1f7fa Mon Sep 17 00:00:00 2001 From: Jason Low Date: Fri, 13 Sep 2013 11:26:52 -0700 Subject: sched/balancing: Consider max cost of idle balance per sched domain In this patch, we keep track of the max cost we spend doing idle load balancing for each sched domain. If the avg time the CPU remains idle is less then the time we have already spent on idle balancing + the max cost of idle balancing in the sched domain, then we don't continue to attempt the balance. We also keep a per rq variable, max_idle_balance_cost, which keeps track of the max time spent on newidle load balances throughout all its domains so that we can determine the avg_idle's max value. By using the max, we avoid overrunning the average. This further reduces the chance we attempt balancing when the CPU is not idle for longer than the cost to balance. Signed-off-by: Jason Low Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1379096813-3032-3-git-send-email-jason.low2@hp.com Signed-off-by: Ingo Molnar --- arch/metag/include/asm/topology.h | 1 + include/linux/sched.h | 1 + include/linux/topology.h | 3 +++ kernel/sched/core.c | 3 ++- kernel/sched/fair.c | 16 ++++++++++++++++ kernel/sched/sched.h | 3 +++ 6 files changed, 26 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/metag/include/asm/topology.h b/arch/metag/include/asm/topology.h index 23f5118f58db..db192924f4b0 100644 --- a/arch/metag/include/asm/topology.h +++ b/arch/metag/include/asm/topology.h @@ -26,6 +26,7 @@ .last_balance = jiffies, \ .balance_interval = 1, \ .nr_balance_failed = 0, \ + .max_newidle_lb_cost = 0, \ } #define cpu_to_node(cpu) ((void)(cpu), 0) diff --git a/include/linux/sched.h b/include/linux/sched.h index 6682da36b293..be078ff9157f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -810,6 +810,7 @@ struct sched_domain { unsigned int nr_balance_failed; /* initialise to 0 */ u64 last_update; + u64 max_newidle_lb_cost; #ifdef CONFIG_SCHEDSTATS /* load_balance() stats */ diff --git a/include/linux/topology.h b/include/linux/topology.h index d3cf0d6e7712..e2a2c3da2929 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -106,6 +106,7 @@ int arch_update_cpu_topology(void); .last_balance = jiffies, \ .balance_interval = 1, \ .smt_gain = 1178, /* 15% */ \ + .max_newidle_lb_cost = 0, \ } #endif #endif /* CONFIG_SCHED_SMT */ @@ -135,6 +136,7 @@ int arch_update_cpu_topology(void); , \ .last_balance = jiffies, \ .balance_interval = 1, \ + .max_newidle_lb_cost = 0, \ } #endif #endif /* CONFIG_SCHED_MC */ @@ -166,6 +168,7 @@ int arch_update_cpu_topology(void); , \ .last_balance = jiffies, \ .balance_interval = 1, \ + .max_newidle_lb_cost = 0, \ } #endif diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 048f39e45761..c2283c54aed0 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1330,7 +1330,7 @@ ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) if (rq->idle_stamp) { u64 delta = rq_clock(rq) - rq->idle_stamp; - u64 max = 2*sysctl_sched_migration_cost; + u64 max = 2*rq->max_idle_balance_cost; update_avg(&rq->avg_idle, delta); @@ -6506,6 +6506,7 @@ void __init sched_init(void) rq->online = 0; rq->idle_stamp = 0; rq->avg_idle = 2*sysctl_sched_migration_cost; + rq->max_idle_balance_cost = sysctl_sched_migration_cost; INIT_LIST_HEAD(&rq->cfs_tasks); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 0784ab6fcc59..ffc99d8f0a95 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5396,6 +5396,7 @@ void idle_balance(int this_cpu, struct rq *this_rq) struct sched_domain *sd; int pulled_task = 0; unsigned long next_balance = jiffies + HZ; + u64 curr_cost = 0; this_rq->idle_stamp = rq_clock(this_rq); @@ -5412,15 +5413,27 @@ void idle_balance(int this_cpu, struct rq *this_rq) for_each_domain(this_cpu, sd) { unsigned long interval; int continue_balancing = 1; + u64 t0, domain_cost; if (!(sd->flags & SD_LOAD_BALANCE)) continue; + if (this_rq->avg_idle < curr_cost + sd->max_newidle_lb_cost) + break; + if (sd->flags & SD_BALANCE_NEWIDLE) { + t0 = sched_clock_cpu(this_cpu); + /* If we've pulled tasks over stop searching: */ pulled_task = load_balance(this_cpu, this_rq, sd, CPU_NEWLY_IDLE, &continue_balancing); + + domain_cost = sched_clock_cpu(this_cpu) - t0; + if (domain_cost > sd->max_newidle_lb_cost) + sd->max_newidle_lb_cost = domain_cost; + + curr_cost += domain_cost; } interval = msecs_to_jiffies(sd->balance_interval); @@ -5442,6 +5455,9 @@ void idle_balance(int this_cpu, struct rq *this_rq) */ this_rq->next_balance = next_balance; } + + if (curr_cost > this_rq->max_idle_balance_cost) + this_rq->max_idle_balance_cost = curr_cost; } /* diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 0d7544c3dba7..e82484db7699 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -476,6 +476,9 @@ struct rq { u64 age_stamp; u64 idle_stamp; u64 avg_idle; + + /* This is used to determine avg_idle's max value */ + u64 max_idle_balance_cost; #endif #ifdef CONFIG_IRQ_TIME_ACCOUNTING -- cgit From f48627e686a69f5215cb0761e731edb3d9859dd9 Mon Sep 17 00:00:00 2001 From: Jason Low Date: Fri, 13 Sep 2013 11:26:53 -0700 Subject: sched/balancing: Periodically decay max cost of idle balance This patch builds on patch 2 and periodically decays that max value to do idle balancing per sched domain by approximately 1% per second. Also decay the rq's max_idle_balance_cost value. Signed-off-by: Jason Low Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1379096813-3032-4-git-send-email-jason.low2@hp.com Signed-off-by: Ingo Molnar --- arch/metag/include/asm/topology.h | 1 + include/linux/sched.h | 3 +++ include/linux/topology.h | 3 +++ kernel/sched/fair.c | 38 +++++++++++++++++++++++++++++++------- 4 files changed, 38 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/metag/include/asm/topology.h b/arch/metag/include/asm/topology.h index db192924f4b0..8e9c0b3b9691 100644 --- a/arch/metag/include/asm/topology.h +++ b/arch/metag/include/asm/topology.h @@ -27,6 +27,7 @@ .balance_interval = 1, \ .nr_balance_failed = 0, \ .max_newidle_lb_cost = 0, \ + .next_decay_max_lb_cost = jiffies, \ } #define cpu_to_node(cpu) ((void)(cpu), 0) diff --git a/include/linux/sched.h b/include/linux/sched.h index be078ff9157f..b5344de1658b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -810,7 +810,10 @@ struct sched_domain { unsigned int nr_balance_failed; /* initialise to 0 */ u64 last_update; + + /* idle_balance() stats */ u64 max_newidle_lb_cost; + unsigned long next_decay_max_lb_cost; #ifdef CONFIG_SCHEDSTATS /* load_balance() stats */ diff --git a/include/linux/topology.h b/include/linux/topology.h index e2a2c3da2929..12ae6ce997d6 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -107,6 +107,7 @@ int arch_update_cpu_topology(void); .balance_interval = 1, \ .smt_gain = 1178, /* 15% */ \ .max_newidle_lb_cost = 0, \ + .next_decay_max_lb_cost = jiffies, \ } #endif #endif /* CONFIG_SCHED_SMT */ @@ -137,6 +138,7 @@ int arch_update_cpu_topology(void); .last_balance = jiffies, \ .balance_interval = 1, \ .max_newidle_lb_cost = 0, \ + .next_decay_max_lb_cost = jiffies, \ } #endif #endif /* CONFIG_SCHED_MC */ @@ -169,6 +171,7 @@ int arch_update_cpu_topology(void); .last_balance = jiffies, \ .balance_interval = 1, \ .max_newidle_lb_cost = 0, \ + .next_decay_max_lb_cost = jiffies, \ } #endif diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ffc99d8f0a95..2b89cd244b0d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5681,15 +5681,39 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle) /* Earliest time when we have to do rebalance again */ unsigned long next_balance = jiffies + 60*HZ; int update_next_balance = 0; - int need_serialize; + int need_serialize, need_decay = 0; + u64 max_cost = 0; update_blocked_averages(cpu); rcu_read_lock(); for_each_domain(cpu, sd) { + /* + * Decay the newidle max times here because this is a regular + * visit to all the domains. Decay ~1% per second. + */ + if (time_after(jiffies, sd->next_decay_max_lb_cost)) { + sd->max_newidle_lb_cost = + (sd->max_newidle_lb_cost * 253) / 256; + sd->next_decay_max_lb_cost = jiffies + HZ; + need_decay = 1; + } + max_cost += sd->max_newidle_lb_cost; + if (!(sd->flags & SD_LOAD_BALANCE)) continue; + /* + * Stop the load balance at this level. There is another + * CPU in our sched group which is doing load balancing more + * actively. + */ + if (!continue_balancing) { + if (need_decay) + continue; + break; + } + interval = sd->balance_interval; if (idle != CPU_IDLE) interval *= sd->busy_factor; @@ -5723,14 +5747,14 @@ out: next_balance = sd->last_balance + interval; update_next_balance = 1; } - + } + if (need_decay) { /* - * Stop the load balance at this level. There is another - * CPU in our sched group which is doing load balancing more - * actively. + * Ensure the rq-wide value also decays but keep it at a + * reasonable floor to avoid funnies with rq->avg_idle. */ - if (!continue_balancing) - break; + rq->max_idle_balance_cost = + max((u64)sysctl_sched_migration_cost, max_cost); } rcu_read_unlock(); -- cgit From 6112fe60ac1bd1e68da8cc4248289d6e48015f9b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 20 Sep 2013 18:00:10 +0530 Subject: regmap: add helper macro to set min/max range of register Add helper macro to set the min and max value of the register range. This is useful when initialising the register ranges of the device like static const struct regmap_range readable_ranges[] = { regmap_reg_range(DEVICE_REG0, DEVICE_REG10), }; Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- include/linux/regmap.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..7d3ae2be6869 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -70,6 +70,8 @@ struct regmap_range { unsigned int range_max; }; +#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, } + /* * A table of ranges including some yes ranges and some no ranges. * If a register belongs to a no_range, the corresponding check function -- cgit From 3e1e3aae1f5d4e8e5edb7e332f6e265597cc5b0a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 Sep 2013 09:10:03 -0700 Subject: net_sched: add u64 rate to psched_ratecfg_precompute() Add an extra u64 rate parameter to psched_ratecfg_precompute() so that some qdisc can opt-in for 64bit rates in the future, to overcome the ~34 Gbits limit. psched_ratecfg_getrate() reports a legacy structure to tc utility, so if actual rate is above the 32bit rate field, cap it to the 34Gbit limit. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sch_generic.h | 11 +++++++++-- net/sched/act_police.c | 4 ++-- net/sched/sch_generic.c | 5 +++-- net/sched/sch_htb.c | 4 ++-- net/sched/sch_tbf.c | 4 ++-- 5 files changed, 18 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f4eb365f7dcd..d0a6321c302e 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -702,13 +702,20 @@ static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, } void psched_ratecfg_precompute(struct psched_ratecfg *r, - const struct tc_ratespec *conf); + const struct tc_ratespec *conf, + u64 rate64); static inline void psched_ratecfg_getrate(struct tc_ratespec *res, const struct psched_ratecfg *r) { memset(res, 0, sizeof(*res)); - res->rate = r->rate_bytes_ps; + + /* legacy struct tc_ratespec has a 32bit @rate field + * Qdisc using 64bit rate should add new attributes + * in order to maintain compatibility. + */ + res->rate = min_t(u64, r->rate_bytes_ps, ~0U); + res->overhead = r->overhead; res->linklayer = (r->linklayer & TC_LINKLAYER_MASK); } diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 189e3c5b3d09..272d8e924cf6 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -231,14 +231,14 @@ override: } if (R_tab) { police->rate_present = true; - psched_ratecfg_precompute(&police->rate, &R_tab->rate); + psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0); qdisc_put_rtab(R_tab); } else { police->rate_present = false; } if (P_tab) { police->peak_present = true; - psched_ratecfg_precompute(&police->peak, &P_tab->rate); + psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0); qdisc_put_rtab(P_tab); } else { police->peak_present = false; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index a74e278654aa..e7121d29c4bd 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -910,11 +910,12 @@ void dev_shutdown(struct net_device *dev) } void psched_ratecfg_precompute(struct psched_ratecfg *r, - const struct tc_ratespec *conf) + const struct tc_ratespec *conf, + u64 rate64) { memset(r, 0, sizeof(*r)); r->overhead = conf->overhead; - r->rate_bytes_ps = conf->rate; + r->rate_bytes_ps = max_t(u64, conf->rate, rate64); r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK); r->mult = 1; /* diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 863846cc5513..6b126f6c9957 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1491,8 +1491,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, cl->prio = TC_HTB_NUMPRIO - 1; } - psched_ratecfg_precompute(&cl->rate, &hopt->rate); - psched_ratecfg_precompute(&cl->ceil, &hopt->ceil); + psched_ratecfg_precompute(&cl->rate, &hopt->rate, 0); + psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, 0); cl->buffer = PSCHED_TICKS2NS(hopt->buffer); cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1aaf1b6e51a2..b0571224f3c9 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -341,9 +341,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) q->tokens = q->buffer; q->ptokens = q->mtu; - psched_ratecfg_precompute(&q->rate, &rtab->rate); + psched_ratecfg_precompute(&q->rate, &rtab->rate, 0); if (ptab) { - psched_ratecfg_precompute(&q->peak, &ptab->rate); + psched_ratecfg_precompute(&q->peak, &ptab->rate, 0); q->peak_present = true; } else { q->peak_present = false; -- cgit From df62cdf348c91baac61b4cb19d19ea1ef87b271e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 Sep 2013 09:10:20 -0700 Subject: net_sched: htb: support of 64bit rates HTB already can deal with 64bit rates, we only have to add two new attributes so that tc can use them to break the current 32bit ABI barrier. TCA_HTB_RATE64 : class rate (in bytes per second) TCA_HTB_CEIL64 : class ceil (in bytes per second) This allows us to setup HTB on 40Gbps links, as 32bit limit is actually ~34Gbps Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/uapi/linux/pkt_sched.h | 2 ++ net/sched/sch_htb.c | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index 9b829134d422..f2624b549e61 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h @@ -357,6 +357,8 @@ enum { TCA_HTB_CTAB, TCA_HTB_RTAB, TCA_HTB_DIRECT_QLEN, + TCA_HTB_RATE64, + TCA_HTB_CEIL64, __TCA_HTB_MAX, }; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 6b126f6c9957..0e1e38b40025 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -997,6 +997,8 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = { [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, [TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 }, + [TCA_HTB_RATE64] = { .type = NLA_U64 }, + [TCA_HTB_CEIL64] = { .type = NLA_U64 }, }; static void htb_work_func(struct work_struct *work) @@ -1114,6 +1116,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, opt.level = cl->level; if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt)) goto nla_put_failure; + if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) && + nla_put_u64(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps)) + goto nla_put_failure; + if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) && + nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps)) + goto nla_put_failure; nla_nest_end(skb, nest); spin_unlock_bh(root_lock); @@ -1332,6 +1340,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, struct qdisc_rate_table *rtab = NULL, *ctab = NULL; struct nlattr *tb[TCA_HTB_MAX + 1]; struct tc_htb_opt *hopt; + u64 rate64, ceil64; /* extract all subattrs from opt attr */ if (!opt) @@ -1491,8 +1500,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, cl->prio = TC_HTB_NUMPRIO - 1; } - psched_ratecfg_precompute(&cl->rate, &hopt->rate, 0); - psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, 0); + rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0; + + ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0; + + psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64); + psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64); cl->buffer = PSCHED_TICKS2NS(hopt->buffer); cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); -- cgit From e8d895a4bb26167292c8c14ecdf61d02502e9c03 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:18 -0700 Subject: compat.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/compat.h | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/net/compat.h b/include/net/compat.h index 6e9565324989..3b603b199c01 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -29,8 +29,8 @@ struct compat_cmsghdr { compat_int_t cmsg_type; }; -extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *); -extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *); +int compat_sock_get_timestamp(struct sock *, struct timeval __user *); +int compat_sock_get_timestampns(struct sock *, struct timespec __user *); #else /* defined(CONFIG_COMPAT) */ /* @@ -40,24 +40,30 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *); #define compat_mmsghdr mmsghdr #endif /* defined(CONFIG_COMPAT) */ -extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); -extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr_storage *, int); -extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned int); -extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, - unsigned int, unsigned int); -extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned int); -extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, - unsigned int, unsigned int, - struct compat_timespec __user *); -extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); -extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); - -extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int); - -extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int, - int (*)(struct sock *, int, int, char __user *, unsigned int)); -extern int compat_mc_getsockopt(struct sock *, int, int, char __user *, - int __user *, int (*)(struct sock *, int, int, char __user *, - int __user *)); +int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); +int verify_compat_iovec(struct msghdr *, struct iovec *, + struct sockaddr_storage *, int); +asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *, + unsigned int); +asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, + unsigned int, unsigned int); +asmlinkage long compat_sys_recvmsg(int, struct compat_msghdr __user *, + unsigned int); +asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, + unsigned int, unsigned int, + struct compat_timespec __user *); +asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, + int __user *); +int put_cmsg_compat(struct msghdr*, int, int, int, void *); + +int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, + unsigned char *, int); + +int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int, + int (*)(struct sock *, int, int, char __user *, + unsigned int)); +int compat_mc_getsockopt(struct sock *, int, int, char __user *, int __user *, + int (*)(struct sock *, int, int, char __user *, + int __user *)); #endif /* NET_COMPAT_H */ -- cgit From 126c623b3980e7c2dd68777171f5b6b6ab352912 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:19 -0700 Subject: dcbevent.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/dcbevent.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/dcbevent.h b/include/net/dcbevent.h index 443626ed4cbc..d2f3041c0dfa 100644 --- a/include/net/dcbevent.h +++ b/include/net/dcbevent.h @@ -25,9 +25,9 @@ enum dcbevent_notif_type { }; #ifdef CONFIG_DCB -extern int register_dcbevent_notifier(struct notifier_block *nb); -extern int unregister_dcbevent_notifier(struct notifier_block *nb); -extern int call_dcbevent_notifiers(unsigned long val, void *v); +int register_dcbevent_notifier(struct notifier_block *nb); +int unregister_dcbevent_notifier(struct notifier_block *nb); +int call_dcbevent_notifiers(unsigned long val, void *v); #else static inline int register_dcbevent_notifier(struct notifier_block *nb) -- cgit From 59ddd965c2388720681eb4dc386bfb074e80788e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:20 -0700 Subject: decnet (dn*.h): Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/dn.h | 20 +++++++++++--------- include/net/dn_dev.h | 30 +++++++++++++++--------------- include/net/dn_fib.h | 47 ++++++++++++++++++++++------------------------- include/net/dn_neigh.h | 12 ++++++------ include/net/dn_nsp.h | 49 ++++++++++++++++++++++++++----------------------- include/net/dn_route.h | 13 +++++++------ 6 files changed, 87 insertions(+), 84 deletions(-) (limited to 'include') diff --git a/include/net/dn.h b/include/net/dn.h index c88bf4ebd330..ccc15588d108 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -199,24 +199,26 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp) fld->fld_dport = scp->addrrem; } -extern unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu); +unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu); #define DN_MENUVER_ACC 0x01 #define DN_MENUVER_USR 0x02 #define DN_MENUVER_PRX 0x04 #define DN_MENUVER_UIC 0x08 -extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr); -extern struct sock *dn_find_by_skb(struct sk_buff *skb); +struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr); +struct sock *dn_find_by_skb(struct sk_buff *skb); #define DN_ASCBUF_LEN 9 -extern char *dn_addr2asc(__u16, char *); -extern int dn_destroy_timer(struct sock *sk); +char *dn_addr2asc(__u16, char *); +int dn_destroy_timer(struct sock *sk); -extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type); -extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, unsigned char *type); +int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, + unsigned char type); +int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, + unsigned char *type); -extern void dn_start_slow_timer(struct sock *sk); -extern void dn_stop_slow_timer(struct sock *sk); +void dn_start_slow_timer(struct sock *sk); +void dn_stop_slow_timer(struct sock *sk); extern __le16 decnet_address; extern int decnet_debug_level; diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h index b9e32db03f20..20b5ab06032d 100644 --- a/include/net/dn_dev.h +++ b/include/net/dn_dev.h @@ -148,27 +148,27 @@ struct rtnode_hello_message { } __packed; -extern void dn_dev_init(void); -extern void dn_dev_cleanup(void); +void dn_dev_init(void); +void dn_dev_cleanup(void); -extern int dn_dev_ioctl(unsigned int cmd, void __user *arg); +int dn_dev_ioctl(unsigned int cmd, void __user *arg); -extern void dn_dev_devices_off(void); -extern void dn_dev_devices_on(void); +void dn_dev_devices_off(void); +void dn_dev_devices_on(void); -extern void dn_dev_init_pkt(struct sk_buff *skb); -extern void dn_dev_veri_pkt(struct sk_buff *skb); -extern void dn_dev_hello(struct sk_buff *skb); +void dn_dev_init_pkt(struct sk_buff *skb); +void dn_dev_veri_pkt(struct sk_buff *skb); +void dn_dev_hello(struct sk_buff *skb); -extern void dn_dev_up(struct net_device *); -extern void dn_dev_down(struct net_device *); +void dn_dev_up(struct net_device *); +void dn_dev_down(struct net_device *); -extern int dn_dev_set_default(struct net_device *dev, int force); -extern struct net_device *dn_dev_get_default(void); -extern int dn_dev_bind_default(__le16 *addr); +int dn_dev_set_default(struct net_device *dev, int force); +struct net_device *dn_dev_get_default(void); +int dn_dev_bind_default(__le16 *addr); -extern int register_dnaddr_notifier(struct notifier_block *nb); -extern int unregister_dnaddr_notifier(struct notifier_block *nb); +int register_dnaddr_notifier(struct notifier_block *nb); +int unregister_dnaddr_notifier(struct notifier_block *nb); static inline int dn_dev_islocal(struct net_device *dev, __le16 addr) { diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h index 74004af31c48..f2ca135ddcc9 100644 --- a/include/net/dn_fib.h +++ b/include/net/dn_fib.h @@ -95,41 +95,38 @@ struct dn_fib_table { /* * dn_fib.c */ -extern void dn_fib_init(void); -extern void dn_fib_cleanup(void); - -extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd, - unsigned long arg); -extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, - struct nlattr *attrs[], - const struct nlmsghdr *nlh, int *errp); -extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, - const struct flowidn *fld, - struct dn_fib_res *res); -extern void dn_fib_release_info(struct dn_fib_info *fi); -extern void dn_fib_flush(void); -extern void dn_fib_select_multipath(const struct flowidn *fld, - struct dn_fib_res *res); +void dn_fib_init(void); +void dn_fib_cleanup(void); + +int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); +struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, + struct nlattr *attrs[], + const struct nlmsghdr *nlh, int *errp); +int dn_fib_semantic_match(int type, struct dn_fib_info *fi, + const struct flowidn *fld, struct dn_fib_res *res); +void dn_fib_release_info(struct dn_fib_info *fi); +void dn_fib_flush(void); +void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res); /* * dn_tables.c */ -extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat); -extern struct dn_fib_table *dn_fib_empty_table(void); -extern void dn_fib_table_init(void); -extern void dn_fib_table_cleanup(void); +struct dn_fib_table *dn_fib_get_table(u32 n, int creat); +struct dn_fib_table *dn_fib_empty_table(void); +void dn_fib_table_init(void); +void dn_fib_table_cleanup(void); /* * dn_rules.c */ -extern void dn_fib_rules_init(void); -extern void dn_fib_rules_cleanup(void); -extern unsigned int dnet_addr_type(__le16 addr); -extern int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res); +void dn_fib_rules_init(void); +void dn_fib_rules_cleanup(void); +unsigned int dnet_addr_type(__le16 addr); +int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res); -extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb); +int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb); -extern void dn_fib_free_info(struct dn_fib_info *fi); +void dn_fib_free_info(struct dn_fib_info *fi); static inline void dn_fib_info_put(struct dn_fib_info *fi) { diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h index 4cb4ae7fb81f..fac4e3f4a6d3 100644 --- a/include/net/dn_neigh.h +++ b/include/net/dn_neigh.h @@ -16,12 +16,12 @@ struct dn_neigh { __u8 priority; }; -extern void dn_neigh_init(void); -extern void dn_neigh_cleanup(void); -extern int dn_neigh_router_hello(struct sk_buff *skb); -extern int dn_neigh_endnode_hello(struct sk_buff *skb); -extern void dn_neigh_pointopoint_hello(struct sk_buff *skb); -extern int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n); +void dn_neigh_init(void); +void dn_neigh_cleanup(void); +int dn_neigh_router_hello(struct sk_buff *skb); +int dn_neigh_endnode_hello(struct sk_buff *skb); +void dn_neigh_pointopoint_hello(struct sk_buff *skb); +int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n); extern struct neigh_table dn_neigh_table; diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h index e43a2893f132..3a3e33d18456 100644 --- a/include/net/dn_nsp.h +++ b/include/net/dn_nsp.h @@ -15,29 +15,32 @@ *******************************************************************************/ /* dn_nsp.c functions prototyping */ -extern void dn_nsp_send_data_ack(struct sock *sk); -extern void dn_nsp_send_oth_ack(struct sock *sk); -extern void dn_nsp_delayed_ack(struct sock *sk); -extern void dn_send_conn_ack(struct sock *sk); -extern void dn_send_conn_conf(struct sock *sk, gfp_t gfp); -extern void dn_nsp_send_disc(struct sock *sk, unsigned char type, - unsigned short reason, gfp_t gfp); -extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type, - unsigned short reason); -extern void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval); -extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags); - -extern void dn_nsp_output(struct sock *sk); -extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum); -extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, int oob); -extern unsigned long dn_nsp_persist(struct sock *sk); -extern int dn_nsp_xmit_timeout(struct sock *sk); - -extern int dn_nsp_rx(struct sk_buff *); -extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb); - -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); -extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err); +void dn_nsp_send_data_ack(struct sock *sk); +void dn_nsp_send_oth_ack(struct sock *sk); +void dn_nsp_delayed_ack(struct sock *sk); +void dn_send_conn_ack(struct sock *sk); +void dn_send_conn_conf(struct sock *sk, gfp_t gfp); +void dn_nsp_send_disc(struct sock *sk, unsigned char type, + unsigned short reason, gfp_t gfp); +void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type, + unsigned short reason); +void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval); +void dn_nsp_send_conninit(struct sock *sk, unsigned char flags); + +void dn_nsp_output(struct sock *sk); +int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, + struct sk_buff_head *q, unsigned short acknum); +void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, + int oob); +unsigned long dn_nsp_persist(struct sock *sk); +int dn_nsp_xmit_timeout(struct sock *sk); + +int dn_nsp_rx(struct sk_buff *); +int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb); + +struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); +struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, + long timeo, int *err); #define NSP_REASON_OK 0 /* No error */ #define NSP_REASON_NR 1 /* No resources */ diff --git a/include/net/dn_route.h b/include/net/dn_route.h index 2e9d317c82dc..b409ad6b8d7a 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -15,10 +15,11 @@ GNU General Public License for more details. *******************************************************************************/ -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); -extern int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *, struct sock *sk, int flags); -extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); -extern void dn_rt_cache_flush(int delay); +struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); +int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *, + struct sock *sk, int flags); +int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); +void dn_rt_cache_flush(int delay); /* Masks for flags field */ #define DN_RT_F_PID 0x07 /* Mask for packet type */ @@ -92,8 +93,8 @@ static inline bool dn_is_output_route(struct dn_route *rt) return rt->fld.flowidn_iif == 0; } -extern void dn_route_init(void); -extern void dn_route_cleanup(void); +void dn_route_init(void); +void dn_route_cleanup(void); #include #include -- cgit From a4023dd01a37f3a648ea028269f946cb55896337 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:21 -0700 Subject: dst.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/dst.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/net/dst.h b/include/net/dst.h index 3bc4865f8267..211dcf1e758e 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -106,7 +106,7 @@ struct dst_entry { }; }; -extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); +u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); extern const u32 dst_default_metrics[]; #define DST_METRICS_READ_ONLY 0x1UL @@ -119,7 +119,7 @@ static inline bool dst_metrics_read_only(const struct dst_entry *dst) return dst->_metrics & DST_METRICS_READ_ONLY; } -extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); +void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); static inline void dst_destroy_metrics_generic(struct dst_entry *dst) { @@ -262,7 +262,7 @@ static inline struct dst_entry *dst_clone(struct dst_entry *dst) return dst; } -extern void dst_release(struct dst_entry *dst); +void dst_release(struct dst_entry *dst); static inline void refdst_drop(unsigned long refdst) { @@ -362,12 +362,11 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) return child; } -extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, - int initial_ref, int initial_obsolete, - unsigned short flags); -extern void __dst_free(struct dst_entry *dst); -extern struct dst_entry *dst_destroy(struct dst_entry *dst); +int dst_discard(struct sk_buff *skb); +void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, + int initial_obsolete, unsigned short flags); +void __dst_free(struct dst_entry *dst); +struct dst_entry *dst_destroy(struct dst_entry *dst); static inline void dst_free(struct dst_entry *dst) { @@ -463,7 +462,7 @@ static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) return dst; } -extern void dst_init(void); +void dst_init(void); /* Flags for xfrm_lookup flags argument. */ enum { @@ -480,9 +479,9 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, return dst_orig; } #else -extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, - const struct flowi *fl, struct sock *sk, - int flags); +struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); #endif #endif /* _NET_DST_H */ -- cgit From 7b3852a2fdd86238709038654f010befca5b47c3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:22 -0700 Subject: esp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/esp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/esp.h b/include/net/esp.h index d58451331dbd..1356dda00d22 100644 --- a/include/net/esp.h +++ b/include/net/esp.h @@ -13,7 +13,7 @@ struct esp_data { struct crypto_aead *aead; }; -extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); +void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); struct ip_esp_hdr; -- cgit From 8de6879fa949b3817f19f145a491e93df8925bc0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:23 -0700 Subject: fib_rules.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/fib_rules.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 4b2b557fb0e8..e584de16e4c3 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -115,14 +115,13 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla) return frh->table; } -extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *); -extern void fib_rules_unregister(struct fib_rules_ops *); +struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, + struct net *); +void fib_rules_unregister(struct fib_rules_ops *); -extern int fib_rules_lookup(struct fib_rules_ops *, - struct flowi *, int flags, - struct fib_lookup_arg *); -extern int fib_default_rule_add(struct fib_rules_ops *, - u32 pref, u32 table, - u32 flags); -extern u32 fib_default_rule_pref(struct fib_rules_ops *ops); +int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags, + struct fib_lookup_arg *); +int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table, + u32 flags); +u32 fib_default_rule_pref(struct fib_rules_ops *ops); #endif -- cgit From 4787342c390a8e7570a81a62c9b361d7a4380893 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:24 -0700 Subject: flow.h/flow_keys.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/flow.h | 11 ++++++----- include/net/flow_keys.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/flow.h b/include/net/flow.h index 628e11b98c58..65ce471d2ab5 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -215,12 +215,13 @@ typedef struct flow_cache_object *(*flow_resolve_t)( struct net *net, const struct flowi *key, u16 family, u8 dir, struct flow_cache_object *oldobj, void *ctx); -extern struct flow_cache_object *flow_cache_lookup( - struct net *net, const struct flowi *key, u16 family, - u8 dir, flow_resolve_t resolver, void *ctx); +struct flow_cache_object *flow_cache_lookup(struct net *net, + const struct flowi *key, u16 family, + u8 dir, flow_resolve_t resolver, + void *ctx); -extern void flow_cache_flush(void); -extern void flow_cache_flush_deferred(void); +void flow_cache_flush(void); +void flow_cache_flush_deferred(void); extern atomic_t flow_cache_genid; #endif diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h index bb8271d487b7..ac2439d02f54 100644 --- a/include/net/flow_keys.h +++ b/include/net/flow_keys.h @@ -13,5 +13,5 @@ struct flow_keys { u8 ip_proto; }; -extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow); +bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow); #endif -- cgit From 2008f21cbdc48761270cec119c8385584691cf34 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:25 -0700 Subject: garp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/garp.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/net/garp.h b/include/net/garp.h index 834d8add9e5f..abf33bbd2e6a 100644 --- a/include/net/garp.h +++ b/include/net/garp.h @@ -112,19 +112,18 @@ struct garp_port { struct rcu_head rcu; }; -extern int garp_register_application(struct garp_application *app); -extern void garp_unregister_application(struct garp_application *app); - -extern int garp_init_applicant(struct net_device *dev, - struct garp_application *app); -extern void garp_uninit_applicant(struct net_device *dev, - struct garp_application *app); - -extern int garp_request_join(const struct net_device *dev, - const struct garp_application *app, - const void *data, u8 len, u8 type); -extern void garp_request_leave(const struct net_device *dev, - const struct garp_application *app, - const void *data, u8 len, u8 type); +int garp_register_application(struct garp_application *app); +void garp_unregister_application(struct garp_application *app); + +int garp_init_applicant(struct net_device *dev, struct garp_application *app); +void garp_uninit_applicant(struct net_device *dev, + struct garp_application *app); + +int garp_request_join(const struct net_device *dev, + const struct garp_application *app, const void *data, + u8 len, u8 type); +void garp_request_leave(const struct net_device *dev, + const struct garp_application *app, + const void *data, u8 len, u8 type); #endif /* _NET_GARP_H */ -- cgit From 8aae218f58f44471c6715e695da5ed9f54dd4491 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:26 -0700 Subject: gen_stats.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/gen_stats.h | 51 ++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index cf8439ba4d11..ea4271dceff0 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -19,32 +19,31 @@ struct gnet_dump { struct tc_stats tc_stats; }; -extern int gnet_stats_start_copy(struct sk_buff *skb, int type, +int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, + struct gnet_dump *d); + +int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, + int tc_stats_type, int xstats_type, spinlock_t *lock, struct gnet_dump *d); -extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, - int tc_stats_type,int xstats_type, - spinlock_t *lock, struct gnet_dump *d); - -extern int gnet_stats_copy_basic(struct gnet_dump *d, - struct gnet_stats_basic_packed *b); -extern int gnet_stats_copy_rate_est(struct gnet_dump *d, - const struct gnet_stats_basic_packed *b, - struct gnet_stats_rate_est64 *r); -extern int gnet_stats_copy_queue(struct gnet_dump *d, - struct gnet_stats_queue *q); -extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); - -extern int gnet_stats_finish_copy(struct gnet_dump *d); - -extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est64 *rate_est, - spinlock_t *stats_lock, struct nlattr *opt); -extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est64 *rate_est); -extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est64 *rate_est, - spinlock_t *stats_lock, struct nlattr *opt); -extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, - const struct gnet_stats_rate_est64 *rate_est); +int gnet_stats_copy_basic(struct gnet_dump *d, + struct gnet_stats_basic_packed *b); +int gnet_stats_copy_rate_est(struct gnet_dump *d, + const struct gnet_stats_basic_packed *b, + struct gnet_stats_rate_est64 *r); +int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q); +int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); + +int gnet_stats_finish_copy(struct gnet_dump *d); + +int gen_new_estimator(struct gnet_stats_basic_packed *bstats, + struct gnet_stats_rate_est64 *rate_est, + spinlock_t *stats_lock, struct nlattr *opt); +void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, + struct gnet_stats_rate_est64 *rate_est); +int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, + struct gnet_stats_rate_est64 *rate_est, + spinlock_t *stats_lock, struct nlattr *opt); +bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, + const struct gnet_stats_rate_est64 *rate_est); #endif -- cgit From ff2b94d2c3d075d0f2fde330e3b5a73053c426c7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:27 -0700 Subject: genetlink.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/genetlink.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 8e0b6c856a13..9b787b62cf16 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -122,7 +122,7 @@ struct genl_ops { struct list_head ops_list; }; -extern int __genl_register_family(struct genl_family *family); +int __genl_register_family(struct genl_family *family); static inline int genl_register_family(struct genl_family *family) { @@ -130,8 +130,8 @@ static inline int genl_register_family(struct genl_family *family) return __genl_register_family(family); } -extern int __genl_register_family_with_ops(struct genl_family *family, - struct genl_ops *ops, size_t n_ops); +int __genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops); static inline int genl_register_family_with_ops(struct genl_family *family, struct genl_ops *ops, size_t n_ops) @@ -140,18 +140,18 @@ static inline int genl_register_family_with_ops(struct genl_family *family, return __genl_register_family_with_ops(family, ops, n_ops); } -extern int genl_unregister_family(struct genl_family *family); -extern int genl_register_ops(struct genl_family *, struct genl_ops *ops); -extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops); -extern int genl_register_mc_group(struct genl_family *family, - struct genl_multicast_group *grp); -extern void genl_unregister_mc_group(struct genl_family *family, - struct genl_multicast_group *grp); -extern void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, - u32 group, struct nlmsghdr *nlh, gfp_t flags); +int genl_unregister_family(struct genl_family *family); +int genl_register_ops(struct genl_family *, struct genl_ops *ops); +int genl_unregister_ops(struct genl_family *, struct genl_ops *ops); +int genl_register_mc_group(struct genl_family *family, + struct genl_multicast_group *grp); +void genl_unregister_mc_group(struct genl_family *family, + struct genl_multicast_group *grp); +void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, + u32 group, struct nlmsghdr *nlh, gfp_t flags); void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, - struct genl_family *family, int flags, u8 cmd); + struct genl_family *family, int flags, u8 cmd); /** * genlmsg_nlhdr - Obtain netlink header from user specified header -- cgit From e60ab84dd59cc0ddb46a7696a56f9de8b8b22f39 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Sep 2013 11:23:28 -0700 Subject: icmp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/icmp.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/icmp.h b/include/net/icmp.h index 081439fd070e..970028e13382 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -39,10 +39,10 @@ struct net_proto_family; struct sk_buff; struct net; -extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); -extern int icmp_rcv(struct sk_buff *skb); -extern void icmp_err(struct sk_buff *, u32 info); -extern int icmp_init(void); -extern void icmp_out_count(struct net *net, unsigned char type); +void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); +int icmp_rcv(struct sk_buff *skb); +void icmp_err(struct sk_buff *skb, u32 info); +int icmp_init(void); +void icmp_out_count(struct net *net, unsigned char type); #endif /* _ICMP_H */ -- cgit From 2485602f1af209aaef3f394ac8336a67cb8742aa Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sun, 18 Aug 2013 22:41:37 +0200 Subject: can: add explicit copyrights to can headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These files are copied to the source code of user space applications (in this case can-utils) and so it makes sense to mention explicitly their copyright. I added the terms of C code that was introduced in the same commit as these headers. Signed-off-by: Uwe Kleine-König Acked-by: Oliver Hartkopp Acked-by: Urs Thuermann Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/bcm.h | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/can/error.h | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/can/gw.h | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/can/raw.h | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/can/bcm.h b/include/uapi/linux/can/bcm.h index 3ebe387fea4d..382251a1d214 100644 --- a/include/uapi/linux/can/bcm.h +++ b/include/uapi/linux/can/bcm.h @@ -7,6 +7,38 @@ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. */ #ifndef CAN_BCM_H diff --git a/include/uapi/linux/can/error.h b/include/uapi/linux/can/error.h index 7b7148bded71..b63204545320 100644 --- a/include/uapi/linux/can/error.h +++ b/include/uapi/linux/can/error.h @@ -7,6 +7,38 @@ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. */ #ifndef CAN_ERROR_H diff --git a/include/uapi/linux/can/gw.h b/include/uapi/linux/can/gw.h index 4e27c82b564a..844c8964bdfe 100644 --- a/include/uapi/linux/can/gw.h +++ b/include/uapi/linux/can/gw.h @@ -7,6 +7,38 @@ * Copyright (c) 2011 Volkswagen Group Electronic Research * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. */ #ifndef CAN_GW_H diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h index a814062b0719..c7d8c334e0ce 100644 --- a/include/uapi/linux/can/raw.h +++ b/include/uapi/linux/can/raw.h @@ -8,6 +8,38 @@ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. */ #ifndef CAN_RAW_H -- cgit From 1c2da13c21a14e9db99c701412ac9069d5b91cf5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 7 Sep 2013 21:34:38 +0200 Subject: can: add explicit copyrights to can's netlink header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file is copied to the source code of user space applications (in this case can-utils) and so it makes sense to mention explicitly their copyright. Signed-off-by: Uwe Kleine-König Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/netlink.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h index 14966ddb7df1..df944ed206a8 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -5,6 +5,14 @@ * * Copyright (c) 2009 Wolfgang Grandegger * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #ifndef CAN_NETLINK_H -- cgit From 1fd51155387264e3ca72094abadcaadb3f5969f6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:41 -0700 Subject: inet*.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/inet6_connection_sock.h | 32 +++++++-------- include/net/inet6_hashtables.h | 38 +++++++++--------- include/net/inet_common.h | 48 +++++++++++----------- include/net/inet_connection_sock.h | 79 ++++++++++++++++++------------------- include/net/inet_hashtables.h | 72 ++++++++++++++++----------------- include/net/inet_sock.h | 4 +- include/net/inet_timewait_sock.h | 37 +++++++++-------- include/net/inetpeer.h | 12 +++--- 8 files changed, 157 insertions(+), 165 deletions(-) (limited to 'include') diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index 04642c920431..f981ba7adeed 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -22,27 +22,25 @@ struct sk_buff; struct sock; struct sockaddr; -extern int inet6_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax); +int inet6_csk_bind_conflict(const struct sock *sk, + const struct inet_bind_bucket *tb, bool relax); -extern struct dst_entry* inet6_csk_route_req(struct sock *sk, - struct flowi6 *fl6, - const struct request_sock *req); +struct dst_entry *inet6_csk_route_req(struct sock *sk, struct flowi6 *fl6, + const struct request_sock *req); -extern struct request_sock *inet6_csk_search_req(const struct sock *sk, - struct request_sock ***prevp, - const __be16 rport, - const struct in6_addr *raddr, - const struct in6_addr *laddr, - const int iif); +struct request_sock *inet6_csk_search_req(const struct sock *sk, + struct request_sock ***prevp, + const __be16 rport, + const struct in6_addr *raddr, + const struct in6_addr *laddr, + const int iif); -extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, - struct request_sock *req, - const unsigned long timeout); +void inet6_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, + const unsigned long timeout); -extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); +void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); +int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); -extern struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu); +struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index fd4ee016ba5c..f52fa88feb64 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -53,7 +53,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk) return inet6_ehashfn(net, laddr, lport, faddr, fport); } -extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); +int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); /* * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so @@ -61,21 +61,19 @@ extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); * * The sockhash lock must be held as a reader here. */ -extern struct sock *__inet6_lookup_established(struct net *net, - struct inet_hashinfo *hashinfo, - const struct in6_addr *saddr, - const __be16 sport, - const struct in6_addr *daddr, - const u16 hnum, - const int dif); - -extern struct sock *inet6_lookup_listener(struct net *net, - struct inet_hashinfo *hashinfo, - const struct in6_addr *saddr, - const __be16 sport, - const struct in6_addr *daddr, - const unsigned short hnum, - const int dif); +struct sock *__inet6_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, + const struct in6_addr *saddr, + const __be16 sport, + const struct in6_addr *daddr, + const u16 hnum, const int dif); + +struct sock *inet6_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, + const struct in6_addr *saddr, + const __be16 sport, + const struct in6_addr *daddr, + const unsigned short hnum, const int dif); static inline struct sock *__inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, @@ -110,9 +108,9 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, inet6_iif(skb)); } -extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, - const struct in6_addr *saddr, const __be16 sport, - const struct in6_addr *daddr, const __be16 dport, - const int dif); +struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, + const struct in6_addr *saddr, const __be16 sport, + const struct in6_addr *daddr, const __be16 dport, + const int dif); #endif /* IS_ENABLED(CONFIG_IPV6) */ #endif /* _INET6_HASHTABLES_H */ diff --git a/include/net/inet_common.h b/include/net/inet_common.h index 234008782c8c..fe7994c48b75 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -13,30 +13,30 @@ struct sock; struct sockaddr; struct socket; -extern int inet_release(struct socket *sock); -extern int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, - int addr_len, int flags); -extern int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, - int addr_len, int flags); -extern int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, - int addr_len, int flags); -extern int inet_accept(struct socket *sock, struct socket *newsock, int flags); -extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t size); -extern ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, - size_t size, int flags); -extern int inet_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t size, int flags); -extern int inet_shutdown(struct socket *sock, int how); -extern int inet_listen(struct socket *sock, int backlog); -extern void inet_sock_destruct(struct sock *sk); -extern int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); -extern int inet_getname(struct socket *sock, struct sockaddr *uaddr, - int *uaddr_len, int peer); -extern int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); -extern int inet_ctl_sock_create(struct sock **sk, unsigned short family, - unsigned short type, unsigned char protocol, - struct net *net); +int inet_release(struct socket *sock); +int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags); +int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags); +int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags); +int inet_accept(struct socket *sock, struct socket *newsock, int flags); +int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + size_t size); +ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, + size_t size, int flags); +int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + size_t size, int flags); +int inet_shutdown(struct socket *sock, int how); +int inet_listen(struct socket *sock, int backlog); +void inet_sock_destruct(struct sock *sk); +int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); +int inet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, + int peer); +int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); +int inet_ctl_sock_create(struct sock **sk, unsigned short family, + unsigned short type, unsigned char protocol, + struct net *net); static inline void inet_ctl_sock_destroy(struct sock *sk) { diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index de2c78529afa..c55aeed41ace 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -146,9 +146,9 @@ static inline void *inet_csk_ca(const struct sock *sk) return (void *)inet_csk(sk)->icsk_ca_priv; } -extern struct sock *inet_csk_clone_lock(const struct sock *sk, - const struct request_sock *req, - const gfp_t priority); +struct sock *inet_csk_clone_lock(const struct sock *sk, + const struct request_sock *req, + const gfp_t priority); enum inet_csk_ack_state_t { ICSK_ACK_SCHED = 1, @@ -157,11 +157,11 @@ enum inet_csk_ack_state_t { ICSK_ACK_PUSHED2 = 8 }; -extern void inet_csk_init_xmit_timers(struct sock *sk, - void (*retransmit_handler)(unsigned long), - void (*delack_handler)(unsigned long), - void (*keepalive_handler)(unsigned long)); -extern void inet_csk_clear_xmit_timers(struct sock *sk); +void inet_csk_init_xmit_timers(struct sock *sk, + void (*retransmit_handler)(unsigned long), + void (*delack_handler)(unsigned long), + void (*keepalive_handler)(unsigned long)); +void inet_csk_clear_xmit_timers(struct sock *sk); static inline void inet_csk_schedule_ack(struct sock *sk) { @@ -178,8 +178,8 @@ static inline void inet_csk_delack_init(struct sock *sk) memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack)); } -extern void inet_csk_delete_keepalive_timer(struct sock *sk); -extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout); +void inet_csk_delete_keepalive_timer(struct sock *sk); +void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout); #ifdef INET_CSK_DEBUG extern const char inet_csk_timer_bug_msg[]; @@ -241,23 +241,21 @@ static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what, #endif } -extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err); +struct sock *inet_csk_accept(struct sock *sk, int flags, int *err); -extern struct request_sock *inet_csk_search_req(const struct sock *sk, - struct request_sock ***prevp, - const __be16 rport, - const __be32 raddr, - const __be32 laddr); -extern int inet_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb, bool relax); -extern int inet_csk_get_port(struct sock *sk, unsigned short snum); +struct request_sock *inet_csk_search_req(const struct sock *sk, + struct request_sock ***prevp, + const __be16 rport, + const __be32 raddr, + const __be32 laddr); +int inet_csk_bind_conflict(const struct sock *sk, + const struct inet_bind_bucket *tb, bool relax); +int inet_csk_get_port(struct sock *sk, unsigned short snum); -extern struct dst_entry* inet_csk_route_req(struct sock *sk, - struct flowi4 *fl4, +struct dst_entry *inet_csk_route_req(struct sock *sk, struct flowi4 *fl4, + const struct request_sock *req); +struct dst_entry *inet_csk_route_child_sock(struct sock *sk, struct sock *newsk, const struct request_sock *req); -extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk, - struct sock *newsk, - const struct request_sock *req); static inline void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req, @@ -266,9 +264,8 @@ static inline void inet_csk_reqsk_queue_add(struct sock *sk, reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child); } -extern void inet_csk_reqsk_queue_hash_add(struct sock *sk, - struct request_sock *req, - unsigned long timeout); +void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, + unsigned long timeout); static inline void inet_csk_reqsk_queue_removed(struct sock *sk, struct request_sock *req) @@ -315,13 +312,13 @@ static inline void inet_csk_reqsk_queue_drop(struct sock *sk, reqsk_free(req); } -extern void inet_csk_reqsk_queue_prune(struct sock *parent, - const unsigned long interval, - const unsigned long timeout, - const unsigned long max_rto); +void inet_csk_reqsk_queue_prune(struct sock *parent, + const unsigned long interval, + const unsigned long timeout, + const unsigned long max_rto); -extern void inet_csk_destroy_sock(struct sock *sk); -extern void inet_csk_prepare_forced_close(struct sock *sk); +void inet_csk_destroy_sock(struct sock *sk); +void inet_csk_prepare_forced_close(struct sock *sk); /* * LISTEN is a special case for poll.. @@ -332,15 +329,15 @@ static inline unsigned int inet_csk_listen_poll(const struct sock *sk) (POLLIN | POLLRDNORM) : 0; } -extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries); -extern void inet_csk_listen_stop(struct sock *sk); +int inet_csk_listen_start(struct sock *sk, const int nr_table_entries); +void inet_csk_listen_stop(struct sock *sk); -extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); +void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen); -extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, unsigned int optlen); +int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen); -extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); +struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET_CONNECTION_SOCK_H */ diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index ef83d9e844b5..594dfeead70f 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -218,22 +218,21 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) } } -extern struct inet_bind_bucket * - inet_bind_bucket_create(struct kmem_cache *cachep, - struct net *net, - struct inet_bind_hashbucket *head, - const unsigned short snum); -extern void inet_bind_bucket_destroy(struct kmem_cache *cachep, - struct inet_bind_bucket *tb); - -static inline int inet_bhashfn(struct net *net, - const __u16 lport, const int bhash_size) +struct inet_bind_bucket * +inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net, + struct inet_bind_hashbucket *head, + const unsigned short snum); +void inet_bind_bucket_destroy(struct kmem_cache *cachep, + struct inet_bind_bucket *tb); + +static inline int inet_bhashfn(struct net *net, const __u16 lport, + const int bhash_size) { return (lport + net_hash_mix(net)) & (bhash_size - 1); } -extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, - const unsigned short snum); +void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, + const unsigned short snum); /* These can have wildcards, don't try too hard. */ static inline int inet_lhashfn(struct net *net, const unsigned short num) @@ -247,23 +246,22 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk) } /* Caller must disable local BH processing. */ -extern int __inet_inherit_port(struct sock *sk, struct sock *child); +int __inet_inherit_port(struct sock *sk, struct sock *child); -extern void inet_put_port(struct sock *sk); +void inet_put_port(struct sock *sk); void inet_hashinfo_init(struct inet_hashinfo *h); -extern int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw); -extern void inet_hash(struct sock *sk); -extern void inet_unhash(struct sock *sk); +int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw); +void inet_hash(struct sock *sk); +void inet_unhash(struct sock *sk); -extern struct sock *__inet_lookup_listener(struct net *net, - struct inet_hashinfo *hashinfo, - const __be32 saddr, - const __be16 sport, - const __be32 daddr, - const unsigned short hnum, - const int dif); +struct sock *__inet_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, + const __be32 saddr, const __be16 sport, + const __be32 daddr, + const unsigned short hnum, + const int dif); static inline struct sock *inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, @@ -339,10 +337,11 @@ static inline struct sock *inet_lookup_listener(struct net *net, * * Local BH must be disabled here. */ -extern struct sock * __inet_lookup_established(struct net *net, - struct inet_hashinfo *hashinfo, - const __be32 saddr, const __be16 sport, - const __be32 daddr, const u16 hnum, const int dif); +struct sock *__inet_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, + const __be32 saddr, const __be16 sport, + const __be32 daddr, const u16 hnum, + const int dif); static inline struct sock * inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, @@ -399,13 +398,14 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, iph->daddr, dport, inet_iif(skb)); } -extern int __inet_hash_connect(struct inet_timewait_death_row *death_row, - struct sock *sk, - u32 port_offset, - int (*check_established)(struct inet_timewait_death_row *, - struct sock *, __u16, struct inet_timewait_sock **), - int (*hash)(struct sock *sk, struct inet_timewait_sock *twp)); +int __inet_hash_connect(struct inet_timewait_death_row *death_row, + struct sock *sk, u32 port_offset, + int (*check_established)(struct inet_timewait_death_row *, + struct sock *, __u16, + struct inet_timewait_sock **), + int (*hash)(struct sock *sk, + struct inet_timewait_sock *twp)); -extern int inet_hash_connect(struct inet_timewait_death_row *death_row, - struct sock *sk); +int inet_hash_connect(struct inet_timewait_death_row *death_row, + struct sock *sk); #endif /* _INET_HASHTABLES_H */ diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index b21a7f06d6a4..636d203727a2 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -199,11 +199,11 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, } #endif -extern int inet_sk_rebuild_header(struct sock *sk); +int inet_sk_rebuild_header(struct sock *sk); extern u32 inet_ehash_secret; extern u32 ipv6_hash_secret; -extern void build_ehash_secret(void); +void build_ehash_secret(void); static inline unsigned int inet_ehashfn(struct net *net, const __be32 laddr, const __u16 lport, diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index f908dfc06505..828200ab1125 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -83,9 +83,9 @@ struct inet_timewait_death_row { int sysctl_max_tw_buckets; }; -extern void inet_twdr_hangman(unsigned long data); -extern void inet_twdr_twkill_work(struct work_struct *work); -extern void inet_twdr_twcal_tick(unsigned long data); +void inet_twdr_hangman(unsigned long data); +void inet_twdr_twkill_work(struct work_struct *work); +void inet_twdr_twcal_tick(unsigned long data); struct inet_bind_bucket; @@ -195,28 +195,27 @@ static inline __be32 sk_rcv_saddr(const struct sock *sk) return sk->__sk_common.skc_rcv_saddr; } -extern void inet_twsk_put(struct inet_timewait_sock *tw); +void inet_twsk_put(struct inet_timewait_sock *tw); -extern int inet_twsk_unhash(struct inet_timewait_sock *tw); +int inet_twsk_unhash(struct inet_timewait_sock *tw); -extern int inet_twsk_bind_unhash(struct inet_timewait_sock *tw, - struct inet_hashinfo *hashinfo); +int inet_twsk_bind_unhash(struct inet_timewait_sock *tw, + struct inet_hashinfo *hashinfo); -extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, - const int state); +struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, + const int state); -extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, - struct sock *sk, - struct inet_hashinfo *hashinfo); +void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, + struct inet_hashinfo *hashinfo); -extern void inet_twsk_schedule(struct inet_timewait_sock *tw, - struct inet_timewait_death_row *twdr, - const int timeo, const int timewait_len); -extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, - struct inet_timewait_death_row *twdr); +void inet_twsk_schedule(struct inet_timewait_sock *tw, + struct inet_timewait_death_row *twdr, + const int timeo, const int timewait_len); +void inet_twsk_deschedule(struct inet_timewait_sock *tw, + struct inet_timewait_death_row *twdr); -extern void inet_twsk_purge(struct inet_hashinfo *hashinfo, - struct inet_timewait_death_row *twdr, int family); +void inet_twsk_purge(struct inet_hashinfo *hashinfo, + struct inet_timewait_death_row *twdr, int family); static inline struct net *twsk_net(const struct inet_timewait_sock *twsk) diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 53f464d7cddc..f4e127af4e17 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -120,9 +120,9 @@ static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from } } -extern void inet_peer_base_init(struct inet_peer_base *); +void inet_peer_base_init(struct inet_peer_base *); -void inet_initpeers(void) __init; +void inet_initpeers(void) __init; #define INETPEER_METRICS_NEW (~(u32) 0) @@ -159,11 +159,11 @@ static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, } /* can be called from BH context or outside */ -extern void inet_putpeer(struct inet_peer *p); -extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); +void inet_putpeer(struct inet_peer *p); +bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); -extern void inetpeer_invalidate_tree(struct inet_peer_base *); -extern void inetpeer_invalidate_family(int family); +void inetpeer_invalidate_tree(struct inet_peer_base *); +void inetpeer_invalidate_family(int family); /* * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, -- cgit From 5c3a0fd7d0fc2985fcd540aa9d7656dcc2d57b41 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:42 -0700 Subject: ip*.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ip.h | 169 +++++++++++++++--------------- include/net/ip6_fib.h | 53 +++++----- include/net/ip6_route.h | 98 ++++++++---------- include/net/ip_fib.h | 61 ++++++----- include/net/ip_vs.h | 245 +++++++++++++++++++++---------------------- include/net/ipv6.h | 268 +++++++++++++++++++++--------------------------- 6 files changed, 416 insertions(+), 478 deletions(-) (limited to 'include') diff --git a/include/net/ip.h b/include/net/ip.h index 5e5268807a1c..c1f192b8cd0e 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -86,53 +86,51 @@ struct packet_type; struct rtable; struct sockaddr; -extern int igmp_mc_proc_init(void); +int igmp_mc_proc_init(void); /* * Functions provided by ip.c */ -extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, - __be32 saddr, __be32 daddr, - struct ip_options_rcu *opt); -extern int ip_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *orig_dev); -extern int ip_local_deliver(struct sk_buff *skb); -extern int ip_mr_input(struct sk_buff *skb); -extern int ip_output(struct sk_buff *skb); -extern int ip_mc_output(struct sk_buff *skb); -extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); -extern int ip_do_nat(struct sk_buff *skb); -extern void ip_send_check(struct iphdr *ip); -extern int __ip_local_out(struct sk_buff *skb); -extern int ip_local_out(struct sk_buff *skb); -extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl); -extern void ip_init(void); -extern int ip_append_data(struct sock *sk, struct flowi4 *fl4, - int getfrag(void *from, char *to, int offset, int len, - int odd, struct sk_buff *skb), - void *from, int len, int protolen, - struct ipcm_cookie *ipc, - struct rtable **rt, - unsigned int flags); -extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb); -extern ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, - int offset, size_t size, int flags); -extern struct sk_buff *__ip_make_skb(struct sock *sk, - struct flowi4 *fl4, - struct sk_buff_head *queue, - struct inet_cork *cork); -extern int ip_send_skb(struct net *net, struct sk_buff *skb); -extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); -extern void ip_flush_pending_frames(struct sock *sk); -extern struct sk_buff *ip_make_skb(struct sock *sk, - struct flowi4 *fl4, - int getfrag(void *from, char *to, int offset, int len, - int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, - struct ipcm_cookie *ipc, - struct rtable **rtp, - unsigned int flags); +int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, + __be32 saddr, __be32 daddr, + struct ip_options_rcu *opt); +int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, + struct net_device *orig_dev); +int ip_local_deliver(struct sk_buff *skb); +int ip_mr_input(struct sk_buff *skb); +int ip_output(struct sk_buff *skb); +int ip_mc_output(struct sk_buff *skb); +int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); +int ip_do_nat(struct sk_buff *skb); +void ip_send_check(struct iphdr *ip); +int __ip_local_out(struct sk_buff *skb); +int ip_local_out(struct sk_buff *skb); +int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl); +void ip_init(void); +int ip_append_data(struct sock *sk, struct flowi4 *fl4, + int getfrag(void *from, char *to, int offset, int len, + int odd, struct sk_buff *skb), + void *from, int len, int protolen, + struct ipcm_cookie *ipc, + struct rtable **rt, + unsigned int flags); +int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, + struct sk_buff *skb); +ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, + int offset, size_t size, int flags); +struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, + struct sk_buff_head *queue, + struct inet_cork *cork); +int ip_send_skb(struct net *net, struct sk_buff *skb); +int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); +void ip_flush_pending_frames(struct sock *sk); +struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4, + int getfrag(void *from, char *to, int offset, + int len, int odd, struct sk_buff *skb), + void *from, int length, int transhdrlen, + struct ipcm_cookie *ipc, struct rtable **rtp, + unsigned int flags); static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) { @@ -140,10 +138,9 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) } /* datagram.c */ -extern int ip4_datagram_connect(struct sock *sk, - struct sockaddr *uaddr, int addr_len); +int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); -extern void ip4_datagram_release_cb(struct sock *sk); +void ip4_datagram_release_cb(struct sock *sk); struct ip_reply_arg { struct kvec iov[1]; @@ -184,16 +181,16 @@ extern struct ipv4_config ipv4_config; #define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) #define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd) -extern unsigned long snmp_fold_field(void __percpu *mib[], int offt); +unsigned long snmp_fold_field(void __percpu *mib[], int offt); #if BITS_PER_LONG==32 -extern u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t sync_off); +u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t sync_off); #else static inline u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_off) { return snmp_fold_field(mib, offt); } #endif -extern int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align); +int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align); static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ]) { @@ -210,7 +207,7 @@ extern struct local_ports { seqlock_t lock; int range[2]; } sysctl_local_ports; -extern void inet_get_local_port_range(int *low, int *high); +void inet_get_local_port_range(int *low, int *high); extern unsigned long *sysctl_local_reserved_ports; static inline int inet_is_reserved_local_port(int port) @@ -231,9 +228,9 @@ extern int sysctl_ip_early_demux; /* From ip_output.c */ extern int sysctl_ip_dynaddr; -extern void ipfrag_init(void); +void ipfrag_init(void); -extern void ip_static_sysctl_init(void); +void ip_static_sysctl_init(void); static inline bool ip_is_fragment(const struct iphdr *iph) { @@ -262,7 +259,7 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) !(dst_metric_locked(dst, RTAX_MTU))); } -extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); +void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk) { @@ -390,7 +387,7 @@ static inline int sk_mc_loop(struct sock *sk) return 1; } -extern bool ip_call_ra_chain(struct sk_buff *skb); +bool ip_call_ra_chain(struct sk_buff *skb); /* * Functions provided by ip_fragment.c @@ -428,50 +425,52 @@ int ip_frag_nqueues(struct net *net); * Functions provided by ip_forward.c */ -extern int ip_forward(struct sk_buff *skb); +int ip_forward(struct sk_buff *skb); /* * Functions provided by ip_options.c */ -extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, - __be32 daddr, struct rtable *rt, int is_frag); -extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); -extern void ip_options_fragment(struct sk_buff *skb); -extern int ip_options_compile(struct net *net, - struct ip_options *opt, struct sk_buff *skb); -extern int ip_options_get(struct net *net, struct ip_options_rcu **optp, - unsigned char *data, int optlen); -extern int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, - unsigned char __user *data, int optlen); -extern void ip_options_undo(struct ip_options * opt); -extern void ip_forward_options(struct sk_buff *skb); -extern int ip_options_rcv_srr(struct sk_buff *skb); +void ip_options_build(struct sk_buff *skb, struct ip_options *opt, + __be32 daddr, struct rtable *rt, int is_frag); +int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); +void ip_options_fragment(struct sk_buff *skb); +int ip_options_compile(struct net *net, struct ip_options *opt, + struct sk_buff *skb); +int ip_options_get(struct net *net, struct ip_options_rcu **optp, + unsigned char *data, int optlen); +int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, + unsigned char __user *data, int optlen); +void ip_options_undo(struct ip_options *opt); +void ip_forward_options(struct sk_buff *skb); +int ip_options_rcv_srr(struct sk_buff *skb); /* * Functions provided by ip_sockglue.c */ -extern void ipv4_pktinfo_prepare(struct sk_buff *skb); -extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); -extern int ip_cmsg_send(struct net *net, - struct msghdr *msg, struct ipcm_cookie *ipc); -extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); -extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); -extern int compat_ip_setsockopt(struct sock *sk, int level, - int optname, char __user *optval, unsigned int optlen); -extern int compat_ip_getsockopt(struct sock *sk, int level, - int optname, char __user *optval, int __user *optlen); -extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); - -extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); -extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, - __be16 port, u32 info, u8 *payload); -extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, - u32 info); +void ipv4_pktinfo_prepare(struct sk_buff *skb); +void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); +int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc); +int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, + unsigned int optlen); +int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, + int __user *optlen); +int compat_ip_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen); +int compat_ip_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +int ip_ra_control(struct sock *sk, unsigned char on, + void (*destructor)(struct sock *)); + +int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); +void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, + u32 info, u8 *payload); +void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, + u32 info); #ifdef CONFIG_PROC_FS -extern int ip_misc_proc_init(void); +int ip_misc_proc_init(void); #endif #endif /* _IP_H */ diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 48ec25a7fcb6..eab88f0e2088 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -267,48 +267,41 @@ typedef struct rt6_info *(*pol_lookup_t)(struct net *, * exported functions */ -extern struct fib6_table *fib6_get_table(struct net *net, u32 id); -extern struct fib6_table *fib6_new_table(struct net *net, u32 id); -extern struct dst_entry *fib6_rule_lookup(struct net *net, - struct flowi6 *fl6, int flags, - pol_lookup_t lookup); +struct fib6_table *fib6_get_table(struct net *net, u32 id); +struct fib6_table *fib6_new_table(struct net *net, u32 id); +struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, + int flags, pol_lookup_t lookup); -extern struct fib6_node *fib6_lookup(struct fib6_node *root, - const struct in6_addr *daddr, - const struct in6_addr *saddr); +struct fib6_node *fib6_lookup(struct fib6_node *root, + const struct in6_addr *daddr, + const struct in6_addr *saddr); -struct fib6_node *fib6_locate(struct fib6_node *root, - const struct in6_addr *daddr, int dst_len, - const struct in6_addr *saddr, int src_len); +struct fib6_node *fib6_locate(struct fib6_node *root, + const struct in6_addr *daddr, int dst_len, + const struct in6_addr *saddr, int src_len); -extern void fib6_clean_all_ro(struct net *net, - int (*func)(struct rt6_info *, void *arg), - int prune, void *arg); +void fib6_clean_all_ro(struct net *net, + int (*func)(struct rt6_info *, void *arg), + int prune, void *arg); -extern void fib6_clean_all(struct net *net, - int (*func)(struct rt6_info *, void *arg), - int prune, void *arg); +void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), + int prune, void *arg); -extern int fib6_add(struct fib6_node *root, - struct rt6_info *rt, - struct nl_info *info); +int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info); -extern int fib6_del(struct rt6_info *rt, - struct nl_info *info); +int fib6_del(struct rt6_info *rt, struct nl_info *info); -extern void inet6_rt_notify(int event, struct rt6_info *rt, - struct nl_info *info); +void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info); -extern void fib6_run_gc(unsigned long expires, - struct net *net, bool force); +void fib6_run_gc(unsigned long expires, struct net *net, bool force); -extern void fib6_gc_cleanup(void); +void fib6_gc_cleanup(void); -extern int fib6_init(void); +int fib6_init(void); #ifdef CONFIG_IPV6_MULTIPLE_TABLES -extern int fib6_rules_init(void); -extern void fib6_rules_cleanup(void); +int fib6_rules_init(void); +void fib6_rules_cleanup(void); #else static inline int fib6_rules_init(void) { diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index f525e7038cca..02e220dc4cf5 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -51,7 +51,7 @@ static inline unsigned int rt6_flags2srcprefs(int flags) return (flags >> 3) & 7; } -extern void rt6_bind_peer(struct rt6_info *rt, int create); +void rt6_bind_peer(struct rt6_info *rt, int create); static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create) { @@ -72,70 +72,58 @@ static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt) return __rt6_get_peer(rt, 1); } -extern void ip6_route_input(struct sk_buff *skb); +void ip6_route_input(struct sk_buff *skb); -extern struct dst_entry * ip6_route_output(struct net *net, - const struct sock *sk, - struct flowi6 *fl6); -extern struct dst_entry * ip6_route_lookup(struct net *net, - struct flowi6 *fl6, int flags); +struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, + struct flowi6 *fl6); +struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, + int flags); -extern int ip6_route_init(void); -extern void ip6_route_cleanup(void); +int ip6_route_init(void); +void ip6_route_cleanup(void); -extern int ipv6_route_ioctl(struct net *net, - unsigned int cmd, - void __user *arg); +int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg); -extern int ip6_route_add(struct fib6_config *cfg); -extern int ip6_ins_rt(struct rt6_info *); -extern int ip6_del_rt(struct rt6_info *); +int ip6_route_add(struct fib6_config *cfg); +int ip6_ins_rt(struct rt6_info *); +int ip6_del_rt(struct rt6_info *); -extern int ip6_route_get_saddr(struct net *net, - struct rt6_info *rt, - const struct in6_addr *daddr, - unsigned int prefs, - struct in6_addr *saddr); +int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, + const struct in6_addr *daddr, unsigned int prefs, + struct in6_addr *saddr); -extern struct rt6_info *rt6_lookup(struct net *net, - const struct in6_addr *daddr, - const struct in6_addr *saddr, - int oif, int flags); +struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, + const struct in6_addr *saddr, int oif, int flags); -extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, - struct flowi6 *fl6); -extern int icmp6_dst_gc(void); +struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct flowi6 *fl6); +int icmp6_dst_gc(void); -extern void fib6_force_start_gc(struct net *net); +void fib6_force_start_gc(struct net *net); -extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, - const struct in6_addr *addr, - bool anycast); +struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, + const struct in6_addr *addr, bool anycast); /* * support functions for ND * */ -extern struct rt6_info * rt6_get_dflt_router(const struct in6_addr *addr, - struct net_device *dev); -extern struct rt6_info * rt6_add_dflt_router(const struct in6_addr *gwaddr, - struct net_device *dev, - unsigned int pref); - -extern void rt6_purge_dflt_routers(struct net *net); - -extern int rt6_route_rcv(struct net_device *dev, - u8 *opt, int len, - const struct in6_addr *gwaddr); - -extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark); -extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, - __be32 mtu); -extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); -extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, - u32 mark); -extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); +struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, + struct net_device *dev); +struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, + struct net_device *dev, unsigned int pref); + +void rt6_purge_dflt_routers(struct net *net); + +int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + const struct in6_addr *gwaddr); + +void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif, + u32 mark); +void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); +void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); +void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, + u32 mark); +void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); struct netlink_callback; @@ -145,10 +133,10 @@ struct rt6_rtnl_dump_arg { struct net *net; }; -extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); -extern void rt6_ifdown(struct net *net, struct net_device *dev); -extern void rt6_mtu_change(struct net_device *dev, unsigned int mtu); -extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); +int rt6_dump_route(struct rt6_info *rt, void *p_arg); +void rt6_ifdown(struct net *net, struct net_device *dev); +void rt6_mtu_change(struct net_device *dev, unsigned int mtu); +void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); /* diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index cbf2be37c91a..9922093f575e 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -165,7 +165,7 @@ struct fib_result_nl { #define FIB_TABLE_HASHSZ 2 #endif -extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh); +__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh); #define FIB_RES_SADDR(net, res) \ ((FIB_RES_NH(res).nh_saddr_genid == \ @@ -187,14 +187,14 @@ struct fib_table { unsigned long tb_data[0]; }; -extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, - struct fib_result *res, int fib_flags); -extern int fib_table_insert(struct fib_table *, struct fib_config *); -extern int fib_table_delete(struct fib_table *, struct fib_config *); -extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb, - struct netlink_callback *cb); -extern int fib_table_flush(struct fib_table *table); -extern void fib_free_table(struct fib_table *tb); +int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, + struct fib_result *res, int fib_flags); +int fib_table_insert(struct fib_table *, struct fib_config *); +int fib_table_delete(struct fib_table *, struct fib_config *); +int fib_table_dump(struct fib_table *table, struct sk_buff *skb, + struct netlink_callback *cb); +int fib_table_flush(struct fib_table *table); +void fib_free_table(struct fib_table *tb); @@ -234,14 +234,13 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp, } #else /* CONFIG_IP_MULTIPLE_TABLES */ -extern int __net_init fib4_rules_init(struct net *net); -extern void __net_exit fib4_rules_exit(struct net *net); +int __net_init fib4_rules_init(struct net *net); +void __net_exit fib4_rules_exit(struct net *net); -extern struct fib_table *fib_new_table(struct net *net, u32 id); -extern struct fib_table *fib_get_table(struct net *net, u32 id); +struct fib_table *fib_new_table(struct net *net, u32 id); +struct fib_table *fib_get_table(struct net *net, u32 id); -extern int __fib_lookup(struct net *net, struct flowi4 *flp, - struct fib_result *res); +int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res); static inline int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) @@ -269,12 +268,12 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp, /* Exported by fib_frontend.c */ extern const struct nla_policy rtm_ipv4_policy[]; -extern void ip_fib_init(void); -extern __be32 fib_compute_spec_dst(struct sk_buff *skb); -extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, - u8 tos, int oif, struct net_device *dev, - struct in_device *idev, u32 *itag); -extern void fib_select_default(struct fib_result *res); +void ip_fib_init(void); +__be32 fib_compute_spec_dst(struct sk_buff *skb); +int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, + u8 tos, int oif, struct net_device *dev, + struct in_device *idev, u32 *itag); +void fib_select_default(struct fib_result *res); #ifdef CONFIG_IP_ROUTE_CLASSID static inline int fib_num_tclassid_users(struct net *net) { @@ -288,15 +287,15 @@ static inline int fib_num_tclassid_users(struct net *net) #endif /* Exported by fib_semantics.c */ -extern int ip_fib_check_default(__be32 gw, struct net_device *dev); -extern int fib_sync_down_dev(struct net_device *dev, int force); -extern int fib_sync_down_addr(struct net *net, __be32 local); -extern int fib_sync_up(struct net_device *dev); -extern void fib_select_multipath(struct fib_result *res); +int ip_fib_check_default(__be32 gw, struct net_device *dev); +int fib_sync_down_dev(struct net_device *dev, int force); +int fib_sync_down_addr(struct net *net, __be32 local); +int fib_sync_up(struct net_device *dev); +void fib_select_multipath(struct fib_result *res); /* Exported by fib_trie.c */ -extern void fib_trie_init(void); -extern struct fib_table *fib_trie_table(u32 id); +void fib_trie_init(void); +struct fib_table *fib_trie_table(u32 id); static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) { @@ -314,7 +313,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) #endif } -extern void free_fib_info(struct fib_info *fi); +void free_fib_info(struct fib_info *fi); static inline void fib_info_put(struct fib_info *fi) { @@ -323,8 +322,8 @@ static inline void fib_info_put(struct fib_info *fi) } #ifdef CONFIG_PROC_FS -extern int __net_init fib_proc_init(struct net *net); -extern void __net_exit fib_proc_exit(struct net *net); +int __net_init fib_proc_init(struct net *net); +void __net_exit fib_proc_exit(struct net *net); #else static inline int fib_proc_init(struct net *net) { diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index f0d70f066f3d..b6fd378c09c8 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -236,7 +236,7 @@ static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a, #ifdef CONFIG_IP_VS_DEBUG #include -extern int ip_vs_get_debug_level(void); +int ip_vs_get_debug_level(void); static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len, const union nf_inet_addr *addr, @@ -532,9 +532,9 @@ struct ip_vs_proto_data { struct tcp_states_t *tcp_state_table; }; -extern struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto); -extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net, - unsigned short proto); +struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto); +struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net, + unsigned short proto); struct ip_vs_conn_param { struct net *net; @@ -1176,8 +1176,8 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs) * IPVS core functions * (from ip_vs_core.c) */ -extern const char *ip_vs_proto_name(unsigned int proto); -extern void ip_vs_init_hash_table(struct list_head *table, int rows); +const char *ip_vs_proto_name(unsigned int proto); +void ip_vs_init_hash_table(struct list_head *table, int rows); #define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t))) #define IP_VS_APP_TYPE_FTP 1 @@ -1240,22 +1240,22 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp) smp_mb__before_atomic_dec(); atomic_dec(&cp->refcnt); } -extern void ip_vs_conn_put(struct ip_vs_conn *cp); -extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); +void ip_vs_conn_put(struct ip_vs_conn *cp); +void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, const union nf_inet_addr *daddr, __be16 dport, unsigned int flags, struct ip_vs_dest *dest, __u32 fwmark); -extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp); +void ip_vs_conn_expire_now(struct ip_vs_conn *cp); -extern const char * ip_vs_state_name(__u16 proto, int state); +const char *ip_vs_state_name(__u16 proto, int state); -extern void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp); -extern int ip_vs_check_template(struct ip_vs_conn *ct); -extern void ip_vs_random_dropentry(struct net *net); -extern int ip_vs_conn_init(void); -extern void ip_vs_conn_cleanup(void); +void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp); +int ip_vs_check_template(struct ip_vs_conn *ct); +void ip_vs_random_dropentry(struct net *net); +int ip_vs_conn_init(void); +void ip_vs_conn_cleanup(void); static inline void ip_vs_control_del(struct ip_vs_conn *cp) { @@ -1320,37 +1320,36 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) /* * IPVS netns init & cleanup functions */ -extern int ip_vs_estimator_net_init(struct net *net); -extern int ip_vs_control_net_init(struct net *net); -extern int ip_vs_protocol_net_init(struct net *net); -extern int ip_vs_app_net_init(struct net *net); -extern int ip_vs_conn_net_init(struct net *net); -extern int ip_vs_sync_net_init(struct net *net); -extern void ip_vs_conn_net_cleanup(struct net *net); -extern void ip_vs_app_net_cleanup(struct net *net); -extern void ip_vs_protocol_net_cleanup(struct net *net); -extern void ip_vs_control_net_cleanup(struct net *net); -extern void ip_vs_estimator_net_cleanup(struct net *net); -extern void ip_vs_sync_net_cleanup(struct net *net); -extern void ip_vs_service_net_cleanup(struct net *net); +int ip_vs_estimator_net_init(struct net *net); +int ip_vs_control_net_init(struct net *net); +int ip_vs_protocol_net_init(struct net *net); +int ip_vs_app_net_init(struct net *net); +int ip_vs_conn_net_init(struct net *net); +int ip_vs_sync_net_init(struct net *net); +void ip_vs_conn_net_cleanup(struct net *net); +void ip_vs_app_net_cleanup(struct net *net); +void ip_vs_protocol_net_cleanup(struct net *net); +void ip_vs_control_net_cleanup(struct net *net); +void ip_vs_estimator_net_cleanup(struct net *net); +void ip_vs_sync_net_cleanup(struct net *net); +void ip_vs_service_net_cleanup(struct net *net); /* * IPVS application functions * (from ip_vs_app.c) */ #define IP_VS_APP_MAX_PORTS 8 -extern struct ip_vs_app *register_ip_vs_app(struct net *net, - struct ip_vs_app *app); -extern void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app); -extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern void ip_vs_unbind_app(struct ip_vs_conn *cp); -extern int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, - __u16 proto, __u16 port); -extern int ip_vs_app_inc_get(struct ip_vs_app *inc); -extern void ip_vs_app_inc_put(struct ip_vs_app *inc); - -extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb); -extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb); +struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app); +void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app); +int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp); +void ip_vs_unbind_app(struct ip_vs_conn *cp); +int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, + __u16 port); +int ip_vs_app_inc_get(struct ip_vs_app *inc); +void ip_vs_app_inc_put(struct ip_vs_app *inc); + +int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb); +int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb); int register_ip_vs_pe(struct ip_vs_pe *pe); int unregister_ip_vs_pe(struct ip_vs_pe *pe); @@ -1371,17 +1370,15 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name); /* * IPVS protocol functions (from ip_vs_proto.c) */ -extern int ip_vs_protocol_init(void); -extern void ip_vs_protocol_cleanup(void); -extern void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags); -extern int *ip_vs_create_timeout_table(int *table, int size); -extern int -ip_vs_set_state_timeout(int *table, int num, const char *const *names, - const char *name, int to); -extern void -ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, - const struct sk_buff *skb, - int offset, const char *msg); +int ip_vs_protocol_init(void); +void ip_vs_protocol_cleanup(void); +void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags); +int *ip_vs_create_timeout_table(int *table, int size); +int ip_vs_set_state_timeout(int *table, int num, const char *const *names, + const char *name, int to); +void ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, + const struct sk_buff *skb, int offset, + const char *msg); extern struct ip_vs_protocol ip_vs_protocol_tcp; extern struct ip_vs_protocol ip_vs_protocol_udp; @@ -1394,22 +1391,22 @@ extern struct ip_vs_protocol ip_vs_protocol_sctp; * Registering/unregistering scheduler functions * (from ip_vs_sched.c) */ -extern int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); -extern int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); -extern int ip_vs_bind_scheduler(struct ip_vs_service *svc, - struct ip_vs_scheduler *scheduler); -extern void ip_vs_unbind_scheduler(struct ip_vs_service *svc, - struct ip_vs_scheduler *sched); -extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name); -extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler); -extern struct ip_vs_conn * +int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); +int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); +int ip_vs_bind_scheduler(struct ip_vs_service *svc, + struct ip_vs_scheduler *scheduler); +void ip_vs_unbind_scheduler(struct ip_vs_service *svc, + struct ip_vs_scheduler *sched); +struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name); +void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler); +struct ip_vs_conn * ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, struct ip_vs_proto_data *pd, int *ignored, struct ip_vs_iphdr *iph); -extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, - struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph); +int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, + struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph); -extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); +void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); /* @@ -1418,25 +1415,24 @@ extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); extern struct ip_vs_stats ip_vs_stats; extern int sysctl_ip_vs_sync_ver; -extern struct ip_vs_service * +struct ip_vs_service * ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol, const union nf_inet_addr *vaddr, __be16 vport); -extern bool -ip_vs_has_real_service(struct net *net, int af, __u16 protocol, - const union nf_inet_addr *daddr, __be16 dport); - -extern int ip_vs_use_count_inc(void); -extern void ip_vs_use_count_dec(void); -extern int ip_vs_register_nl_ioctl(void); -extern void ip_vs_unregister_nl_ioctl(void); -extern int ip_vs_control_init(void); -extern void ip_vs_control_cleanup(void); -extern struct ip_vs_dest * +bool ip_vs_has_real_service(struct net *net, int af, __u16 protocol, + const union nf_inet_addr *daddr, __be16 dport); + +int ip_vs_use_count_inc(void); +void ip_vs_use_count_dec(void); +int ip_vs_register_nl_ioctl(void); +void ip_vs_unregister_nl_ioctl(void); +int ip_vs_control_init(void); +void ip_vs_control_cleanup(void); +struct ip_vs_dest * ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol, __u32 fwmark, __u32 flags); -extern void ip_vs_try_bind_dest(struct ip_vs_conn *cp); +void ip_vs_try_bind_dest(struct ip_vs_conn *cp); static inline void ip_vs_dest_hold(struct ip_vs_dest *dest) { @@ -1453,56 +1449,49 @@ static inline void ip_vs_dest_put(struct ip_vs_dest *dest) * IPVS sync daemon data and function prototypes * (from ip_vs_sync.c) */ -extern int start_sync_thread(struct net *net, int state, char *mcast_ifn, - __u8 syncid); -extern int stop_sync_thread(struct net *net, int state); -extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); - +int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid); +int stop_sync_thread(struct net *net, int state); +void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); /* * IPVS rate estimator prototypes (from ip_vs_est.c) */ -extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); -extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); -extern void ip_vs_zero_estimator(struct ip_vs_stats *stats); -extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst, - struct ip_vs_stats *stats); +void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); +void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); +void ip_vs_zero_estimator(struct ip_vs_stats *stats); +void ip_vs_read_estimator(struct ip_vs_stats_user *dst, + struct ip_vs_stats *stats); /* * Various IPVS packet transmitters (from ip_vs_xmit.c) */ -extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); -extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, - struct ip_vs_iphdr *iph); -extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); -extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, - struct ip_vs_iphdr *iph); -extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); -extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset, - unsigned int hooknum, struct ip_vs_iphdr *iph); -extern void ip_vs_dest_dst_rcu_free(struct rcu_head *head); +int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, int offset, + unsigned int hooknum, struct ip_vs_iphdr *iph); +void ip_vs_dest_dst_rcu_free(struct rcu_head *head); #ifdef CONFIG_IP_VS_IPV6 -extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, - struct ip_vs_iphdr *iph); -extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, - struct ip_vs_iphdr *iph); -extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, - struct ip_vs_iphdr *iph); -extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); -extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset, - unsigned int hooknum, struct ip_vs_iphdr *iph); +int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, int offset, + unsigned int hooknum, struct ip_vs_iphdr *iph); #endif #ifdef CONFIG_SYSCTL @@ -1551,15 +1540,15 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) return fwd; } -extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, - struct ip_vs_conn *cp, int dir); +void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, + struct ip_vs_conn *cp, int dir); #ifdef CONFIG_IP_VS_IPV6 -extern void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, - struct ip_vs_conn *cp, int dir); +void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, + struct ip_vs_conn *cp, int dir); #endif -extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); +__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum) { @@ -1618,13 +1607,13 @@ static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs) #endif } -extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, - int outin); -extern int ip_vs_confirm_conntrack(struct sk_buff *skb); -extern void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct, - struct ip_vs_conn *cp, u_int8_t proto, - const __be16 port, int from_rs); -extern void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp); +void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, + int outin); +int ip_vs_confirm_conntrack(struct sk_buff *skb); +void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct, + struct ip_vs_conn *cp, u_int8_t proto, + const __be16 port, int from_rs); +void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp); #else diff --git a/include/net/ipv6.h b/include/net/ipv6.h index bbf1c8fb8511..fe1c7f6c9217 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -244,14 +244,14 @@ struct ipv6_fl_socklist { struct rcu_head rcu; }; -extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); -extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, - struct ip6_flowlabel * fl, - struct ipv6_txoptions * fopt); -extern void fl6_free_socklist(struct sock *sk); -extern int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen); -extern int ip6_flowlabel_init(void); -extern void ip6_flowlabel_cleanup(void); +struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); +struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, + struct ip6_flowlabel *fl, + struct ipv6_txoptions *fopt); +void fl6_free_socklist(struct sock *sk); +int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen); +int ip6_flowlabel_init(void); +void ip6_flowlabel_cleanup(void); static inline void fl6_sock_release(struct ip6_flowlabel *fl) { @@ -259,7 +259,7 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) atomic_dec(&fl->users); } -extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); +void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len); @@ -267,19 +267,21 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, struct sock *sk, struct flowi6 *fl6); -extern int ip6_ra_control(struct sock *sk, int sel); +int ip6_ra_control(struct sock *sk, int sel); -extern int ipv6_parse_hopopts(struct sk_buff *skb); +int ipv6_parse_hopopts(struct sk_buff *skb); -extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); -extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, - int newtype, - struct ipv6_opt_hdr __user *newopt, - int newoptlen); +struct ipv6_txoptions *ipv6_dup_options(struct sock *sk, + struct ipv6_txoptions *opt); +struct ipv6_txoptions *ipv6_renew_options(struct sock *sk, + struct ipv6_txoptions *opt, + int newtype, + struct ipv6_opt_hdr __user *newopt, + int newoptlen); struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, struct ipv6_txoptions *opt); -extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb); +bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb); static inline bool ipv6_accept_ra(struct inet6_dev *idev) { @@ -306,7 +308,7 @@ static inline int ip6_frag_mem(struct net *net) #define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */ #define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */ -extern int __ipv6_addr_type(const struct in6_addr *addr); +int __ipv6_addr_type(const struct in6_addr *addr); static inline int ipv6_addr_type(const struct in6_addr *addr) { return __ipv6_addr_type(addr) & 0xffff; @@ -656,9 +658,9 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); } -extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); +void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); -extern int ip6_dst_hoplimit(struct dst_entry *dst); +int ip6_dst_hoplimit(struct dst_entry *dst); /* * Header manipulation @@ -682,83 +684,65 @@ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) * rcv function (called from netdevice level) */ -extern int ipv6_rcv(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev); +int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev); -extern int ip6_rcv_finish(struct sk_buff *skb); +int ip6_rcv_finish(struct sk_buff *skb); /* * upper-layer output functions */ -extern int ip6_xmit(struct sock *sk, - struct sk_buff *skb, - struct flowi6 *fl6, - struct ipv6_txoptions *opt, - int tclass); - -extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); - -extern int ip6_append_data(struct sock *sk, - int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, - int length, - int transhdrlen, - int hlimit, - int tclass, - struct ipv6_txoptions *opt, - struct flowi6 *fl6, - struct rt6_info *rt, - unsigned int flags, - int dontfrag); - -extern int ip6_push_pending_frames(struct sock *sk); - -extern void ip6_flush_pending_frames(struct sock *sk); - -extern int ip6_dst_lookup(struct sock *sk, - struct dst_entry **dst, - struct flowi6 *fl6); -extern struct dst_entry * ip6_dst_lookup_flow(struct sock *sk, - struct flowi6 *fl6, - const struct in6_addr *final_dst, - bool can_sleep); -extern struct dst_entry * ip6_sk_dst_lookup_flow(struct sock *sk, - struct flowi6 *fl6, - const struct in6_addr *final_dst, - bool can_sleep); -extern struct dst_entry * ip6_blackhole_route(struct net *net, - struct dst_entry *orig_dst); +int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + struct ipv6_txoptions *opt, int tclass); + +int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); + +int ip6_append_data(struct sock *sk, + int getfrag(void *from, char *to, int offset, int len, + int odd, struct sk_buff *skb), + void *from, int length, int transhdrlen, int hlimit, + int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, + struct rt6_info *rt, unsigned int flags, int dontfrag); + +int ip6_push_pending_frames(struct sock *sk); + +void ip6_flush_pending_frames(struct sock *sk); + +int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6); +struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + const struct in6_addr *final_dst, + bool can_sleep); +struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + const struct in6_addr *final_dst, + bool can_sleep); +struct dst_entry *ip6_blackhole_route(struct net *net, + struct dst_entry *orig_dst); /* * skb processing functions */ -extern int ip6_output(struct sk_buff *skb); -extern int ip6_forward(struct sk_buff *skb); -extern int ip6_input(struct sk_buff *skb); -extern int ip6_mc_input(struct sk_buff *skb); +int ip6_output(struct sk_buff *skb); +int ip6_forward(struct sk_buff *skb); +int ip6_input(struct sk_buff *skb); +int ip6_mc_input(struct sk_buff *skb); -extern int __ip6_local_out(struct sk_buff *skb); -extern int ip6_local_out(struct sk_buff *skb); +int __ip6_local_out(struct sk_buff *skb); +int ip6_local_out(struct sk_buff *skb); /* * Extension header (options) processing */ -extern void ipv6_push_nfrag_opts(struct sk_buff *skb, - struct ipv6_txoptions *opt, - u8 *proto, - struct in6_addr **daddr_p); -extern void ipv6_push_frag_opts(struct sk_buff *skb, - struct ipv6_txoptions *opt, - u8 *proto); +void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, + u8 *proto, struct in6_addr **daddr_p); +void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, + u8 *proto); -extern int ipv6_skip_exthdr(const struct sk_buff *, int start, - u8 *nexthdrp, __be16 *frag_offp); +int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp, + __be16 *frag_offp); -extern bool ipv6_ext_hdr(u8 nexthdr); +bool ipv6_ext_hdr(u8 nexthdr); enum { IP6_FH_F_FRAG = (1 << 0), @@ -767,57 +751,44 @@ enum { }; /* find specified header and get offset to it */ -extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, - int target, unsigned short *fragoff, int *fragflg); +int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, + unsigned short *fragoff, int *fragflg); -extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); +int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); -extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6, - const struct ipv6_txoptions *opt, - struct in6_addr *orig); +struct in6_addr *fl6_update_dst(struct flowi6 *fl6, + const struct ipv6_txoptions *opt, + struct in6_addr *orig); /* * socket options (ipv6_sockglue.c) */ -extern int ipv6_setsockopt(struct sock *sk, int level, - int optname, - char __user *optval, - unsigned int optlen); -extern int ipv6_getsockopt(struct sock *sk, int level, - int optname, - char __user *optval, - int __user *optlen); -extern int compat_ipv6_setsockopt(struct sock *sk, - int level, - int optname, - char __user *optval, - unsigned int optlen); -extern int compat_ipv6_getsockopt(struct sock *sk, - int level, - int optname, - char __user *optval, - int __user *optlen); - -extern int ip6_datagram_connect(struct sock *sk, - struct sockaddr *addr, int addr_len); - -extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); -extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); -extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, - u32 info, u8 *payload); -extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); -extern void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu); - -extern int inet6_release(struct socket *sock); -extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr, - int addr_len); -extern int inet6_getname(struct socket *sock, struct sockaddr *uaddr, - int *uaddr_len, int peer); -extern int inet6_ioctl(struct socket *sock, unsigned int cmd, - unsigned long arg); - -extern int inet6_hash_connect(struct inet_timewait_death_row *death_row, +int ipv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen); +int ipv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen); +int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); + +int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len); + +int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); +int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); +void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, + u32 info, u8 *payload); +void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); +void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu); + +int inet6_release(struct socket *sock); +int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); +int inet6_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, + int peer); +int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); + +int inet6_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); /* @@ -829,30 +800,29 @@ extern const struct proto_ops inet6_dgram_ops; struct group_source_req; struct group_filter; -extern int ip6_mc_source(int add, int omode, struct sock *sk, - struct group_source_req *pgsr); -extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); -extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, - struct group_filter __user *optval, - int __user *optlen); -extern unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, - const struct in6_addr *daddr, u32 rnd); +int ip6_mc_source(int add, int omode, struct sock *sk, + struct group_source_req *pgsr); +int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); +int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, + struct group_filter __user *optval, int __user *optlen); +unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, + const struct in6_addr *daddr, u32 rnd); #ifdef CONFIG_PROC_FS -extern int ac6_proc_init(struct net *net); -extern void ac6_proc_exit(struct net *net); -extern int raw6_proc_init(void); -extern void raw6_proc_exit(void); -extern int tcp6_proc_init(struct net *net); -extern void tcp6_proc_exit(struct net *net); -extern int udp6_proc_init(struct net *net); -extern void udp6_proc_exit(struct net *net); -extern int udplite6_proc_init(void); -extern void udplite6_proc_exit(void); -extern int ipv6_misc_proc_init(void); -extern void ipv6_misc_proc_exit(void); -extern int snmp6_register_dev(struct inet6_dev *idev); -extern int snmp6_unregister_dev(struct inet6_dev *idev); +int ac6_proc_init(struct net *net); +void ac6_proc_exit(struct net *net); +int raw6_proc_init(void); +void raw6_proc_exit(void); +int tcp6_proc_init(struct net *net); +void tcp6_proc_exit(struct net *net); +int udp6_proc_init(struct net *net); +void udp6_proc_exit(struct net *net); +int udplite6_proc_init(void); +void udplite6_proc_exit(void); +int ipv6_misc_proc_init(void); +void ipv6_misc_proc_exit(void); +int snmp6_register_dev(struct inet6_dev *idev); +int snmp6_unregister_dev(struct inet6_dev *idev); #else static inline int ac6_proc_init(struct net *net) { return 0; } @@ -865,10 +835,10 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; } extern struct ctl_table ipv6_route_table_template[]; extern struct ctl_table ipv6_icmp_table_template[]; -extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); -extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); -extern int ipv6_sysctl_register(void); -extern void ipv6_sysctl_unregister(void); +struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); +struct ctl_table *ipv6_route_sysctl_init(struct net *net); +int ipv6_sysctl_register(void); +void ipv6_sysctl_unregister(void); #endif #endif /* _NET_IPV6_H */ -- cgit From 9d03626a28fd8c14511c96826cb4ca2112fb7709 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:43 -0700 Subject: ipx.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ipx.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/ipx.h b/include/net/ipx.h index c1fec6b464cc..9e9e35465baf 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -123,23 +123,23 @@ extern struct list_head ipx_routes; extern rwlock_t ipx_routes_lock; extern struct list_head ipx_interfaces; -extern struct ipx_interface *ipx_interfaces_head(void); +struct ipx_interface *ipx_interfaces_head(void); extern spinlock_t ipx_interfaces_lock; extern struct ipx_interface *ipx_primary_net; -extern int ipx_proc_init(void); -extern void ipx_proc_exit(void); +int ipx_proc_init(void); +void ipx_proc_exit(void); -extern const char *ipx_frame_name(__be16); -extern const char *ipx_device_name(struct ipx_interface *intrfc); +const char *ipx_frame_name(__be16); +const char *ipx_device_name(struct ipx_interface *intrfc); static __inline__ void ipxitf_hold(struct ipx_interface *intrfc) { atomic_inc(&intrfc->refcnt); } -extern void ipxitf_down(struct ipx_interface *intrfc); +void ipxitf_down(struct ipx_interface *intrfc); static __inline__ void ipxitf_put(struct ipx_interface *intrfc) { -- cgit From cb7d3d71e986067d19d991d75bff07ca304c9084 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:44 -0700 Subject: lapb.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/lapb.h | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/include/net/lapb.h b/include/net/lapb.h index df892a94f2c6..9510f8725f03 100644 --- a/include/net/lapb.h +++ b/include/net/lapb.h @@ -105,40 +105,40 @@ struct lapb_cb { }; /* lapb_iface.c */ -extern void lapb_connect_confirmation(struct lapb_cb *lapb, int); -extern void lapb_connect_indication(struct lapb_cb *lapb, int); -extern void lapb_disconnect_confirmation(struct lapb_cb *lapb, int); -extern void lapb_disconnect_indication(struct lapb_cb *lapb, int); -extern int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *); -extern int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *); +void lapb_connect_confirmation(struct lapb_cb *lapb, int); +void lapb_connect_indication(struct lapb_cb *lapb, int); +void lapb_disconnect_confirmation(struct lapb_cb *lapb, int); +void lapb_disconnect_indication(struct lapb_cb *lapb, int); +int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *); +int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *); /* lapb_in.c */ -extern void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *); +void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *); /* lapb_out.c */ -extern void lapb_kick(struct lapb_cb *lapb); -extern void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int); -extern void lapb_establish_data_link(struct lapb_cb *lapb); -extern void lapb_enquiry_response(struct lapb_cb *lapb); -extern void lapb_timeout_response(struct lapb_cb *lapb); -extern void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short); -extern void lapb_check_need_response(struct lapb_cb *lapb, int, int); +void lapb_kick(struct lapb_cb *lapb); +void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int); +void lapb_establish_data_link(struct lapb_cb *lapb); +void lapb_enquiry_response(struct lapb_cb *lapb); +void lapb_timeout_response(struct lapb_cb *lapb); +void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short); +void lapb_check_need_response(struct lapb_cb *lapb, int, int); /* lapb_subr.c */ -extern void lapb_clear_queues(struct lapb_cb *lapb); -extern void lapb_frames_acked(struct lapb_cb *lapb, unsigned short); -extern void lapb_requeue_frames(struct lapb_cb *lapb); -extern int lapb_validate_nr(struct lapb_cb *lapb, unsigned short); -extern int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *); -extern void lapb_send_control(struct lapb_cb *lapb, int, int, int); -extern void lapb_transmit_frmr(struct lapb_cb *lapb); +void lapb_clear_queues(struct lapb_cb *lapb); +void lapb_frames_acked(struct lapb_cb *lapb, unsigned short); +void lapb_requeue_frames(struct lapb_cb *lapb); +int lapb_validate_nr(struct lapb_cb *lapb, unsigned short); +int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *); +void lapb_send_control(struct lapb_cb *lapb, int, int, int); +void lapb_transmit_frmr(struct lapb_cb *lapb); /* lapb_timer.c */ -extern void lapb_start_t1timer(struct lapb_cb *lapb); -extern void lapb_start_t2timer(struct lapb_cb *lapb); -extern void lapb_stop_t1timer(struct lapb_cb *lapb); -extern void lapb_stop_t2timer(struct lapb_cb *lapb); -extern int lapb_t1timer_running(struct lapb_cb *lapb); +void lapb_start_t1timer(struct lapb_cb *lapb); +void lapb_start_t2timer(struct lapb_cb *lapb); +void lapb_stop_t1timer(struct lapb_cb *lapb); +void lapb_stop_t2timer(struct lapb_cb *lapb); +int lapb_t1timer_running(struct lapb_cb *lapb); /* * Debug levels. -- cgit From bf3c710f71a6144bd4d3bb9efb91099863debfb8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:45 -0700 Subject: llc*.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/llc.h | 50 ++++++------ include/net/llc_c_ac.h | 190 ++++++++++++++++++++------------------------- include/net/llc_c_ev.h | 207 +++++++++++++++++++------------------------------ include/net/llc_conn.h | 36 ++++----- include/net/llc_if.h | 7 +- include/net/llc_pdu.h | 33 ++++---- include/net/llc_s_ac.h | 20 +++-- include/net/llc_s_ev.h | 21 +++-- include/net/llc_sap.h | 22 +++--- 9 files changed, 253 insertions(+), 333 deletions(-) (limited to 'include') diff --git a/include/net/llc.h b/include/net/llc.h index 9e7d7f08ef77..68490cbc8a65 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -95,29 +95,29 @@ struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap, extern struct list_head llc_sap_list; extern spinlock_t llc_sap_list_lock; -extern int llc_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *orig_dev); +int llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, + struct net_device *orig_dev); -extern int llc_mac_hdr_init(struct sk_buff *skb, - const unsigned char *sa, const unsigned char *da); +int llc_mac_hdr_init(struct sk_buff *skb, const unsigned char *sa, + const unsigned char *da); -extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, - struct sk_buff *skb)); -extern void llc_remove_pack(int type); +void llc_add_pack(int type, + void (*handler)(struct llc_sap *sap, struct sk_buff *skb)); +void llc_remove_pack(int type); -extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb)); +void llc_set_station_handler(void (*handler)(struct sk_buff *skb)); -extern struct llc_sap *llc_sap_open(unsigned char lsap, - int (*rcv)(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev)); +struct llc_sap *llc_sap_open(unsigned char lsap, + int (*rcv)(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt, + struct net_device *orig_dev)); static inline void llc_sap_hold(struct llc_sap *sap) { atomic_inc(&sap->refcnt); } -extern void llc_sap_close(struct llc_sap *sap); +void llc_sap_close(struct llc_sap *sap); static inline void llc_sap_put(struct llc_sap *sap) { @@ -125,27 +125,27 @@ static inline void llc_sap_put(struct llc_sap *sap) llc_sap_close(sap); } -extern struct llc_sap *llc_sap_find(unsigned char sap_value); +struct llc_sap *llc_sap_find(unsigned char sap_value); -extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, - unsigned char *dmac, unsigned char dsap); +int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, + unsigned char *dmac, unsigned char dsap); -extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); +void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); +void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_station_init(void); -extern void llc_station_exit(void); +void llc_station_init(void); +void llc_station_exit(void); #ifdef CONFIG_PROC_FS -extern int llc_proc_init(void); -extern void llc_proc_exit(void); +int llc_proc_init(void); +void llc_proc_exit(void); #else #define llc_proc_init() (0) #define llc_proc_exit() do { } while(0) #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_SYSCTL -extern int llc_sysctl_init(void); -extern void llc_sysctl_exit(void); +int llc_sysctl_init(void); +void llc_sysctl_exit(void); extern int sysctl_llc2_ack_timeout; extern int sysctl_llc2_busy_timeout; diff --git a/include/net/llc_c_ac.h b/include/net/llc_c_ac.h index df83f69d2de4..f3be818e73c1 100644 --- a/include/net/llc_c_ac.h +++ b/include/net/llc_c_ac.h @@ -89,114 +89,92 @@ typedef int (*llc_conn_action_t)(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ac_conn_confirm(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_data_ind(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_disc_ind(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_rst_ind(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_rst_confirm(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_disc_cmd_p_set_x(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_dm_rsp_f_set_p(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_dm_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_i_cmd_p_set_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_send_i_xxx_x_set_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_resend_i_xxx_x_set_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_resend_i_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rej_cmd_p_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rej_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rej_xxx_x_set_0(struct sock* sk, +int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_data_ind(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_set_remote_busy(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock* sk, +int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ac_send_rr_cmd_p_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rr_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_ack_rsp_f_set_1(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_rr_xxx_x_set_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_ack_xxx_x_set_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_send_ua_rsp_f_set_p(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_set_s_flag_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_s_flag_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_start_p_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_start_ack_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_start_rej_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_start_ack_tmr_if_not_running(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_stop_ack_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_stop_p_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_stop_rej_timer(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_stop_all_timers(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_stop_other_timers(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_upd_nr_received(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_inc_tx_win_size(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_dec_tx_win_size(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_upd_p_flag(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_data_flag_2(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_data_flag_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_data_flag_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock* sk, - struct sk_buff *skb); -extern int llc_conn_ac_set_p_flag_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_remote_busy_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_retry_cnt_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_cause_flag_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_cause_flag_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_inc_retry_cnt_by_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_vr_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_inc_vr_by_1(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_vs_0(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_set_vs_nr(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_rst_vs(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_upd_vs(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_disc(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_reset(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_disc_confirm(struct sock* sk, struct sk_buff *skb); -extern u8 llc_circular_between(u8 a, u8 b, u8 c); -extern int llc_conn_ac_send_ack_if_needed(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_adjust_npta_by_rr(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_adjust_npta_by_rnr(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_rst_sendack_flag(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_send_i_rsp_as_ack(struct sock* sk, struct sk_buff *skb); -extern int llc_conn_ac_send_i_as_ack(struct sock* sk, struct sk_buff *skb); +int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_s_flag_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_data_flag_2(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_data_flag_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_data_flag_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_vr_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_vs_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb); +int llc_conn_disc(struct sock *sk, struct sk_buff *skb); +int llc_conn_reset(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb); +u8 llc_circular_between(u8 a, u8 b, u8 c); +int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_rst_sendack_flag(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_i_rsp_as_ack(struct sock *sk, struct sk_buff *skb); +int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb); -extern void llc_conn_busy_tmr_cb(unsigned long timeout_data); -extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data); -extern void llc_conn_ack_tmr_cb(unsigned long timeout_data); -extern void llc_conn_rej_tmr_cb(unsigned long timeout_data); +void llc_conn_busy_tmr_cb(unsigned long timeout_data); +void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data); +void llc_conn_ack_tmr_cb(unsigned long timeout_data); +void llc_conn_rej_tmr_cb(unsigned long timeout_data); -extern void llc_conn_set_p_flag(struct sock *sk, u8 value); +void llc_conn_set_p_flag(struct sock *sk, u8 value); #endif /* LLC_C_AC_H */ diff --git a/include/net/llc_c_ev.h b/include/net/llc_c_ev.h index 6ca3113df39e..3948cf111dd0 100644 --- a/include/net/llc_c_ev.h +++ b/include/net/llc_c_ev.h @@ -128,138 +128,93 @@ static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb) typedef int (*llc_conn_ev_t)(struct sock *sk, struct sk_buff *skb); typedef int (*llc_conn_ev_qfyr_t)(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_local_busy_detected(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, +int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, +int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_sendack_tmr_exp(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_sendack_tmr_exp(struct sock *sk, struct sk_buff *skb); /* NOT_USED functions and their variations */ -extern int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, + struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb); /* Available connection action qualifiers */ -extern int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, +int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk, struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, - struct sk_buff *skb); -extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, - struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb); +int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb); static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb) { diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index 2f97d8ddce92..0134681acc4c 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -95,28 +95,24 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) return skb->cb[sizeof(skb->cb) - 1]; } -extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, - struct proto *prot); -extern void llc_sk_free(struct sock *sk); +struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, + struct proto *prot); +void llc_sk_free(struct sock *sk); -extern void llc_sk_reset(struct sock *sk); +void llc_sk_reset(struct sock *sk); /* Access to a connection */ -extern int llc_conn_state_process(struct sock *sk, struct sk_buff *skb); -extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); -extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb); -extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, - u8 first_p_bit); -extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, - u8 first_f_bit); -extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, - u16 *how_many_unacked); -extern struct sock *llc_lookup_established(struct llc_sap *sap, - struct llc_addr *daddr, - struct llc_addr *laddr); -extern void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk); -extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk); +int llc_conn_state_process(struct sock *sk, struct sk_buff *skb); +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); +void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb); +void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit); +void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit); +int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, u16 *how_many_unacked); +struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, + struct llc_addr *laddr); +void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk); +void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk); -extern u8 llc_data_accept_state(u8 state); -extern void llc_build_offset_table(void); +u8 llc_data_accept_state(u8 state); +void llc_build_offset_table(void); #endif /* LLC_CONN_H */ diff --git a/include/net/llc_if.h b/include/net/llc_if.h index f0cb909b60eb..8d5c543cd620 100644 --- a/include/net/llc_if.h +++ b/include/net/llc_if.h @@ -62,8 +62,7 @@ #define LLC_STATUS_CONFLICT 7 /* disconnect conn */ #define LLC_STATUS_RESET_DONE 8 /* */ -extern int llc_establish_connection(struct sock *sk, u8 *lmac, - u8 *dmac, u8 dsap); -extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb); -extern int llc_send_disc(struct sock *sk); +int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap); +int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb); +int llc_send_disc(struct sock *sk); #endif /* LLC_IF_H */ diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h index 5a93d13ac95c..31e2de7d57c5 100644 --- a/include/net/llc_pdu.h +++ b/include/net/llc_pdu.h @@ -410,21 +410,20 @@ struct llc_frmr_info { u8 ind_bits; /* indicator bits set with macro */ } __packed; -extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type); -extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value); -extern void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit); -extern void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit); -extern void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr); -extern void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); -extern void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); -extern void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); -extern void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit); -extern void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit); -extern void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, - struct llc_pdu_sn *prev_pdu, - u8 f_bit, u8 vs, u8 vr, u8 vzyxw); -extern void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); -extern void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); -extern void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); -extern void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit); +void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type); +void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value); +void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit); +void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit); +void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr); +void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit); +void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit); +void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu, + u8 f_bit, u8 vs, u8 vr, u8 vzyxw); +void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit); #endif /* LLC_PDU_H */ diff --git a/include/net/llc_s_ac.h b/include/net/llc_s_ac.h index 37a3bbd02394..a61b98c108ee 100644 --- a/include/net/llc_s_ac.h +++ b/include/net/llc_s_ac.h @@ -25,15 +25,13 @@ /* All action functions must look like this */ typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_unitdata_ind(struct llc_sap *sap, - struct sk_buff *skb); -extern int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_report_status(struct llc_sap *sap, - struct sk_buff *skb); -extern int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb); #endif /* LLC_S_AC_H */ diff --git a/include/net/llc_s_ev.h b/include/net/llc_s_ev.h index e3acb9329e4a..84db3a59ed28 100644 --- a/include/net/llc_s_ev.h +++ b/include/net/llc_s_ev.h @@ -53,15 +53,14 @@ struct llc_sap; typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_sap_ev_deactivation_req(struct llc_sap *sap, - struct sk_buff *skb); +int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb); +int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb); #endif /* LLC_S_EV_H */ diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h index ed25bec2f648..1e4df9fd9fb2 100644 --- a/include/net/llc_sap.h +++ b/include/net/llc_sap.h @@ -19,18 +19,14 @@ struct net_device; struct sk_buff; struct sock; -extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, - unsigned char prim); -extern struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, - u8 type, u32 data_size); +void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); +void llc_save_primitive(struct sock *sk, struct sk_buff *skb, + unsigned char prim); +struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, + u8 type, u32 data_size); -extern void llc_build_and_send_test_pkt(struct llc_sap *sap, - struct sk_buff *skb, - unsigned char *dmac, - unsigned char dsap); -extern void llc_build_and_send_xid_pkt(struct llc_sap *sap, - struct sk_buff *skb, - unsigned char *dmac, - unsigned char dsap); +void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, + unsigned char *dmac, unsigned char dsap); +void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb, + unsigned char *dmac, unsigned char dsap); #endif /* LLC_SAP_H */ -- cgit From a5be1eb6488f4755a8dc237d5ba689667ddeeab5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:46 -0700 Subject: mrp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/mrp.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/net/mrp.h b/include/net/mrp.h index 4fbf02aa2ec1..687c8feecd09 100644 --- a/include/net/mrp.h +++ b/include/net/mrp.h @@ -125,19 +125,17 @@ struct mrp_port { struct rcu_head rcu; }; -extern int mrp_register_application(struct mrp_application *app); -extern void mrp_unregister_application(struct mrp_application *app); - -extern int mrp_init_applicant(struct net_device *dev, - struct mrp_application *app); -extern void mrp_uninit_applicant(struct net_device *dev, - struct mrp_application *app); - -extern int mrp_request_join(const struct net_device *dev, - const struct mrp_application *app, - const void *value, u8 len, u8 type); -extern void mrp_request_leave(const struct net_device *dev, - const struct mrp_application *app, - const void *value, u8 len, u8 type); +int mrp_register_application(struct mrp_application *app); +void mrp_unregister_application(struct mrp_application *app); + +int mrp_init_applicant(struct net_device *dev, struct mrp_application *app); +void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *app); + +int mrp_request_join(const struct net_device *dev, + const struct mrp_application *app, + const void *value, u8 len, u8 type); +void mrp_request_leave(const struct net_device *dev, + const struct mrp_application *app, + const void *value, u8 len, u8 type); #endif /* _NET_MRP_H */ -- cgit From 3cc818a27d17fc57aa37ee89d09feb2bc2dd789f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:47 -0700 Subject: ndisc.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ndisc.h | 61 +++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/include/net/ndisc.h b/include/net/ndisc.h index ea0cc26ab70e..6bbda34d5e59 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -110,8 +110,8 @@ struct ndisc_options { #define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) -extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, - struct ndisc_options *ndopts); +struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, + struct ndisc_options *ndopts); /* * Return the padding between the option length and the start of the @@ -189,60 +189,51 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons return n; } -extern int ndisc_init(void); -extern int ndisc_late_init(void); +int ndisc_init(void); +int ndisc_late_init(void); -extern void ndisc_late_cleanup(void); -extern void ndisc_cleanup(void); +void ndisc_late_cleanup(void); +void ndisc_cleanup(void); -extern int ndisc_rcv(struct sk_buff *skb); +int ndisc_rcv(struct sk_buff *skb); -extern void ndisc_send_ns(struct net_device *dev, - struct neighbour *neigh, - const struct in6_addr *solicit, - const struct in6_addr *daddr, - const struct in6_addr *saddr); +void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, + const struct in6_addr *solicit, + const struct in6_addr *daddr, const struct in6_addr *saddr); -extern void ndisc_send_rs(struct net_device *dev, - const struct in6_addr *saddr, - const struct in6_addr *daddr); -extern void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, - const struct in6_addr *daddr, - const struct in6_addr *solicited_addr, - bool router, bool solicited, bool override, - bool inc_opt); +void ndisc_send_rs(struct net_device *dev, + const struct in6_addr *saddr, const struct in6_addr *daddr); +void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, + const struct in6_addr *daddr, + const struct in6_addr *solicited_addr, + bool router, bool solicited, bool override, bool inc_opt); -extern void ndisc_send_redirect(struct sk_buff *skb, - const struct in6_addr *target); +void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target); -extern int ndisc_mc_map(const struct in6_addr *addr, char *buf, - struct net_device *dev, int dir); +int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, + int dir); /* * IGMP */ -extern int igmp6_init(void); +int igmp6_init(void); -extern void igmp6_cleanup(void); +void igmp6_cleanup(void); -extern int igmp6_event_query(struct sk_buff *skb); +int igmp6_event_query(struct sk_buff *skb); -extern int igmp6_event_report(struct sk_buff *skb); +int igmp6_event_report(struct sk_buff *skb); #ifdef CONFIG_SYSCTL -extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, - int write, - void __user *buffer, - size_t *lenp, - loff_t *ppos); +int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen); #endif -extern void inet6_ifinfo_notify(int event, - struct inet6_dev *idev); +void inet6_ifinfo_notify(int event, struct inet6_dev *idev); #endif -- cgit From e67e16ea9b5ad1dd76adf32233aed75c1f619433 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:48 -0700 Subject: net_namespace.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/net_namespace.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 1313456a0994..38c2afb585de 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -136,8 +136,8 @@ struct net { extern struct net init_net; #ifdef CONFIG_NET_NS -extern struct net *copy_net_ns(unsigned long flags, - struct user_namespace *user_ns, struct net *old_net); +struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns, + struct net *old_net); #else /* CONFIG_NET_NS */ #include @@ -154,11 +154,11 @@ static inline struct net *copy_net_ns(unsigned long flags, extern struct list_head net_namespace_list; -extern struct net *get_net_ns_by_pid(pid_t pid); -extern struct net *get_net_ns_by_fd(int pid); +struct net *get_net_ns_by_pid(pid_t pid); +struct net *get_net_ns_by_fd(int pid); #ifdef CONFIG_NET_NS -extern void __put_net(struct net *net); +void __put_net(struct net *net); static inline struct net *get_net(struct net *net) { @@ -190,7 +190,7 @@ int net_eq(const struct net *net1, const struct net *net2) return net1 == net2; } -extern void net_drop_ns(void *); +void net_drop_ns(void *); #else @@ -307,19 +307,19 @@ struct pernet_operations { * device which caused kernel oops, and panics during network * namespace cleanup. So please don't get this wrong. */ -extern int register_pernet_subsys(struct pernet_operations *); -extern void unregister_pernet_subsys(struct pernet_operations *); -extern int register_pernet_device(struct pernet_operations *); -extern void unregister_pernet_device(struct pernet_operations *); +int register_pernet_subsys(struct pernet_operations *); +void unregister_pernet_subsys(struct pernet_operations *); +int register_pernet_device(struct pernet_operations *); +void unregister_pernet_device(struct pernet_operations *); struct ctl_table; struct ctl_table_header; #ifdef CONFIG_SYSCTL -extern int net_sysctl_init(void); -extern struct ctl_table_header *register_net_sysctl(struct net *net, - const char *path, struct ctl_table *table); -extern void unregister_net_sysctl_table(struct ctl_table_header *header); +int net_sysctl_init(void); +struct ctl_table_header *register_net_sysctl(struct net *net, const char *path, + struct ctl_table *table); +void unregister_net_sysctl_table(struct ctl_table_header *header); #else static inline int net_sysctl_init(void) { return 0; } static inline struct ctl_table_header *register_net_sysctl(struct net *net, -- cgit From 70a3926f49896be866e5f2bd9c47cf4b33e3f2e3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:49 -0700 Subject: iw_handler.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/iw_handler.h | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 5d5a6a4732ef..a830b01baba4 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -432,44 +432,32 @@ struct iw_public_data { /* First : function strictly used inside the kernel */ /* Handle /proc/net/wireless, called in net/code/dev.c */ -extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, - int length); +int dev_get_wireless_info(char *buffer, char **start, off_t offset, int length); /* Second : functions that may be called by driver modules */ /* Send a single event to user space */ -extern void wireless_send_event(struct net_device * dev, - unsigned int cmd, - union iwreq_data * wrqu, - const char * extra); +void wireless_send_event(struct net_device *dev, unsigned int cmd, + union iwreq_data *wrqu, const char *extra); /* We may need a function to send a stream of events to user space. * More on that later... */ /* Standard handler for SIOCSIWSPY */ -extern int iw_handler_set_spy(struct net_device * dev, - struct iw_request_info * info, - union iwreq_data * wrqu, - char * extra); +int iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); /* Standard handler for SIOCGIWSPY */ -extern int iw_handler_get_spy(struct net_device * dev, - struct iw_request_info * info, - union iwreq_data * wrqu, - char * extra); +int iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); /* Standard handler for SIOCSIWTHRSPY */ -extern int iw_handler_set_thrspy(struct net_device * dev, - struct iw_request_info *info, - union iwreq_data * wrqu, - char * extra); +int iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); /* Standard handler for SIOCGIWTHRSPY */ -extern int iw_handler_get_thrspy(struct net_device * dev, - struct iw_request_info *info, - union iwreq_data * wrqu, - char * extra); +int iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); /* Driver call to update spy records */ -extern void wireless_spy_update(struct net_device * dev, - unsigned char * address, - struct iw_quality * wstats); +void wireless_spy_update(struct net_device *dev, unsigned char *address, + struct iw_quality *wstats); /************************* INLINE FUNTIONS *************************/ /* -- cgit From 4f69053b72c542faec2096ab454bba729a423efe Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:50 -0700 Subject: netevent/netlink.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/netevent.h | 6 ++--- include/net/netlink.h | 63 ++++++++++++++++++++------------------------------ 2 files changed, 28 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/include/net/netevent.h b/include/net/netevent.h index fe630dde35c3..d8bbb38584b6 100644 --- a/include/net/netevent.h +++ b/include/net/netevent.h @@ -26,8 +26,8 @@ enum netevent_notif_type { NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */ }; -extern int register_netevent_notifier(struct notifier_block *nb); -extern int unregister_netevent_notifier(struct notifier_block *nb); -extern int call_netevent_notifiers(unsigned long val, void *v); +int register_netevent_notifier(struct notifier_block *nb); +int unregister_netevent_notifier(struct notifier_block *nb); +int call_netevent_notifiers(unsigned long val, void *v); #endif diff --git a/include/net/netlink.h b/include/net/netlink.h index 9690b0f6698a..2b47eaadba8f 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -225,44 +225,31 @@ struct nl_info { u32 portid; }; -extern int netlink_rcv_skb(struct sk_buff *skb, - int (*cb)(struct sk_buff *, - struct nlmsghdr *)); -extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, - u32 portid, unsigned int group, int report, - gfp_t flags); - -extern int nla_validate(const struct nlattr *head, - int len, int maxtype, - const struct nla_policy *policy); -extern int nla_parse(struct nlattr **tb, int maxtype, - const struct nlattr *head, int len, - const struct nla_policy *policy); -extern int nla_policy_len(const struct nla_policy *, int); -extern struct nlattr * nla_find(const struct nlattr *head, - int len, int attrtype); -extern size_t nla_strlcpy(char *dst, const struct nlattr *nla, - size_t dstsize); -extern int nla_memcpy(void *dest, const struct nlattr *src, int count); -extern int nla_memcmp(const struct nlattr *nla, const void *data, - size_t size); -extern int nla_strcmp(const struct nlattr *nla, const char *str); -extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, - int attrlen); -extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen); -extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, - int attrlen); -extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen); -extern void __nla_put(struct sk_buff *skb, int attrtype, - int attrlen, const void *data); -extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen, - const void *data); -extern int nla_put(struct sk_buff *skb, int attrtype, - int attrlen, const void *data); -extern int nla_put_nohdr(struct sk_buff *skb, int attrlen, - const void *data); -extern int nla_append(struct sk_buff *skb, int attrlen, - const void *data); +int netlink_rcv_skb(struct sk_buff *skb, + int (*cb)(struct sk_buff *, struct nlmsghdr *)); +int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid, + unsigned int group, int report, gfp_t flags); + +int nla_validate(const struct nlattr *head, int len, int maxtype, + const struct nla_policy *policy); +int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, + int len, const struct nla_policy *policy); +int nla_policy_len(const struct nla_policy *, int); +struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype); +size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); +int nla_memcpy(void *dest, const struct nlattr *src, int count); +int nla_memcmp(const struct nlattr *nla, const void *data, size_t size); +int nla_strcmp(const struct nlattr *nla, const char *str); +struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); +void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen); +struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); +void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen); +void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, + const void *data); +void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data); +int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data); +int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data); +int nla_append(struct sk_buff *skb, int attrlen, const void *data); /************************************************************************** * Netlink Messages -- cgit From 96496127fe2f37c3670facfdbcc5cc51460c439c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:51 -0700 Subject: netrom.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/netrom.h | 89 ++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 45 deletions(-) (limited to 'include') diff --git a/include/net/netrom.h b/include/net/netrom.h index 121dcf854db5..110350aca3df 100644 --- a/include/net/netrom.h +++ b/include/net/netrom.h @@ -183,51 +183,50 @@ extern int sysctl_netrom_routing_control; extern int sysctl_netrom_link_fails_count; extern int sysctl_netrom_reset_circuit; -extern int nr_rx_frame(struct sk_buff *, struct net_device *); -extern void nr_destroy_socket(struct sock *); +int nr_rx_frame(struct sk_buff *, struct net_device *); +void nr_destroy_socket(struct sock *); /* nr_dev.c */ -extern int nr_rx_ip(struct sk_buff *, struct net_device *); -extern void nr_setup(struct net_device *); +int nr_rx_ip(struct sk_buff *, struct net_device *); +void nr_setup(struct net_device *); /* nr_in.c */ -extern int nr_process_rx_frame(struct sock *, struct sk_buff *); +int nr_process_rx_frame(struct sock *, struct sk_buff *); /* nr_loopback.c */ -extern void nr_loopback_init(void); -extern void nr_loopback_clear(void); -extern int nr_loopback_queue(struct sk_buff *); +void nr_loopback_init(void); +void nr_loopback_clear(void); +int nr_loopback_queue(struct sk_buff *); /* nr_out.c */ -extern void nr_output(struct sock *, struct sk_buff *); -extern void nr_send_nak_frame(struct sock *); -extern void nr_kick(struct sock *); -extern void nr_transmit_buffer(struct sock *, struct sk_buff *); -extern void nr_establish_data_link(struct sock *); -extern void nr_enquiry_response(struct sock *); -extern void nr_check_iframes_acked(struct sock *, unsigned short); +void nr_output(struct sock *, struct sk_buff *); +void nr_send_nak_frame(struct sock *); +void nr_kick(struct sock *); +void nr_transmit_buffer(struct sock *, struct sk_buff *); +void nr_establish_data_link(struct sock *); +void nr_enquiry_response(struct sock *); +void nr_check_iframes_acked(struct sock *, unsigned short); /* nr_route.c */ -extern void nr_rt_device_down(struct net_device *); -extern struct net_device *nr_dev_first(void); -extern struct net_device *nr_dev_get(ax25_address *); -extern int nr_rt_ioctl(unsigned int, void __user *); -extern void nr_link_failed(ax25_cb *, int); -extern int nr_route_frame(struct sk_buff *, ax25_cb *); +void nr_rt_device_down(struct net_device *); +struct net_device *nr_dev_first(void); +struct net_device *nr_dev_get(ax25_address *); +int nr_rt_ioctl(unsigned int, void __user *); +void nr_link_failed(ax25_cb *, int); +int nr_route_frame(struct sk_buff *, ax25_cb *); extern const struct file_operations nr_nodes_fops; extern const struct file_operations nr_neigh_fops; -extern void nr_rt_free(void); +void nr_rt_free(void); /* nr_subr.c */ -extern void nr_clear_queues(struct sock *); -extern void nr_frames_acked(struct sock *, unsigned short); -extern void nr_requeue_frames(struct sock *); -extern int nr_validate_nr(struct sock *, unsigned short); -extern int nr_in_rx_window(struct sock *, unsigned short); -extern void nr_write_internal(struct sock *, int); +void nr_clear_queues(struct sock *); +void nr_frames_acked(struct sock *, unsigned short); +void nr_requeue_frames(struct sock *); +int nr_validate_nr(struct sock *, unsigned short); +int nr_in_rx_window(struct sock *, unsigned short); +void nr_write_internal(struct sock *, int); -extern void __nr_transmit_reply(struct sk_buff *skb, int mine, - unsigned char cmdflags); +void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags); /* * This routine is called when a Connect Acknowledge with the Choke Flag @@ -247,24 +246,24 @@ do { \ __nr_transmit_reply((skb), (mine), NR_RESET); \ } while (0) -extern void nr_disconnect(struct sock *, int); +void nr_disconnect(struct sock *, int); /* nr_timer.c */ -extern void nr_init_timers(struct sock *sk); -extern void nr_start_heartbeat(struct sock *); -extern void nr_start_t1timer(struct sock *); -extern void nr_start_t2timer(struct sock *); -extern void nr_start_t4timer(struct sock *); -extern void nr_start_idletimer(struct sock *); -extern void nr_stop_heartbeat(struct sock *); -extern void nr_stop_t1timer(struct sock *); -extern void nr_stop_t2timer(struct sock *); -extern void nr_stop_t4timer(struct sock *); -extern void nr_stop_idletimer(struct sock *); -extern int nr_t1timer_running(struct sock *); +void nr_init_timers(struct sock *sk); +void nr_start_heartbeat(struct sock *); +void nr_start_t1timer(struct sock *); +void nr_start_t2timer(struct sock *); +void nr_start_t4timer(struct sock *); +void nr_start_idletimer(struct sock *); +void nr_stop_heartbeat(struct sock *); +void nr_stop_t1timer(struct sock *); +void nr_stop_t2timer(struct sock *); +void nr_stop_t4timer(struct sock *); +void nr_stop_idletimer(struct sock *); +int nr_t1timer_running(struct sock *); /* sysctl_net_netrom.c */ -extern void nr_register_sysctl(void); -extern void nr_unregister_sysctl(void); +void nr_register_sysctl(void); +void nr_unregister_sysctl(void); #endif -- cgit From 8dda204164131ff56fffc5443c475d8ed57d5ebd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 Sep 2013 10:22:52 -0700 Subject: p8022.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/p8022.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/p8022.h b/include/net/p8022.h index 42e9fac51b31..05e41383856b 100644 --- a/include/net/p8022.h +++ b/include/net/p8022.h @@ -1,13 +1,13 @@ #ifndef _NET_P8022_H #define _NET_P8022_H -extern struct datalink_proto * - register_8022_client(unsigned char type, - int (*func)(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev)); -extern void unregister_8022_client(struct datalink_proto *proto); +struct datalink_proto * +register_8022_client(unsigned char type, + int (*func)(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt, + struct net_device *orig_dev)); +void unregister_8022_client(struct datalink_proto *proto); -extern struct datalink_proto *make_8023_client(void); -extern void destroy_8023_client(struct datalink_proto *dl); +struct datalink_proto *make_8023_client(void); +void destroy_8023_client(struct datalink_proto *dl); #endif -- cgit From ca9a563805f7ae821e3303b1bdbc65d3a3c783ff Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Date: Thu, 19 Sep 2013 07:24:00 +0100 Subject: iio: ti_am335x_adc: Add continuous sampling support Previously the driver had only one-shot reading functionality. This patch adds continuous sampling support to the driver. Continuous sampling starts when buffer is enabled. HW IRQ wakes worker thread that pushes samples to userspace. Sampling stops when buffer is disabled by userspace. Patil Rachna (TI) laid the ground work for ADC HW register access. Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs. I fixed channel scanning so multiple ADC channels can be read simultaneously and pushed to userspace. Restructured the driver to fit IIO ABI. And added INDIO_BUFFER_HARDWARE mode. Signed-off-by: Zubair Lutfullah Acked-by: Greg Kroah-Hartman Signed-off-by: Russ Dill Acked-by: Lee Jones Acked-by: Sebastian Andrzej Siewior Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ti_am335x_adc.c | 213 ++++++++++++++++++++++++++++++++++- include/linux/mfd/ti_am335x_tscadc.h | 9 ++ 3 files changed, 218 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 0cf5c611b4c6..8b885188b839 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -177,6 +177,7 @@ config TI_ADC081C config TI_AM335X_ADC tristate "TI's AM335X ADC driver" depends on MFD_TI_AM335X_TSCADC + select IIO_KFIFO_BUF help Say yes here to build support for Texas Instruments ADC driver which is also a MFD client. diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index ebe93eba3ec8..5287bffd8a75 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -28,12 +28,20 @@ #include #include +#include +#include +#include +#include +#include struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; int channels; u8 channel_line[8]; u8 channel_step[8]; + int buffer_en_ch_steps; + struct iio_trigger *trig; + u16 data[8]; }; static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) @@ -56,8 +64,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev) return step_en; } -static void tiadc_step_config(struct tiadc_device *adc_dev) +static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) { + return 1 << adc_dev->channel_step[chan]; +} + +static void tiadc_step_config(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); unsigned int stepconfig; int i, steps; @@ -72,7 +86,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) */ steps = TOTAL_STEPS - adc_dev->channels; - stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; + if (iio_buffer_enabled(indio_dev)) + stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1 + | STEPCONFIG_MODE_SWCNT; + else + stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; for (i = 0; i < adc_dev->channels; i++) { int chan; @@ -85,9 +103,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) adc_dev->channel_step[i] = steps; steps++; } +} + +static irqreturn_t tiadc_irq_h(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct tiadc_device *adc_dev = iio_priv(indio_dev); + unsigned int status, config; + status = tiadc_readl(adc_dev, REG_IRQSTATUS); + + /* + * ADC and touchscreen share the IRQ line. + * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only + */ + if (status & IRQENB_FIFO1OVRRUN) { + /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */ + config = tiadc_readl(adc_dev, REG_CTRL); + config &= ~(CNTRLREG_TSCSSENB); + tiadc_writel(adc_dev, REG_CTRL, config); + tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN + | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES); + tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); + return IRQ_HANDLED; + } else if (status & IRQENB_FIFO1THRES) { + /* Disable irq and wake worker thread */ + tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES); + return IRQ_WAKE_THREAD; + } + + return IRQ_NONE; +} + +static irqreturn_t tiadc_worker_h(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct tiadc_device *adc_dev = iio_priv(indio_dev); + int i, k, fifo1count, read; + u16 *data = adc_dev->data; + + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); + for (k = 0; k < fifo1count; k = k + i) { + for (i = 0; i < (indio_dev->scan_bytes)/2; i++) { + read = tiadc_readl(adc_dev, REG_FIFO1); + data[i] = read & FIFOREAD_DATA_MASK; + } + iio_push_to_buffers(indio_dev, (u8 *) data); + } + + tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES); + tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); + + return IRQ_HANDLED; +} + +static int tiadc_buffer_preenable(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); + int i, fifo1count, read; + + tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | + IRQENB_FIFO1OVRRUN | + IRQENB_FIFO1UNDRFLW)); + + /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */ + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); + for (i = 0; i < fifo1count; i++) + read = tiadc_readl(adc_dev, REG_FIFO1); + + return iio_sw_buffer_preenable(indio_dev); +} + +static int tiadc_buffer_postenable(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct iio_buffer *buffer = indio_dev->buffer; + unsigned int enb = 0; + u8 bit; + + tiadc_step_config(indio_dev); + for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels) + enb |= (get_adc_step_bit(adc_dev, bit) << 1); + adc_dev->buffer_en_ch_steps = enb; + + am335x_tsc_se_set(adc_dev->mfd_tscadc, enb); + + tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES + | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); + tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES + | IRQENB_FIFO1OVRRUN); + + return 0; +} + +static int tiadc_buffer_predisable(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); + int fifo1count, i, read; + + tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | + IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); + am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); + /* Flush FIFO of leftover data in the time it takes to disable adc */ + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); + for (i = 0; i < fifo1count; i++) + read = tiadc_readl(adc_dev, REG_FIFO1); + + return 0; } +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev) +{ + tiadc_step_config(indio_dev); + + return 0; +} + +static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { + .preenable = &tiadc_buffer_preenable, + .postenable = &tiadc_buffer_postenable, + .predisable = &tiadc_buffer_predisable, + .postdisable = &tiadc_buffer_postdisable, +}; + +int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + int irq, + unsigned long flags, + const struct iio_buffer_setup_ops *setup_ops) +{ + int ret; + + indio_dev->buffer = iio_kfifo_allocate(indio_dev); + if (!indio_dev->buffer) + return -ENOMEM; + + ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh, + flags, indio_dev->name, indio_dev); + if (ret) + goto error_kfifo_free; + + indio_dev->setup_ops = setup_ops; + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(irq, indio_dev); +error_kfifo_free: + iio_kfifo_free(indio_dev->buffer); + return ret; +} + +static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) +{ + struct tiadc_device *adc_dev = iio_priv(indio_dev); + + free_irq(adc_dev->mfd_tscadc->irq, indio_dev); + iio_kfifo_free(indio_dev->buffer); + iio_buffer_unregister(indio_dev); +} + + static const char * const chan_name_ain[] = { "AIN0", "AIN1", @@ -120,6 +304,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) chan->channel = adc_dev->channel_line[i]; chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan->datasheet_name = chan_name_ain[chan->channel]; + chan->scan_index = i; chan->scan_type.sign = 'u'; chan->scan_type.realbits = 12; chan->scan_type.storagebits = 16; @@ -147,6 +332,10 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, u32 step_en; unsigned long timeout = jiffies + usecs_to_jiffies (IDLE_TIMEOUT * adc_dev->channels); + + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + step_en = get_adc_step_mask(adc_dev); am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); @@ -237,20 +426,33 @@ static int tiadc_probe(struct platform_device *pdev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &tiadc_info; - tiadc_step_config(adc_dev); + tiadc_step_config(indio_dev); + tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); err = tiadc_channel_init(indio_dev, adc_dev->channels); if (err < 0) return err; - err = iio_device_register(indio_dev); + err = tiadc_iio_buffered_hardware_setup(indio_dev, + &tiadc_worker_h, + &tiadc_irq_h, + adc_dev->mfd_tscadc->irq, + IRQF_SHARED, + &tiadc_buffer_setup_ops); + if (err) goto err_free_channels; + err = iio_device_register(indio_dev); + if (err) + goto err_buffer_unregister; + platform_set_drvdata(pdev, indio_dev); return 0; +err_buffer_unregister: + tiadc_iio_buffered_hardware_remove(indio_dev); err_free_channels: tiadc_channels_remove(indio_dev); return err; @@ -263,6 +465,7 @@ static int tiadc_remove(struct platform_device *pdev) u32 step_en; iio_device_unregister(indio_dev); + tiadc_iio_buffered_hardware_remove(indio_dev); tiadc_channels_remove(indio_dev); step_en = get_adc_step_mask(adc_dev); @@ -301,7 +504,7 @@ static int tiadc_resume(struct device *dev) restore &= ~(CNTRLREG_POWERDOWN); tiadc_writel(adc_dev, REG_CTRL, restore); - tiadc_step_config(adc_dev); + tiadc_step_config(indio_dev); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index db1791bb997a..7d98562b3b51 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -46,16 +46,24 @@ /* Step Enable */ #define STEPENB_MASK (0x1FFFF << 0) #define STEPENB(val) ((val) << 0) +#define ENB(val) (1 << (val)) +#define STPENB_STEPENB STEPENB(0x1FFFF) +#define STPENB_STEPENB_TC STEPENB(0x1FFF) /* IRQ enable */ #define IRQENB_HW_PEN BIT(0) #define IRQENB_FIFO0THRES BIT(2) +#define IRQENB_FIFO0OVRRUN BIT(3) +#define IRQENB_FIFO0UNDRFLW BIT(4) #define IRQENB_FIFO1THRES BIT(5) +#define IRQENB_FIFO1OVRRUN BIT(6) +#define IRQENB_FIFO1UNDRFLW BIT(7) #define IRQENB_PENUP BIT(9) /* Step Configuration */ #define STEPCONFIG_MODE_MASK (3 << 0) #define STEPCONFIG_MODE(val) ((val) << 0) +#define STEPCONFIG_MODE_SWCNT STEPCONFIG_MODE(1) #define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2) #define STEPCONFIG_AVG_MASK (7 << 2) #define STEPCONFIG_AVG(val) ((val) << 2) @@ -124,6 +132,7 @@ #define MAX_CLK_DIV 7 #define TOTAL_STEPS 16 #define TOTAL_CHANNELS 8 +#define FIFO1_THRESHOLD 19 /* * ADC runs at 3MHz, and it takes -- cgit From d2c3d072c4aded65f0632223cc0d3a8a2e577b3a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 19 Sep 2013 13:59:00 +0100 Subject: iio: Add iio_push_buffers_with_timestamp() helper Drivers using software buffers often store the timestamp in their data buffer before calling iio_push_to_buffers() with that data buffer. Storing the timestamp in the buffer usually involves some ugly pointer arithmetic. This patch adds a new helper function called iio_push_buffers_with_timestamp() which is similar to iio_push_to_buffers but takes an additional timestamp parameter. The function will help to hide to uglyness in one central place instead of exposing it in every driver. If timestamps are enabled for the IIO device iio_push_buffers_with_timestamp() will store the timestamp as the last element in buffer, before passing the buffer on to iio_push_buffers(). The buffer needs large enough to hold the timestamp in this case. If timestamps are disabled iio_push_buffers_with_timestamp() will behave just like iio_push_buffers(). Signed-off-by: Lars-Peter Clausen Cc: Oleksandr Kravchenko Cc: Josh Wu Cc: Denis Ciocca Cc: Manuel Stahl Cc: Ge Gao Cc: Peter Meerwald Cc: Jacek Anaszewski Cc: Fabio Estevam Cc: Marek Vasut Signed-off-by: Jonathan Cameron --- include/linux/iio/buffer.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'include') diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index e5507e999ed1..a1124bdc4cac 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -122,6 +122,31 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, */ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data); +/* + * iio_push_to_buffers_with_timestamp() - push data and timestamp to buffers + * @indio_dev: iio_dev structure for device. + * @data: sample data + * @timestamp: timestamp for the sample data + * + * Pushes data to the IIO device's buffers. If timestamps are enabled for the + * device the function will store the supplied timestamp as the last element in + * the sample data buffer before pushing it to the device buffers. The sample + * data buffer needs to be large enough to hold the additional timestamp + * (usually the buffer should be indio->scan_bytes bytes large). + * + * Returns 0 on success, a negative error code otherwise. + */ +static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, + void *data, int64_t timestamp) +{ + if (indio_dev->scan_timestamp) { + size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1; + ((int64_t *)data)[ts_offset] = timestamp; + } + + return iio_push_to_buffers(indio_dev, data); +} + int iio_update_demux(struct iio_dev *indio_dev); /** -- cgit From 6d3b334d677cd0c18cf99ababe1441b62dd08020 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:16 -0700 Subject: ping.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ping.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/ping.h b/include/net/ping.h index 5db0224b73ac..3f67704f3747 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -103,8 +103,8 @@ void ping_seq_stop(struct seq_file *seq, void *v); int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo); void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo); -extern int __init ping_proc_init(void); -extern void ping_proc_exit(void); +int __init ping_proc_init(void); +void ping_proc_exit(void); #endif void __init ping_init(void); -- cgit From f307c6365648e919d7ac733f0b3a7e9ee3e31eb2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:17 -0700 Subject: protocol.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/protocol.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/net/protocol.h b/include/net/protocol.h index 047c0476c0a0..fbf7676c9a02 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -96,20 +96,20 @@ extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS]; extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; #endif -extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num); -extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num); -extern int inet_add_offload(const struct net_offload *prot, unsigned char num); -extern int inet_del_offload(const struct net_offload *prot, unsigned char num); -extern void inet_register_protosw(struct inet_protosw *p); -extern void inet_unregister_protosw(struct inet_protosw *p); +int inet_add_protocol(const struct net_protocol *prot, unsigned char num); +int inet_del_protocol(const struct net_protocol *prot, unsigned char num); +int inet_add_offload(const struct net_offload *prot, unsigned char num); +int inet_del_offload(const struct net_offload *prot, unsigned char num); +void inet_register_protosw(struct inet_protosw *p); +void inet_unregister_protosw(struct inet_protosw *p); #if IS_ENABLED(CONFIG_IPV6) -extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); -extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); -extern int inet6_register_protosw(struct inet_protosw *p); -extern void inet6_unregister_protosw(struct inet_protosw *p); +int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); +int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); +int inet6_register_protosw(struct inet_protosw *p); +void inet6_unregister_protosw(struct inet_protosw *p); #endif -extern int inet6_add_offload(const struct net_offload *prot, unsigned char num); -extern int inet6_del_offload(const struct net_offload *prot, unsigned char num); +int inet6_add_offload(const struct net_offload *prot, unsigned char num); +int inet6_del_offload(const struct net_offload *prot, unsigned char num); #endif /* _PROTOCOL_H */ -- cgit From c64b5c4b916f47ba854a560d6c56d87790e344ca Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:18 -0700 Subject: psnap.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/psnap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/psnap.h b/include/net/psnap.h index fe456c295b04..78db4cc1306a 100644 --- a/include/net/psnap.h +++ b/include/net/psnap.h @@ -1,11 +1,11 @@ #ifndef _NET_PSNAP_H #define _NET_PSNAP_H -extern struct datalink_proto * +struct datalink_proto * register_snap_client(const unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *orig_dev)); -extern void unregister_snap_client(struct datalink_proto *proto); +void unregister_snap_client(struct datalink_proto *proto); #endif -- cgit From 0ad6ad946167a706e22eb7bad9e77735bc577074 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:19 -0700 Subject: raw/rawv6.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/raw.h | 6 +++--- include/net/rawv6.h | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/raw.h b/include/net/raw.h index 42ce6fe7a2d5..6a40c6562dd2 100644 --- a/include/net/raw.h +++ b/include/net/raw.h @@ -26,7 +26,7 @@ extern struct proto raw_prot; void raw_icmp_error(struct sk_buff *, int, u32); int raw_local_deliver(struct sk_buff *, int); -extern int raw_rcv(struct sock *, struct sk_buff *); +int raw_rcv(struct sock *, struct sk_buff *); #define RAW_HTABLE_SIZE MAX_INET_PROTOS @@ -36,8 +36,8 @@ struct raw_hashinfo { }; #ifdef CONFIG_PROC_FS -extern int raw_proc_init(void); -extern void raw_proc_exit(void); +int raw_proc_init(void); +void raw_proc_exit(void); struct raw_iter_state { struct seq_net_private p; diff --git a/include/net/rawv6.h b/include/net/rawv6.h index e7ea660e4db6..87783dea0791 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -7,8 +7,7 @@ void raw6_icmp_error(struct sk_buff *, int nexthdr, u8 type, u8 code, int inner_offset, __be32); bool raw6_local_deliver(struct sk_buff *, int); -extern int rawv6_rcv(struct sock *sk, - struct sk_buff *skb); +int rawv6_rcv(struct sock *sk, struct sk_buff *skb); #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) int rawv6_mh_filter_register(int (*filter)(struct sock *sock, -- cgit From c0f4502a8700832bb3a917fdcfe080f5ccf1c617 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:20 -0700 Subject: request_sock.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/request_sock.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 59795e42c8b6..65c3e5164a5c 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -43,7 +43,7 @@ struct request_sock_ops { struct request_sock *req); }; -extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req); +int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req); /* struct request_sock - mini sock to represent a connection request */ @@ -162,13 +162,13 @@ struct request_sock_queue { */ }; -extern int reqsk_queue_alloc(struct request_sock_queue *queue, - unsigned int nr_table_entries); +int reqsk_queue_alloc(struct request_sock_queue *queue, + unsigned int nr_table_entries); -extern void __reqsk_queue_destroy(struct request_sock_queue *queue); -extern void reqsk_queue_destroy(struct request_sock_queue *queue); -extern void reqsk_fastopen_remove(struct sock *sk, - struct request_sock *req, bool reset); +void __reqsk_queue_destroy(struct request_sock_queue *queue); +void reqsk_queue_destroy(struct request_sock_queue *queue); +void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, + bool reset); static inline struct request_sock * reqsk_queue_yank_acceptq(struct request_sock_queue *queue) -- cgit From 54df3b961db19e3eb6ccbac0ca469c56b1b58689 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:21 -0700 Subject: rose.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/rose.h | 114 ++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 54 deletions(-) (limited to 'include') diff --git a/include/net/rose.h b/include/net/rose.h index 555dd198aab7..50811fe2c585 100644 --- a/include/net/rose.h +++ b/include/net/rose.h @@ -160,38 +160,42 @@ extern int sysctl_rose_routing_control; extern int sysctl_rose_link_fail_timeout; extern int sysctl_rose_maximum_vcs; extern int sysctl_rose_window_size; -extern int rosecmp(rose_address *, rose_address *); -extern int rosecmpm(rose_address *, rose_address *, unsigned short); -extern char *rose2asc(char *buf, const rose_address *); -extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *); -extern void rose_kill_by_neigh(struct rose_neigh *); -extern unsigned int rose_new_lci(struct rose_neigh *); -extern int rose_rx_call_request(struct sk_buff *, struct net_device *, struct rose_neigh *, unsigned int); -extern void rose_destroy_socket(struct sock *); + +int rosecmp(rose_address *, rose_address *); +int rosecmpm(rose_address *, rose_address *, unsigned short); +char *rose2asc(char *buf, const rose_address *); +struct sock *rose_find_socket(unsigned int, struct rose_neigh *); +void rose_kill_by_neigh(struct rose_neigh *); +unsigned int rose_new_lci(struct rose_neigh *); +int rose_rx_call_request(struct sk_buff *, struct net_device *, + struct rose_neigh *, unsigned int); +void rose_destroy_socket(struct sock *); /* rose_dev.c */ -extern void rose_setup(struct net_device *); +void rose_setup(struct net_device *); /* rose_in.c */ -extern int rose_process_rx_frame(struct sock *, struct sk_buff *); +int rose_process_rx_frame(struct sock *, struct sk_buff *); /* rose_link.c */ -extern void rose_start_ftimer(struct rose_neigh *); -extern void rose_stop_ftimer(struct rose_neigh *); -extern void rose_stop_t0timer(struct rose_neigh *); -extern int rose_ftimer_running(struct rose_neigh *); -extern void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, unsigned short); -extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char, unsigned char); -extern void rose_transmit_link(struct sk_buff *, struct rose_neigh *); +void rose_start_ftimer(struct rose_neigh *); +void rose_stop_ftimer(struct rose_neigh *); +void rose_stop_t0timer(struct rose_neigh *); +int rose_ftimer_running(struct rose_neigh *); +void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, + unsigned short); +void rose_transmit_clear_request(struct rose_neigh *, unsigned int, + unsigned char, unsigned char); +void rose_transmit_link(struct sk_buff *, struct rose_neigh *); /* rose_loopback.c */ -extern void rose_loopback_init(void); -extern void rose_loopback_clear(void); -extern int rose_loopback_queue(struct sk_buff *, struct rose_neigh *); +void rose_loopback_init(void); +void rose_loopback_clear(void); +int rose_loopback_queue(struct sk_buff *, struct rose_neigh *); /* rose_out.c */ -extern void rose_kick(struct sock *); -extern void rose_enquiry_response(struct sock *); +void rose_kick(struct sock *); +void rose_enquiry_response(struct sock *); /* rose_route.c */ extern struct rose_neigh *rose_loopback_neigh; @@ -199,43 +203,45 @@ extern const struct file_operations rose_neigh_fops; extern const struct file_operations rose_nodes_fops; extern const struct file_operations rose_routes_fops; -extern void rose_add_loopback_neigh(void); -extern int __must_check rose_add_loopback_node(rose_address *); -extern void rose_del_loopback_node(rose_address *); -extern void rose_rt_device_down(struct net_device *); -extern void rose_link_device_down(struct net_device *); -extern struct net_device *rose_dev_first(void); -extern struct net_device *rose_dev_get(rose_address *); -extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *); -extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *, int); -extern int rose_rt_ioctl(unsigned int, void __user *); -extern void rose_link_failed(ax25_cb *, int); -extern int rose_route_frame(struct sk_buff *, ax25_cb *); -extern void rose_rt_free(void); +void rose_add_loopback_neigh(void); +int __must_check rose_add_loopback_node(rose_address *); +void rose_del_loopback_node(rose_address *); +void rose_rt_device_down(struct net_device *); +void rose_link_device_down(struct net_device *); +struct net_device *rose_dev_first(void); +struct net_device *rose_dev_get(rose_address *); +struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *); +struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, + unsigned char *, int); +int rose_rt_ioctl(unsigned int, void __user *); +void rose_link_failed(ax25_cb *, int); +int rose_route_frame(struct sk_buff *, ax25_cb *); +void rose_rt_free(void); /* rose_subr.c */ -extern void rose_clear_queues(struct sock *); -extern void rose_frames_acked(struct sock *, unsigned short); -extern void rose_requeue_frames(struct sock *); -extern int rose_validate_nr(struct sock *, unsigned short); -extern void rose_write_internal(struct sock *, int); -extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); -extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *); -extern void rose_disconnect(struct sock *, int, int, int); +void rose_clear_queues(struct sock *); +void rose_frames_acked(struct sock *, unsigned short); +void rose_requeue_frames(struct sock *); +int rose_validate_nr(struct sock *, unsigned short); +void rose_write_internal(struct sock *, int); +int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); +int rose_parse_facilities(unsigned char *, unsigned int, + struct rose_facilities_struct *); +void rose_disconnect(struct sock *, int, int, int); /* rose_timer.c */ -extern void rose_start_heartbeat(struct sock *); -extern void rose_start_t1timer(struct sock *); -extern void rose_start_t2timer(struct sock *); -extern void rose_start_t3timer(struct sock *); -extern void rose_start_hbtimer(struct sock *); -extern void rose_start_idletimer(struct sock *); -extern void rose_stop_heartbeat(struct sock *); -extern void rose_stop_timer(struct sock *); -extern void rose_stop_idletimer(struct sock *); +void rose_start_heartbeat(struct sock *); +void rose_start_t1timer(struct sock *); +void rose_start_t2timer(struct sock *); +void rose_start_t3timer(struct sock *); +void rose_start_hbtimer(struct sock *); +void rose_start_idletimer(struct sock *); +void rose_stop_heartbeat(struct sock *); +void rose_stop_timer(struct sock *); +void rose_stop_idletimer(struct sock *); /* sysctl_net_rose.c */ -extern void rose_register_sysctl(void); -extern void rose_unregister_sysctl(void); +void rose_register_sysctl(void); +void rose_unregister_sysctl(void); #endif -- cgit From 2702c4bb89b2a9bfe49f3db77a1bac88d5c6404c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:22 -0700 Subject: route.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/route.h | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/net/route.h b/include/net/route.h index afdeeb5bec25..6f572ca66d25 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -108,13 +108,15 @@ struct rt_cache_stat { extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; -extern int ip_rt_init(void); -extern void rt_cache_flush(struct net *net); -extern void rt_flush_dev(struct net_device *dev); -extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); -extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, - struct sock *sk); -extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); + +int ip_rt_init(void); +void rt_cache_flush(struct net *net); +void rt_flush_dev(struct net_device *dev); +struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); +struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, + struct sock *sk); +struct dst_entry *ipv4_blackhole_route(struct net *net, + struct dst_entry *dst_orig); static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp) { @@ -162,8 +164,8 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 return ip_route_output_key(net, fl4); } -extern int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, - u8 tos, struct net_device *devin); +int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, + u8 tos, struct net_device *devin); static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, u8 tos, struct net_device *devin) @@ -179,24 +181,25 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, return err; } -extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, - int oif, u32 mark, u8 protocol, int flow_flags); -extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); -extern void ipv4_redirect(struct sk_buff *skb, struct net *net, - int oif, u32 mark, u8 protocol, int flow_flags); -extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk); -extern void ip_rt_send_redirect(struct sk_buff *skb); - -extern unsigned int inet_addr_type(struct net *net, __be32 addr); -extern unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); -extern void ip_rt_multicast_event(struct in_device *); -extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); -extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); -extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); +void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif, + u32 mark, u8 protocol, int flow_flags); +void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); +void ipv4_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, + u8 protocol, int flow_flags); +void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk); +void ip_rt_send_redirect(struct sk_buff *skb); + +unsigned int inet_addr_type(struct net *net, __be32 addr); +unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, + __be32 addr); +void ip_rt_multicast_event(struct in_device *); +int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); +void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); +int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); struct in_ifaddr; -extern void fib_add_ifaddr(struct in_ifaddr *); -extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *); +void fib_add_ifaddr(struct in_ifaddr *); +void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *); static inline void ip_rt_put(struct rtable *rt) { -- cgit From efb48ccfcda4dbb9fce39c5c8df19644a08121c0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:23 -0700 Subject: rtnetlink.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/rtnetlink.h | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 702664833a53..bb13a182fba6 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -8,14 +8,12 @@ typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *); typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *); typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *); -extern int __rtnl_register(int protocol, int msgtype, - rtnl_doit_func, rtnl_dumpit_func, - rtnl_calcit_func); -extern void rtnl_register(int protocol, int msgtype, - rtnl_doit_func, rtnl_dumpit_func, - rtnl_calcit_func); -extern int rtnl_unregister(int protocol, int msgtype); -extern void rtnl_unregister_all(int protocol); +int __rtnl_register(int protocol, int msgtype, + rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func); +void rtnl_register(int protocol, int msgtype, + rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func); +int rtnl_unregister(int protocol, int msgtype); +void rtnl_unregister_all(int protocol); static inline int rtnl_msg_family(const struct nlmsghdr *nlh) { @@ -83,11 +81,11 @@ struct rtnl_link_ops { unsigned int (*get_num_rx_queues)(void); }; -extern int __rtnl_link_register(struct rtnl_link_ops *ops); -extern void __rtnl_link_unregister(struct rtnl_link_ops *ops); +int __rtnl_link_register(struct rtnl_link_ops *ops); +void __rtnl_link_unregister(struct rtnl_link_ops *ops); -extern int rtnl_link_register(struct rtnl_link_ops *ops); -extern void rtnl_link_unregister(struct rtnl_link_ops *ops); +int rtnl_link_register(struct rtnl_link_ops *ops); +void rtnl_link_unregister(struct rtnl_link_ops *ops); /** * struct rtnl_af_ops - rtnetlink address family operations @@ -117,18 +115,18 @@ struct rtnl_af_ops { const struct nlattr *attr); }; -extern int __rtnl_af_register(struct rtnl_af_ops *ops); -extern void __rtnl_af_unregister(struct rtnl_af_ops *ops); +int __rtnl_af_register(struct rtnl_af_ops *ops); +void __rtnl_af_unregister(struct rtnl_af_ops *ops); -extern int rtnl_af_register(struct rtnl_af_ops *ops); -extern void rtnl_af_unregister(struct rtnl_af_ops *ops); +int rtnl_af_register(struct rtnl_af_ops *ops); +void rtnl_af_unregister(struct rtnl_af_ops *ops); +struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); +struct net_device *rtnl_create_link(struct net *net, char *ifname, + const struct rtnl_link_ops *ops, + struct nlattr *tb[]); +int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm); -extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); -extern struct net_device *rtnl_create_link(struct net *net, - char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]); -extern int rtnl_configure_link(struct net_device *dev, - const struct ifinfomsg *ifm); extern const struct nla_policy ifla_policy[IFLA_MAX+1]; #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) -- cgit From 8153ff5c5f3183dec007469d7e039b4d01ea6d82 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:24 -0700 Subject: scm.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/scm.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/scm.h b/include/net/scm.h index 8de2d37d2077..262532d111f5 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -33,11 +33,11 @@ struct scm_cookie { #endif }; -extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); -extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); -extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); -extern void __scm_destroy(struct scm_cookie *scm); -extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); +void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); +void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); +int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); +void __scm_destroy(struct scm_cookie *scm); +struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl); #ifdef CONFIG_SECURITY_NETWORK static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) -- cgit From a4ea1fef97e31fbdac77e5d1e183ea345fbb2cd6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:25 -0700 Subject: secure_seq.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/secure_seq.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h index 6ca975bebd37..52c1a906f288 100644 --- a/include/net/secure_seq.h +++ b/include/net/secure_seq.h @@ -3,19 +3,19 @@ #include -extern void net_secret_init(void); -extern __u32 secure_ip_id(__be32 daddr); -extern __u32 secure_ipv6_id(const __be32 daddr[4]); -extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); -extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, - __be16 dport); -extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport); -extern __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, - __be16 sport, __be16 dport); -extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport); -extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, - __be16 sport, __be16 dport); +void net_secret_init(void); +__u32 secure_ip_id(__be32 daddr); +__u32 secure_ipv6_id(const __be32 daddr[4]); +u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); +u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport); +__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); +__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, + __be16 sport, __be16 dport); +u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); +u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport); #endif /* _NET_SECURE_SEQ */ -- cgit From 69336bd2d3ddce315dc57be894e4b57a91036a14 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:26 -0700 Subject: sock.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/sock.h | 223 ++++++++++++++++++++++++----------------------------- 1 file changed, 99 insertions(+), 124 deletions(-) (limited to 'include') diff --git a/include/net/sock.h b/include/net/sock.h index 6ba2e7b0e2b1..4625d2eff461 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -746,7 +746,7 @@ static inline int sk_stream_wspace(const struct sock *sk) return sk->sk_sndbuf - sk->sk_wmem_queued; } -extern void sk_stream_write_space(struct sock *sk); +void sk_stream_write_space(struct sock *sk); /* OOB backlog add */ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) @@ -788,7 +788,7 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s return 0; } -extern int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); +int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) { @@ -853,15 +853,15 @@ static inline void sock_rps_reset_rxhash(struct sock *sk) __rc; \ }) -extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p); -extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p); -extern void sk_stream_wait_close(struct sock *sk, long timeo_p); -extern int sk_stream_error(struct sock *sk, int flags, int err); -extern void sk_stream_kill_queues(struct sock *sk); -extern void sk_set_memalloc(struct sock *sk); -extern void sk_clear_memalloc(struct sock *sk); +int sk_stream_wait_connect(struct sock *sk, long *timeo_p); +int sk_stream_wait_memory(struct sock *sk, long *timeo_p); +void sk_stream_wait_close(struct sock *sk, long timeo_p); +int sk_stream_error(struct sock *sk, int flags, int err); +void sk_stream_kill_queues(struct sock *sk); +void sk_set_memalloc(struct sock *sk); +void sk_clear_memalloc(struct sock *sk); -extern int sk_wait_data(struct sock *sk, long *timeo); +int sk_wait_data(struct sock *sk, long *timeo); struct request_sock_ops; struct timewait_sock_ops; @@ -1031,8 +1031,8 @@ struct cg_proto { struct mem_cgroup *memcg; }; -extern int proto_register(struct proto *prot, int alloc_slab); -extern void proto_unregister(struct proto *prot); +int proto_register(struct proto *prot, int alloc_slab); +void proto_unregister(struct proto *prot); static inline bool memcg_proto_active(struct cg_proto *cg_proto) { @@ -1287,8 +1287,8 @@ proto_memory_pressure(struct proto *prot) #ifdef CONFIG_PROC_FS /* Called with local bh disabled */ -extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc); -extern int sock_prot_inuse_get(struct net *net, struct proto *proto); +void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc); +int sock_prot_inuse_get(struct net *net, struct proto *proto); #else static inline void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc) @@ -1364,8 +1364,8 @@ static inline struct inode *SOCK_INODE(struct socket *socket) /* * Functions for memory accounting */ -extern int __sk_mem_schedule(struct sock *sk, int size, int kind); -extern void __sk_mem_reclaim(struct sock *sk); +int __sk_mem_schedule(struct sock *sk, int size, int kind); +void __sk_mem_reclaim(struct sock *sk); #define SK_MEM_QUANTUM ((int)PAGE_SIZE) #define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM) @@ -1473,14 +1473,14 @@ do { \ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ } while (0) -extern void lock_sock_nested(struct sock *sk, int subclass); +void lock_sock_nested(struct sock *sk, int subclass); static inline void lock_sock(struct sock *sk) { lock_sock_nested(sk, 0); } -extern void release_sock(struct sock *sk); +void release_sock(struct sock *sk); /* BH context may only use the following locking interface. */ #define bh_lock_sock(__sk) spin_lock(&((__sk)->sk_lock.slock)) @@ -1489,7 +1489,7 @@ extern void release_sock(struct sock *sk); SINGLE_DEPTH_NESTING) #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) -extern bool lock_sock_fast(struct sock *sk); +bool lock_sock_fast(struct sock *sk); /** * unlock_sock_fast - complement of lock_sock_fast * @sk: socket @@ -1507,108 +1507,84 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow) } -extern struct sock *sk_alloc(struct net *net, int family, - gfp_t priority, - struct proto *prot); -extern void sk_free(struct sock *sk); -extern void sk_release_kernel(struct sock *sk); -extern struct sock *sk_clone_lock(const struct sock *sk, - const gfp_t priority); - -extern struct sk_buff *sock_wmalloc(struct sock *sk, - unsigned long size, int force, - gfp_t priority); -extern struct sk_buff *sock_rmalloc(struct sock *sk, - unsigned long size, int force, - gfp_t priority); -extern void sock_wfree(struct sk_buff *skb); -extern void skb_orphan_partial(struct sk_buff *skb); -extern void sock_rfree(struct sk_buff *skb); -extern void sock_edemux(struct sk_buff *skb); - -extern int sock_setsockopt(struct socket *sock, int level, - int op, char __user *optval, - unsigned int optlen); - -extern int sock_getsockopt(struct socket *sock, int level, - int op, char __user *optval, - int __user *optlen); -extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, - unsigned long size, - int noblock, - int *errcode); -extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, - unsigned long header_len, - unsigned long data_len, - int noblock, - int *errcode, - int max_page_order); -extern void *sock_kmalloc(struct sock *sk, int size, - gfp_t priority); -extern void sock_kfree_s(struct sock *sk, void *mem, int size); -extern void sk_send_sigurg(struct sock *sk); +struct sock *sk_alloc(struct net *net, int family, gfp_t priority, + struct proto *prot); +void sk_free(struct sock *sk); +void sk_release_kernel(struct sock *sk); +struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority); + +struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, + gfp_t priority); +struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, + gfp_t priority); +void sock_wfree(struct sk_buff *skb); +void skb_orphan_partial(struct sk_buff *skb); +void sock_rfree(struct sk_buff *skb); +void sock_edemux(struct sk_buff *skb); + +int sock_setsockopt(struct socket *sock, int level, int op, + char __user *optval, unsigned int optlen); + +int sock_getsockopt(struct socket *sock, int level, int op, + char __user *optval, int __user *optlen); +struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, + int noblock, int *errcode); +struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, + unsigned long data_len, int noblock, + int *errcode, int max_page_order); +void *sock_kmalloc(struct sock *sk, int size, gfp_t priority); +void sock_kfree_s(struct sock *sk, void *mem, int size); +void sk_send_sigurg(struct sock *sk); /* * Functions to fill in entries in struct proto_ops when a protocol * does not implement a particular function. */ -extern int sock_no_bind(struct socket *, - struct sockaddr *, int); -extern int sock_no_connect(struct socket *, - struct sockaddr *, int, int); -extern int sock_no_socketpair(struct socket *, - struct socket *); -extern int sock_no_accept(struct socket *, - struct socket *, int); -extern int sock_no_getname(struct socket *, - struct sockaddr *, int *, int); -extern unsigned int sock_no_poll(struct file *, struct socket *, - struct poll_table_struct *); -extern int sock_no_ioctl(struct socket *, unsigned int, - unsigned long); -extern int sock_no_listen(struct socket *, int); -extern int sock_no_shutdown(struct socket *, int); -extern int sock_no_getsockopt(struct socket *, int , int, - char __user *, int __user *); -extern int sock_no_setsockopt(struct socket *, int, int, - char __user *, unsigned int); -extern int sock_no_sendmsg(struct kiocb *, struct socket *, - struct msghdr *, size_t); -extern int sock_no_recvmsg(struct kiocb *, struct socket *, - struct msghdr *, size_t, int); -extern int sock_no_mmap(struct file *file, - struct socket *sock, - struct vm_area_struct *vma); -extern ssize_t sock_no_sendpage(struct socket *sock, - struct page *page, - int offset, size_t size, - int flags); +int sock_no_bind(struct socket *, struct sockaddr *, int); +int sock_no_connect(struct socket *, struct sockaddr *, int, int); +int sock_no_socketpair(struct socket *, struct socket *); +int sock_no_accept(struct socket *, struct socket *, int); +int sock_no_getname(struct socket *, struct sockaddr *, int *, int); +unsigned int sock_no_poll(struct file *, struct socket *, + struct poll_table_struct *); +int sock_no_ioctl(struct socket *, unsigned int, unsigned long); +int sock_no_listen(struct socket *, int); +int sock_no_shutdown(struct socket *, int); +int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *); +int sock_no_setsockopt(struct socket *, int, int, char __user *, unsigned int); +int sock_no_sendmsg(struct kiocb *, struct socket *, struct msghdr *, size_t); +int sock_no_recvmsg(struct kiocb *, struct socket *, struct msghdr *, size_t, + int); +int sock_no_mmap(struct file *file, struct socket *sock, + struct vm_area_struct *vma); +ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, + size_t size, int flags); /* * Functions to fill in entries in struct proto_ops when a protocol * uses the inet style. */ -extern int sock_common_getsockopt(struct socket *sock, int level, int optname, +int sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); -extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, +int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags); -extern int sock_common_setsockopt(struct socket *sock, int level, int optname, +int sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen); -extern int compat_sock_common_getsockopt(struct socket *sock, int level, +int compat_sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); -extern int compat_sock_common_setsockopt(struct socket *sock, int level, +int compat_sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen); -extern void sk_common_release(struct sock *sk); +void sk_common_release(struct sock *sk); /* * Default socket callbacks and setup code */ /* Initialise core socket variables */ -extern void sock_init_data(struct socket *sock, struct sock *sk); +void sock_init_data(struct socket *sock, struct sock *sk); -extern void sk_filter_release_rcu(struct rcu_head *rcu); +void sk_filter_release_rcu(struct rcu_head *rcu); /** * sk_filter_release - release a socket filter @@ -1669,8 +1645,7 @@ static inline void sock_put(struct sock *sk) sk_free(sk); } -extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb, - const int nested); +int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested); static inline void sk_tx_queue_set(struct sock *sk, int tx_queue) { @@ -1724,8 +1699,8 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) write_unlock_bh(&sk->sk_callback_lock); } -extern kuid_t sock_i_uid(struct sock *sk); -extern unsigned long sock_i_ino(struct sock *sk); +kuid_t sock_i_uid(struct sock *sk); +unsigned long sock_i_ino(struct sock *sk); static inline struct dst_entry * __sk_dst_get(struct sock *sk) @@ -1747,7 +1722,7 @@ sk_dst_get(struct sock *sk) return dst; } -extern void sk_reset_txq(struct sock *sk); +void sk_reset_txq(struct sock *sk); static inline void dst_negative_advice(struct sock *sk) { @@ -1800,16 +1775,16 @@ sk_dst_reset(struct sock *sk) spin_unlock(&sk->sk_dst_lock); } -extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); +struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); -extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); +struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); static inline bool sk_can_gso(const struct sock *sk) { return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); } -extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst); +void sk_setup_caps(struct sock *sk, struct dst_entry *dst); static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags) { @@ -2022,14 +1997,14 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) sk_mem_charge(sk, skb->truesize); } -extern void sk_reset_timer(struct sock *sk, struct timer_list *timer, - unsigned long expires); +void sk_reset_timer(struct sock *sk, struct timer_list *timer, + unsigned long expires); -extern void sk_stop_timer(struct sock *sk, struct timer_list *timer); +void sk_stop_timer(struct sock *sk, struct timer_list *timer); -extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); +int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); -extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb); +int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb); /* * Recover an error report and clear atomically @@ -2097,7 +2072,7 @@ static inline struct page_frag *sk_page_frag(struct sock *sk) return &sk->sk_frag; } -extern bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag); +bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag); /* * Default write policy as shown to user space via poll/select/SIGIO @@ -2135,10 +2110,10 @@ static inline int sock_intr_errno(long timeo) return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR; } -extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, - struct sk_buff *skb); -extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, - struct sk_buff *skb); +void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, + struct sk_buff *skb); +void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, + struct sk_buff *skb); static inline void sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) @@ -2171,8 +2146,8 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) __sock_recv_wifi_status(msg, sk, skb); } -extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, - struct sk_buff *skb); +void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, + struct sk_buff *skb); static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) @@ -2197,7 +2172,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, * * Currently only depends on SOCK_TIMESTAMPING* flags. */ -extern void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags); +void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags); /** * sk_eat_skb - Release a skb if it is no longer needed @@ -2261,11 +2236,11 @@ static inline struct sock *skb_steal_sock(struct sk_buff *skb) return NULL; } -extern void sock_enable_timestamp(struct sock *sk, int flag); -extern int sock_get_timestamp(struct sock *, struct timeval __user *); -extern int sock_get_timestampns(struct sock *, struct timespec __user *); -extern int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, - int level, int type); +void sock_enable_timestamp(struct sock *sk, int flag); +int sock_get_timestamp(struct sock *, struct timeval __user *); +int sock_get_timestampns(struct sock *, struct timespec __user *); +int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level, + int type); /* * Enable debug/info messages -- cgit From f6982299f273b827c8fe80c4c34e9fcdf95af20d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 22 Sep 2013 10:32:27 -0700 Subject: stp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/stp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/stp.h b/include/net/stp.h index ad447f105417..3af174d70d9e 100644 --- a/include/net/stp.h +++ b/include/net/stp.h @@ -8,7 +8,7 @@ struct stp_proto { void *data; }; -extern int stp_proto_register(const struct stp_proto *proto); -extern void stp_proto_unregister(const struct stp_proto *proto); +int stp_proto_register(const struct stp_proto *proto); +void stp_proto_unregister(const struct stp_proto *proto); #endif /* _NET_STP_H */ -- cgit From 3f2b9c9cdf389e303b2273679af08aab5f153517 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 17 Sep 2013 05:48:51 +0930 Subject: module: remove rmmod --wait option. The option to wait for a module reference count to reach zero was in the initial module implementation, but it was never supported in modprobe (you had to use rmmod --wait). After discussion with Lucas, It has been deprecated (with a 10 second sleep) in kmod for the last year. This finally removes it: the flag will evoke a printk warning and a normal (non-blocking) remove attempt. Cc: Lucas De Marchi Signed-off-by: Rusty Russell --- include/linux/module.h | 3 --- kernel/module.c | 46 ++++++++-------------------------------------- 2 files changed, 8 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/include/linux/module.h b/include/linux/module.h index 05f2447f8c15..15cd6b1b211e 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -367,9 +367,6 @@ struct module /* What modules do I depend on? */ struct list_head target_list; - /* Who is waiting for us to be unloaded */ - struct task_struct *waiter; - /* Destruction function. */ void (*exit)(void); diff --git a/kernel/module.c b/kernel/module.c index dc582749fa13..947105fd4cab 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -644,8 +644,6 @@ static int module_unload_init(struct module *mod) /* Hold reference count during initialization. */ __this_cpu_write(mod->refptr->incs, 1); - /* Backwards compatibility macros put refcount during init. */ - mod->waiter = current; return 0; } @@ -771,16 +769,9 @@ static int __try_stop_module(void *_sref) static int try_stop_module(struct module *mod, int flags, int *forced) { - if (flags & O_NONBLOCK) { - struct stopref sref = { mod, flags, forced }; + struct stopref sref = { mod, flags, forced }; - return stop_machine(__try_stop_module, &sref, NULL); - } else { - /* We don't need to stop the machine for this. */ - mod->state = MODULE_STATE_GOING; - synchronize_sched(); - return 0; - } + return stop_machine(__try_stop_module, &sref, NULL); } unsigned long module_refcount(struct module *mod) @@ -813,21 +804,6 @@ EXPORT_SYMBOL(module_refcount); /* This exists whether we can unload or not */ static void free_module(struct module *mod); -static void wait_for_zero_refcount(struct module *mod) -{ - /* Since we might sleep for some time, release the mutex first */ - mutex_unlock(&module_mutex); - for (;;) { - pr_debug("Looking at refcount...\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - if (module_refcount(mod) == 0) - break; - schedule(); - } - current->state = TASK_RUNNING; - mutex_lock(&module_mutex); -} - SYSCALL_DEFINE2(delete_module, const char __user *, name_user, unsigned int, flags) { @@ -842,6 +818,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, return -EFAULT; name[MODULE_NAME_LEN-1] = '\0'; + if (!(flags & O_NONBLOCK)) { + printk(KERN_WARNING + "waiting module removal not supported: please upgrade"); + } + if (mutex_lock_interruptible(&module_mutex) != 0) return -EINTR; @@ -859,8 +840,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, /* Doing init or already dying? */ if (mod->state != MODULE_STATE_LIVE) { - /* FIXME: if (force), slam module count and wake up - waiter --RR */ + /* FIXME: if (force), slam module count damn the torpedoes */ pr_debug("%s already dying\n", mod->name); ret = -EBUSY; goto out; @@ -876,18 +856,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, } } - /* Set this up before setting mod->state */ - mod->waiter = current; - /* Stop the machine so refcounts can't move and disable module. */ ret = try_stop_module(mod, flags, &forced); if (ret != 0) goto out; - /* Never wait if forced. */ - if (!forced && module_refcount(mod) != 0) - wait_for_zero_refcount(mod); - mutex_unlock(&module_mutex); /* Final destruction now no one is using it. */ if (mod->exit != NULL) @@ -1005,9 +978,6 @@ void module_put(struct module *module) __this_cpu_inc(module->refptr->decs); trace_module_put(module, _RET_IP_); - /* Maybe they're waiting for us to drop reference? */ - if (unlikely(!module_is_live(module))) - wake_up_process(module->waiter); preempt_enable(); } } -- cgit From cd64647f043e3fd3569bcf068f47f030198ff93a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 23 Sep 2013 16:43:58 +0800 Subject: hung_task: Change sysctl_hung_task_check_count to 'int' As 'sysctl_hung_task_check_count' is 'unsigned long' when this value is assigned to max_count in check_hung_uninterruptible_tasks(), it's truncated to 'int' type. This causes a minor artifact: if we write 2^32 to sysctl.hung_task_check_count, hung task detection will be effectively disabled. With this fix, it will still truncate the user input to 32 bits, but reading sysctl.hung_task_check_count reflects the actual truncated value. Signed-off-by: Li Zefan Acked-by: Ingo Molnar Link: http://lkml.kernel.org/r/523FFF4E.9050401@huawei.com Signed-off-by: Ingo Molnar --- include/linux/sched/sysctl.h | 2 +- kernel/hung_task.c | 2 +- kernel/sysctl.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index bf8086b2506e..9552afa733d8 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -2,8 +2,8 @@ #define _SCHED_SYSCTL_H #ifdef CONFIG_DETECT_HUNG_TASK +extern int sysctl_hung_task_check_count; extern unsigned int sysctl_hung_task_panic; -extern unsigned long sysctl_hung_task_check_count; extern unsigned long sysctl_hung_task_timeout_secs; extern unsigned long sysctl_hung_task_warnings; extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write, diff --git a/kernel/hung_task.c b/kernel/hung_task.c index 3e97fb126e6b..042252383fd2 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c @@ -20,7 +20,7 @@ /* * The number of tasks checked: */ -unsigned long __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT; +int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT; /* * Limit number of tasks checked in a batch. diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b2f06f3c6a3f..b24ed7f87a14 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -962,9 +962,10 @@ static struct ctl_table kern_table[] = { { .procname = "hung_task_check_count", .data = &sysctl_hung_task_check_count, - .maxlen = sizeof(unsigned long), + .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_doulongvec_minmax, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, }, { .procname = "hung_task_timeout_secs", -- cgit From 2a855b644c310d5db5a80b8816c0c7748c167977 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 23 Aug 2013 09:40:42 -0700 Subject: rcu: Make list_splice_init_rcu() account for RCU readers The list_splice_init_rcu() function allows a list visible to RCU readers to be spliced into another list visible to RCU readers. This is OK, except for the use of INIT_LIST_HEAD(), which does pointer updates without doing anything to make those updates safe for concurrent readers. Of course, most of the time INIT_LIST_HEAD() is being used in reader-free contexts, such as initialization or cleanup, so it is OK for it to update pointers in an unsafe-for-RCU-readers manner. This commit therefore creates an INIT_LIST_HEAD_RCU() that uses ACCESS_ONCE() to make the updates reader-safe. The reason that we can use ACCESS_ONCE() instead of the more typical rcu_assign_pointer() is that list_splice_init_rcu() is updating the pointers to reference something that is already visible to readers, so that there is no problem with pre-initialized values. Signed-off-by: Paul E. McKenney --- include/linux/rculist.h | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 4106721c4e5e..45a0a9e81478 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -18,6 +18,21 @@ * be used anywhere you would want to use a list_empty_rcu(). */ +/* + * INIT_LIST_HEAD_RCU - Initialize a list_head visible to RCU readers + * @list: list to be initialized + * + * You should instead use INIT_LIST_HEAD() for normal initialization and + * cleanup tasks, when readers have no access to the list being initialized. + * However, if the list being initialized is visible to readers, you + * need to keep the compiler from being too mischievous. + */ +static inline void INIT_LIST_HEAD_RCU(struct list_head *list) +{ + ACCESS_ONCE(list->next) = list; + ACCESS_ONCE(list->prev) = list; +} + /* * return the ->next pointer of a list_head in an rcu safe * way, we must not access it directly @@ -191,9 +206,13 @@ static inline void list_splice_init_rcu(struct list_head *list, if (list_empty(list)) return; - /* "first" and "last" tracking list, so initialize it. */ + /* + * "first" and "last" tracking list, so initialize it. RCU readers + * have access to this list, so we must use INIT_LIST_HEAD_RCU() + * instead of INIT_LIST_HEAD(). + */ - INIT_LIST_HEAD(list); + INIT_LIST_HEAD_RCU(list); /* * At this point, the list body still points to the source list. -- cgit From 63c4db78e80407976e47bccaa2a4d8251b5a10bc Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 9 Aug 2013 12:19:29 -0700 Subject: rcu: Add tracing to rcu_gp_kthread() This commit adds tracing to the rcu_gp_kthread() function in order to help trace down hangs potentially involving this kthread. Reported-by: Clark Williams Reported-by: Carsten Emde Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 28 +++++++++++++++++++--------- kernel/rcutree.c | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index ee2376cfaab3..60077e12093c 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -39,15 +39,25 @@ TRACE_EVENT(rcu_utilization, #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) /* - * Tracepoint for grace-period events: starting and ending a grace - * period ("start" and "end", respectively), a CPU noting the start - * of a new grace period or the end of an old grace period ("cpustart" - * and "cpuend", respectively), a CPU passing through a quiescent - * state ("cpuqs"), a CPU coming online or going offline ("cpuonl" - * and "cpuofl", respectively), a CPU being kicked for being too - * long in dyntick-idle mode ("kick"), a CPU accelerating its new - * callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU - * accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB"). + * Tracepoint for grace-period events. Takes a string identifying the + * RCU flavor, the grace-period number, and a string identifying the + * grace-period-related event as follows: + * + * "AccReadyCB": CPU acclerates new callbacks to RCU_NEXT_READY_TAIL. + * "AccWaitCB": CPU accelerates new callbacks to RCU_WAIT_TAIL. + * "start": Start a grace period. + * "cpustart": CPU first notices a grace-period start. + * "cpuqs": CPU passes through a quiescent state. + * "cpuonl": CPU comes online. + * "cpuofl": CPU goes offline. + * "reqwait": GP kthread sleeps waiting for grace-period request. + * "reqwaitsig": GP kthread awakened by signal from reqwait state. + * "fqswait": GP kthread waiting until time to force quiescent states. + * "fqsstart": GP kthread starts forcing quiescent states. + * "fqsend": GP kthread done forcing quiescent states. + * "fqswaitsig": GP kthread awakened by signal from fqswait state. + * "end": End a grace period. + * "cpuend": CPU first notices a grace-period end. */ TRACE_EVENT(rcu_grace_period, diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 6d028fdbf86c..78d371526667 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1480,6 +1480,9 @@ static int __noreturn rcu_gp_kthread(void *arg) /* Handle grace-period start. */ for (;;) { + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("reqwait")); wait_event_interruptible(rsp->gp_wq, ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_INIT); @@ -1487,6 +1490,9 @@ static int __noreturn rcu_gp_kthread(void *arg) break; cond_resched(); flush_signals(current); + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("reqwaitsig")); } /* Handle quiescent-state forcing. */ @@ -1500,6 +1506,9 @@ static int __noreturn rcu_gp_kthread(void *arg) for (;;) { if (!ret) rsp->jiffies_force_qs = jiffies + j; + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("fqswait")); ret = wait_event_interruptible_timeout(rsp->gp_wq, ((gf = ACCESS_ONCE(rsp->gp_flags)) & RCU_GP_FLAG_FQS) || @@ -1513,12 +1522,21 @@ static int __noreturn rcu_gp_kthread(void *arg) /* If time for quiescent-state forcing, do it. */ if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) || (gf & RCU_GP_FLAG_FQS)) { + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("fqsstart")); fqs_state = rcu_gp_fqs(rsp, fqs_state); + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("fqsend")); cond_resched(); } else { /* Deal with stray signal. */ cond_resched(); flush_signals(current); + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("fqswaitsig")); } j = jiffies_till_next_fqs; if (j > HZ) { -- cgit From bb311eccbdab974639263060b8452bf304af0b0c Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 9 Aug 2013 16:02:09 -0700 Subject: rcu: Add tracing of normal (non-NOCB) grace-period requests This commit adds tracing to the normal grace-period request points. These are rcu_gp_cleanup(), which checks for the need for another grace period at the end of the previous grace period, and rcu_start_gp_advanced(), which restarts RCU's state machine after an idle period. These trace events are intended to help track down bugs where RCU remains idle despite there being work for it to do. Reported-by: Clark Williams Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 1 + kernel/rcutree.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index 60077e12093c..98466c618ebc 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -45,6 +45,7 @@ TRACE_EVENT(rcu_utilization, * * "AccReadyCB": CPU acclerates new callbacks to RCU_NEXT_READY_TAIL. * "AccWaitCB": CPU accelerates new callbacks to RCU_WAIT_TAIL. + * "newreq": Request a new grace period. * "start": Start a grace period. * "cpustart": CPU first notices a grace-period start. * "cpuqs": CPU passes through a quiescent state. diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 78d371526667..54dd6d03dbb5 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1459,8 +1459,12 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) rsp->fqs_state = RCU_GP_IDLE; rdp = this_cpu_ptr(rsp->rda); rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */ - if (cpu_needs_another_gp(rsp, rdp)) + if (cpu_needs_another_gp(rsp, rdp)) { rsp->gp_flags = 1; + trace_rcu_grace_period(rsp->name, + ACCESS_ONCE(rsp->gpnum), + TPS("newreq")); + } raw_spin_unlock_irq(&rnp->lock); } @@ -1584,6 +1588,8 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, return; } rsp->gp_flags = RCU_GP_FLAG_INIT; + trace_rcu_grace_period(rsp->name, ACCESS_ONCE(rsp->gpnum), + TPS("newreq")); /* * We can't do wakeups while holding the rnp->lock, as that -- cgit From 9261dd0da6c6432f08670719069449c6efe4f7a9 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 14 Aug 2013 16:24:26 -0700 Subject: rcu: Add tracing for rcuo no-CBs CPU wakeup handshake Lost wakeups from call_rcu() to the rcuo kthreads can result in hangs that are difficult to diagnose. This commit therefore adds tracing to help pin down the cause of these hangs. Reported-by: Clark Williams Reported-by: Carsten Emde Signed-off-by: Paul E. McKenney [ paulmck: Add const per kbuild test robot's advice. ] --- include/trace/events/rcu.h | 37 +++++++++++++++++++++++++++++++++++++ kernel/rcutree_plugin.h | 14 +++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index 98466c618ebc..4301cd9e3ee5 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -171,6 +171,42 @@ TRACE_EVENT(rcu_grace_period_init, __entry->grplo, __entry->grphi, __entry->qsmask) ); +/* + * Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended + * to assist debugging of these handoffs. + * + * The first argument is the name of the RCU flavor, and the second is + * the number of the offloaded CPU are extracted. The third and final + * argument is a string as follows: + * + * "WakeEmpty": Wake rcuo kthread, first CB to empty list. + * "WakeOvf": Wake rcuo kthread, CB list is huge. + * "WakeNot": Don't wake rcuo kthread. + * "WakeNotPoll": Don't wake rcuo kthread because it is polling. + * "WokeEmpty": rcuo kthread woke to find empty list. + * "WokeNonEmpty": rcuo kthread woke to find non-empty list. + */ +TRACE_EVENT(rcu_nocb_wake, + + TP_PROTO(const char *rcuname, int cpu, const char *reason), + + TP_ARGS(rcuname, cpu, reason), + + TP_STRUCT__entry( + __field(const char *, rcuname) + __field(int, cpu) + __field(const char *, reason) + ), + + TP_fast_assign( + __entry->rcuname = rcuname; + __entry->cpu = cpu; + __entry->reason = reason; + ), + + TP_printk("%s %d %s", __entry->rcuname, __entry->cpu, __entry->reason) +); + /* * Tracepoint for tasks blocking within preemptible-RCU read-side * critical sections. Track the type of RCU (which one day might @@ -667,6 +703,7 @@ TRACE_EVENT(rcu_barrier, #define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \ level, grplo, grphi, event) \ do { } while (0) +#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0) #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 130c97b027f2..f4ed24b18e77 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -2108,15 +2108,22 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, /* If we are not being polled and there is a kthread, awaken it ... */ t = ACCESS_ONCE(rdp->nocb_kthread); - if (rcu_nocb_poll | !t) + if (rcu_nocb_poll | !t) { + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("WakeNotPoll")); return; + } len = atomic_long_read(&rdp->nocb_q_count); if (old_rhpp == &rdp->nocb_head) { wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ rdp->qlen_last_fqs_check = 0; + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty")); } else if (len > rdp->qlen_last_fqs_check + qhimark) { wake_up_process(t); /* ... or if many callbacks queued. */ rdp->qlen_last_fqs_check = LONG_MAX / 2; + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf")); + } else { + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeNot")); } return; } @@ -2233,10 +2240,15 @@ static int rcu_nocb_kthread(void *arg) wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); list = ACCESS_ONCE(rdp->nocb_head); if (!list) { + if (!rcu_nocb_poll) + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("WokeEmpty")); schedule_timeout_interruptible(1); flush_signals(current); continue; } + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("WokeNonEmpty")); /* * Extract queued callbacks, update counts, and wait -- cgit From 69a79bb12a81024d718e73c52e886907a3777b34 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 15 Aug 2013 13:23:23 -0700 Subject: rcu: Track rcu_nocb_kthread()'s sleeping and awakening This commit adds event traces to track all of rcu_nocb_kthread()'s blocking and awakening. Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 4 ++++ kernel/rcutree_plugin.h | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index 4301cd9e3ee5..a087d82ed431 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -183,8 +183,12 @@ TRACE_EVENT(rcu_grace_period_init, * "WakeOvf": Wake rcuo kthread, CB list is huge. * "WakeNot": Don't wake rcuo kthread. * "WakeNotPoll": Don't wake rcuo kthread because it is polling. + * "Poll": Start of new polling cycle for rcu_nocb_poll. + * "Sleep": Sleep waiting for CBs for !rcu_nocb_poll. * "WokeEmpty": rcuo kthread woke to find empty list. * "WokeNonEmpty": rcuo kthread woke to find non-empty list. + * "WaitQueue": Enqueue partially done, timed wait for it to complete. + * "WokeQueue": Partial enqueue now complete. */ TRACE_EVENT(rcu_nocb_wake, diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 24b01b69be92..21205b185340 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -2230,6 +2230,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) static int rcu_nocb_kthread(void *arg) { int c, cl; + bool firsttime = 1; struct rcu_head *list; struct rcu_head *next; struct rcu_head **tail; @@ -2238,8 +2239,15 @@ static int rcu_nocb_kthread(void *arg) /* Each pass through this loop invokes one batch of callbacks */ for (;;) { /* If not polling, wait for next batch of callbacks. */ - if (!rcu_nocb_poll) + if (!rcu_nocb_poll) { + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("Sleep")); wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); + } else if (firsttime) { + firsttime = 0; + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("Poll")); + } list = ACCESS_ONCE(rdp->nocb_head); if (!list) { if (!rcu_nocb_poll) @@ -2249,6 +2257,7 @@ static int rcu_nocb_kthread(void *arg) flush_signals(current); continue; } + firsttime = 1; trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WokeNonEmpty")); @@ -2271,7 +2280,11 @@ static int rcu_nocb_kthread(void *arg) next = list->next; /* Wait for enqueuing to complete, if needed. */ while (next == NULL && &list->next != tail) { + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("WaitQueue")); schedule_timeout_interruptible(1); + trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, + TPS("WokeQueue")); next = list->next; } debug_rcu_head_unqueue(list); -- cgit From 15f5191b6acbbb38029b06284e8fd20275e7cfe8 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 18 Aug 2013 11:59:25 -0700 Subject: rcu: Avoid sparse warnings in rcu_nocb_wake trace event The event-tracing macros do not like bool tracing arguments, so this commit makes them be of type char. This change has the knock-on effect of making it illegal to pass a pointer into one of these arguments, so also change rcutiny's first call to trace_rcu_batch_end() to convert from pointer to boolean, prefixing with "!!". Reported-by: kbuild test robot Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 10 +++++----- kernel/rcutiny.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index a087d82ed431..aca382266411 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -591,17 +591,17 @@ TRACE_EVENT(rcu_invoke_kfree_callback, TRACE_EVENT(rcu_batch_end, TP_PROTO(const char *rcuname, int callbacks_invoked, - bool cb, bool nr, bool iit, bool risk), + char cb, char nr, char iit, char risk), TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk), TP_STRUCT__entry( __field(const char *, rcuname) __field(int, callbacks_invoked) - __field(bool, cb) - __field(bool, nr) - __field(bool, iit) - __field(bool, risk) + __field(char, cb) + __field(char, nr) + __field(char, iit) + __field(char, risk) ), TP_fast_assign( diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 9ed6075dc562..80b6e273f1c5 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -273,7 +273,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) if (&rcp->rcucblist == rcp->donetail) { RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1)); RCU_TRACE(trace_rcu_batch_end(rcp->name, 0, - ACCESS_ONCE(rcp->rcucblist), + !!ACCESS_ONCE(rcp->rcucblist), need_resched(), is_idle_task(current), false)); -- cgit From 774487611c949e6d194877e7147f6eeeec092b53 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 16 Sep 2013 17:02:00 +0100 Subject: iio: pressure-core: st: Provide support for the Vdd power supply The power to some of the sensors are controlled by regulators. In most cases these are 'always on', but if not they will fail to work until the regulator is enabled using the relevant APIs. This patch allows for the Vdd power supply to be specified by either platform data or Device Tree. Signed-off-by: Lee Jones Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_core.c | 28 ++++++++++++++++++++++++++++ include/linux/iio/common/st_sensors.h | 3 +++ 2 files changed, 31 insertions(+) (limited to 'include') diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 2da411b6925b..baeab109f41d 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -313,6 +314,29 @@ static const struct iio_trigger_ops st_press_trigger_ops = { #define ST_PRESS_TRIGGER_OPS NULL #endif +static void st_press_power_enable(struct iio_dev *indio_dev) +{ + struct st_sensor_data *pdata = iio_priv(indio_dev); + int err; + + /* Regulators not mandatory, but if requested we should enable it. */ + pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd"); + if (!IS_ERR(pdata->vdd)) { + err = regulator_enable(pdata->vdd); + if (err != 0) + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd supply\n"); + } +} + +static void st_press_power_disable(struct iio_dev *indio_dev) +{ + struct st_sensor_data *pdata = iio_priv(indio_dev); + + if (!IS_ERR(pdata->vdd)) + regulator_disable(pdata->vdd); +} + int st_press_common_probe(struct iio_dev *indio_dev, struct st_sensors_platform_data *plat_data) { @@ -323,6 +347,8 @@ int st_press_common_probe(struct iio_dev *indio_dev, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &press_info; + st_press_power_enable(indio_dev); + err = st_sensors_check_device_support(indio_dev, ARRAY_SIZE(st_press_sensors), st_press_sensors); @@ -380,6 +406,8 @@ void st_press_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *pdata = iio_priv(indio_dev); + st_press_power_disable(indio_dev); + iio_device_unregister(indio_dev); if (pdata->get_irq_data_ready(indio_dev) > 0) st_sensors_deallocate_trigger(indio_dev); diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index e732fda6c8e6..968b84e5f380 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -201,6 +202,7 @@ struct st_sensors { * @trig: The trigger in use by the core driver. * @sensor: Pointer to the current sensor struct in use. * @current_fullscale: Maximum range of measure by the sensor. + * @vdd: Pointer to sensor's Vdd power supply * @enabled: Status of the sensor (false->off, true->on). * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. * @buffer_data: Data used by buffer part. @@ -216,6 +218,7 @@ struct st_sensor_data { struct iio_trigger *trig; struct st_sensors *sensor; struct st_sensor_fullscale_avl *current_fullscale; + struct regulator *vdd; bool enabled; bool multiread_bit; -- cgit From 71e1980c8d465fd304d867d36f2246b72513efed Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 16 Sep 2013 17:02:00 +0100 Subject: iio: pressure-core: st: Provide support for the Vdd_IO power supply The power to some of the sensors are controlled by regulators. In most cases these are 'always on', but if not they will fail to work until the regulator is enabled using the relevant APIs. This patch allows for the Vdd_IO power supply to be specified by either platform data or Device Tree. Signed-off-by: Lee Jones Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_core.c | 13 ++++++++++++- include/linux/iio/common/st_sensors.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index baeab109f41d..58083f9d51c5 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -319,7 +319,7 @@ static void st_press_power_enable(struct iio_dev *indio_dev) struct st_sensor_data *pdata = iio_priv(indio_dev); int err; - /* Regulators not mandatory, but if requested we should enable it. */ + /* Regulators not mandatory, but if requested we should enable them. */ pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd"); if (!IS_ERR(pdata->vdd)) { err = regulator_enable(pdata->vdd); @@ -327,6 +327,14 @@ static void st_press_power_enable(struct iio_dev *indio_dev) dev_warn(&indio_dev->dev, "Failed to enable specified Vdd supply\n"); } + + pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio"); + if (!IS_ERR(pdata->vdd_io)) { + err = regulator_enable(pdata->vdd_io); + if (err != 0) + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd_IO supply\n"); + } } static void st_press_power_disable(struct iio_dev *indio_dev) @@ -335,6 +343,9 @@ static void st_press_power_disable(struct iio_dev *indio_dev) if (!IS_ERR(pdata->vdd)) regulator_disable(pdata->vdd); + + if (!IS_ERR(pdata->vdd_io)) + regulator_disable(pdata->vdd_io); } int st_press_common_probe(struct iio_dev *indio_dev, diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 968b84e5f380..3c005eb3a0a4 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -203,6 +203,7 @@ struct st_sensors { * @sensor: Pointer to the current sensor struct in use. * @current_fullscale: Maximum range of measure by the sensor. * @vdd: Pointer to sensor's Vdd power supply + * @vdd_io: Pointer to sensor's Vdd-IO power supply * @enabled: Status of the sensor (false->off, true->on). * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. * @buffer_data: Data used by buffer part. @@ -219,6 +220,7 @@ struct st_sensor_data { struct st_sensors *sensor; struct st_sensor_fullscale_avl *current_fullscale; struct regulator *vdd; + struct regulator *vdd_io; bool enabled; bool multiread_bit; -- cgit From 5c9f30236f53f3fbee170e2452dfa0e5dce4727b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:32 -0700 Subject: tcp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/tcp.h | 424 +++++++++++++++++++++++++++--------------------------- 1 file changed, 208 insertions(+), 216 deletions(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index b1aa324c5e65..0e47551e9bdb 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -50,7 +50,7 @@ extern struct inet_hashinfo tcp_hashinfo; extern struct percpu_counter tcp_orphan_count; -extern void tcp_time_wait(struct sock *sk, int state, int timeo); +void tcp_time_wait(struct sock *sk, int state, int timeo); #define MAX_TCP_HEADER (128 + MAX_HEADER) #define MAX_TCP_OPTION_SPACE 40 @@ -325,7 +325,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift) return false; } -extern bool tcp_check_oom(struct sock *sk, int shift); +bool tcp_check_oom(struct sock *sk, int shift); /* syncookies: remember time of last synqueue overflow */ static inline void tcp_synq_overflow(struct sock *sk) @@ -348,38 +348,38 @@ extern struct proto tcp_prot; #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) -extern void tcp_init_mem(struct net *net); - -extern void tcp_tasklet_init(void); - -extern void tcp_v4_err(struct sk_buff *skb, u32); - -extern void tcp_shutdown (struct sock *sk, int how); - -extern void tcp_v4_early_demux(struct sk_buff *skb); -extern int tcp_v4_rcv(struct sk_buff *skb); - -extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); -extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t size); -extern int tcp_sendpage(struct sock *sk, struct page *page, int offset, - size_t size, int flags); -extern void tcp_release_cb(struct sock *sk); -extern void tcp_wfree(struct sk_buff *skb); -extern void tcp_write_timer_handler(struct sock *sk); -extern void tcp_delack_timer_handler(struct sock *sk); -extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); -extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - const struct tcphdr *th, unsigned int len); -extern void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, - const struct tcphdr *th, unsigned int len); -extern void tcp_rcv_space_adjust(struct sock *sk); -extern void tcp_cleanup_rbuf(struct sock *sk, int copied); -extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp); -extern void tcp_twsk_destructor(struct sock *sk); -extern ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags); +void tcp_init_mem(struct net *net); + +void tcp_tasklet_init(void); + +void tcp_v4_err(struct sk_buff *skb, u32); + +void tcp_shutdown(struct sock *sk, int how); + +void tcp_v4_early_demux(struct sk_buff *skb); +int tcp_v4_rcv(struct sk_buff *skb); + +int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); +int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t size); +int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, + int flags); +void tcp_release_cb(struct sock *sk); +void tcp_wfree(struct sk_buff *skb); +void tcp_write_timer_handler(struct sock *sk); +void tcp_delack_timer_handler(struct sock *sk); +int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); +int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, + const struct tcphdr *th, unsigned int len); +void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, + const struct tcphdr *th, unsigned int len); +void tcp_rcv_space_adjust(struct sock *sk); +void tcp_cleanup_rbuf(struct sock *sk, int copied); +int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp); +void tcp_twsk_destructor(struct sock *sk); +ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); static inline void tcp_dec_quickack_mode(struct sock *sk, const unsigned int pkts) @@ -409,66 +409,65 @@ enum tcp_tw_status { }; -extern enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw, - struct sk_buff *skb, - const struct tcphdr *th); -extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb, - struct request_sock *req, - struct request_sock **prev, - bool fastopen); -extern int tcp_child_process(struct sock *parent, struct sock *child, - struct sk_buff *skb); -extern void tcp_enter_loss(struct sock *sk, int how); -extern void tcp_clear_retrans(struct tcp_sock *tp); -extern void tcp_update_metrics(struct sock *sk); -extern void tcp_init_metrics(struct sock *sk); -extern void tcp_metrics_init(void); -extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check); -extern bool tcp_remember_stamp(struct sock *sk); -extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw); -extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst); -extern void tcp_disable_fack(struct tcp_sock *tp); -extern void tcp_close(struct sock *sk, long timeout); -extern void tcp_init_sock(struct sock *sk); -extern unsigned int tcp_poll(struct file * file, struct socket *sock, - struct poll_table_struct *wait); -extern int tcp_getsockopt(struct sock *sk, int level, int optname, +enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw, + struct sk_buff *skb, + const struct tcphdr *th); +struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + struct request_sock *req, struct request_sock **prev, + bool fastopen); +int tcp_child_process(struct sock *parent, struct sock *child, + struct sk_buff *skb); +void tcp_enter_loss(struct sock *sk, int how); +void tcp_clear_retrans(struct tcp_sock *tp); +void tcp_update_metrics(struct sock *sk); +void tcp_init_metrics(struct sock *sk); +void tcp_metrics_init(void); +bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, + bool paws_check); +bool tcp_remember_stamp(struct sock *sk); +bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw); +void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst); +void tcp_disable_fack(struct tcp_sock *tp); +void tcp_close(struct sock *sk, long timeout); +void tcp_init_sock(struct sock *sk); +unsigned int tcp_poll(struct file *file, struct socket *sock, + struct poll_table_struct *wait); +int tcp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +int tcp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen); +int compat_tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); -extern int tcp_setsockopt(struct sock *sk, int level, int optname, +int compat_tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); -extern int compat_tcp_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen); -extern int compat_tcp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, unsigned int optlen); -extern void tcp_set_keepalive(struct sock *sk, int val); -extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req); -extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int nonblock, int flags, int *addr_len); -extern void tcp_parse_options(const struct sk_buff *skb, - struct tcp_options_received *opt_rx, - int estab, struct tcp_fastopen_cookie *foc); -extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); +void tcp_set_keepalive(struct sock *sk, int val); +void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req); +int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int nonblock, int flags, int *addr_len); +void tcp_parse_options(const struct sk_buff *skb, + struct tcp_options_received *opt_rx, + int estab, struct tcp_fastopen_cookie *foc); +const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); /* * TCP v4 functions exported for the inet6 API */ -extern void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); -extern int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); -extern struct sock * tcp_create_openreq_child(struct sock *sk, - struct request_sock *req, - struct sk_buff *skb); -extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, - struct request_sock *req, - struct dst_entry *dst); -extern int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb); -extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, - int addr_len); -extern int tcp_connect(struct sock *sk); -extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, - struct request_sock *req, - struct tcp_fastopen_cookie *foc); -extern int tcp_disconnect(struct sock *sk, int flags); +void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); +int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); +struct sock *tcp_create_openreq_child(struct sock *sk, + struct request_sock *req, + struct sk_buff *skb); +struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + struct request_sock *req, + struct dst_entry *dst); +int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb); +int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); +int tcp_connect(struct sock *sk); +struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, + struct request_sock *req, + struct tcp_fastopen_cookie *foc); +int tcp_disconnect(struct sock *sk, int flags); void tcp_connect_init(struct sock *sk); void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); @@ -477,15 +476,14 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb); /* From syncookies.c */ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; -extern int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, - u32 cookie); -extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, - struct ip_options *opt); +int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, + u32 cookie); +struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, + struct ip_options *opt); #ifdef CONFIG_SYN_COOKIES -extern u32 __cookie_v4_init_sequence(const struct iphdr *iph, - const struct tcphdr *th, u16 *mssp); -extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, - __u16 *mss); +u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th, + u16 *mssp); +__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mss); #else static inline __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, @@ -495,19 +493,19 @@ static inline __u32 cookie_v4_init_sequence(struct sock *sk, } #endif -extern __u32 cookie_init_timestamp(struct request_sock *req); -extern bool cookie_check_timestamp(struct tcp_options_received *opt, - struct net *net, bool *ecn_ok); +__u32 cookie_init_timestamp(struct request_sock *req); +bool cookie_check_timestamp(struct tcp_options_received *opt, struct net *net, + bool *ecn_ok); /* From net/ipv6/syncookies.c */ -extern int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, - u32 cookie); -extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); +int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, + u32 cookie); +struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); #ifdef CONFIG_SYN_COOKIES -extern u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, - const struct tcphdr *th, u16 *mssp); -extern __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, - __u16 *mss); +u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, + const struct tcphdr *th, u16 *mssp); +__u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, + __u16 *mss); #else static inline __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, @@ -518,47 +516,46 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk, #endif /* tcp_output.c */ -extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, - int nonagle); -extern bool tcp_may_send_now(struct sock *sk); -extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *); -extern int tcp_retransmit_skb(struct sock *, struct sk_buff *); -extern void tcp_retransmit_timer(struct sock *sk); -extern void tcp_xmit_retransmit_queue(struct sock *); -extern void tcp_simple_retransmit(struct sock *); -extern int tcp_trim_head(struct sock *, struct sk_buff *, u32); -extern int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int); - -extern void tcp_send_probe0(struct sock *); -extern void tcp_send_partial(struct sock *); -extern int tcp_write_wakeup(struct sock *); -extern void tcp_send_fin(struct sock *sk); -extern void tcp_send_active_reset(struct sock *sk, gfp_t priority); -extern int tcp_send_synack(struct sock *); -extern bool tcp_syn_flood_action(struct sock *sk, - const struct sk_buff *skb, - const char *proto); -extern void tcp_push_one(struct sock *, unsigned int mss_now); -extern void tcp_send_ack(struct sock *sk); -extern void tcp_send_delayed_ack(struct sock *sk); -extern void tcp_send_loss_probe(struct sock *sk); -extern bool tcp_schedule_loss_probe(struct sock *sk); +void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, + int nonagle); +bool tcp_may_send_now(struct sock *sk); +int __tcp_retransmit_skb(struct sock *, struct sk_buff *); +int tcp_retransmit_skb(struct sock *, struct sk_buff *); +void tcp_retransmit_timer(struct sock *sk); +void tcp_xmit_retransmit_queue(struct sock *); +void tcp_simple_retransmit(struct sock *); +int tcp_trim_head(struct sock *, struct sk_buff *, u32); +int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int); + +void tcp_send_probe0(struct sock *); +void tcp_send_partial(struct sock *); +int tcp_write_wakeup(struct sock *); +void tcp_send_fin(struct sock *sk); +void tcp_send_active_reset(struct sock *sk, gfp_t priority); +int tcp_send_synack(struct sock *); +bool tcp_syn_flood_action(struct sock *sk, const struct sk_buff *skb, + const char *proto); +void tcp_push_one(struct sock *, unsigned int mss_now); +void tcp_send_ack(struct sock *sk); +void tcp_send_delayed_ack(struct sock *sk); +void tcp_send_loss_probe(struct sock *sk); +bool tcp_schedule_loss_probe(struct sock *sk); /* tcp_input.c */ -extern void tcp_cwnd_application_limited(struct sock *sk); -extern void tcp_resume_early_retransmit(struct sock *sk); -extern void tcp_rearm_rto(struct sock *sk); -extern void tcp_reset(struct sock *sk); +void tcp_cwnd_application_limited(struct sock *sk); +void tcp_resume_early_retransmit(struct sock *sk); +void tcp_rearm_rto(struct sock *sk); +void tcp_reset(struct sock *sk); /* tcp_timer.c */ -extern void tcp_init_xmit_timers(struct sock *); +void tcp_init_xmit_timers(struct sock *); static inline void tcp_clear_xmit_timers(struct sock *sk) { inet_csk_clear_xmit_timers(sk); } -extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu); -extern unsigned int tcp_current_mss(struct sock *sk); +unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu); +unsigned int tcp_current_mss(struct sock *sk); /* Bound MSS / TSO packet size with the half of the window */ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) @@ -584,20 +581,20 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) } /* tcp.c */ -extern void tcp_get_info(const struct sock *, struct tcp_info *); +void tcp_get_info(const struct sock *, struct tcp_info *); /* Read 'sendfile()'-style from a TCP socket */ typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *, unsigned int, size_t); -extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, - sk_read_actor_t recv_actor); +int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t recv_actor); -extern void tcp_initialize_rcv_mss(struct sock *sk); +void tcp_initialize_rcv_mss(struct sock *sk); -extern int tcp_mtu_to_mss(struct sock *sk, int pmtu); -extern int tcp_mss_to_mtu(struct sock *sk, int mss); -extern void tcp_mtup_init(struct sock *sk); -extern void tcp_init_buffer_space(struct sock *sk); +int tcp_mtu_to_mss(struct sock *sk, int pmtu); +int tcp_mss_to_mtu(struct sock *sk, int mss); +void tcp_mtup_init(struct sock *sk); +void tcp_init_buffer_space(struct sock *sk); static inline void tcp_bound_rto(const struct sock *sk) { @@ -610,7 +607,7 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp) return (tp->srtt >> 3) + tp->rttvar; } -extern void tcp_set_rto(struct sock *sk); +void tcp_set_rto(struct sock *sk); static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd) { @@ -663,7 +660,7 @@ static inline u32 tcp_receive_window(const struct tcp_sock *tp) * scaling applied to the result. The caller does these things * if necessary. This is a "raw" window selection. */ -extern u32 __tcp_select_window(struct sock *sk); +u32 __tcp_select_window(struct sock *sk); void tcp_send_window_probe(struct sock *sk); @@ -800,24 +797,24 @@ struct tcp_congestion_ops { struct module *owner; }; -extern int tcp_register_congestion_control(struct tcp_congestion_ops *type); -extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type); +int tcp_register_congestion_control(struct tcp_congestion_ops *type); +void tcp_unregister_congestion_control(struct tcp_congestion_ops *type); -extern void tcp_init_congestion_control(struct sock *sk); -extern void tcp_cleanup_congestion_control(struct sock *sk); -extern int tcp_set_default_congestion_control(const char *name); -extern void tcp_get_default_congestion_control(char *name); -extern void tcp_get_available_congestion_control(char *buf, size_t len); -extern void tcp_get_allowed_congestion_control(char *buf, size_t len); -extern int tcp_set_allowed_congestion_control(char *allowed); -extern int tcp_set_congestion_control(struct sock *sk, const char *name); -extern void tcp_slow_start(struct tcp_sock *tp); -extern void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w); +void tcp_init_congestion_control(struct sock *sk); +void tcp_cleanup_congestion_control(struct sock *sk); +int tcp_set_default_congestion_control(const char *name); +void tcp_get_default_congestion_control(char *name); +void tcp_get_available_congestion_control(char *buf, size_t len); +void tcp_get_allowed_congestion_control(char *buf, size_t len); +int tcp_set_allowed_congestion_control(char *allowed); +int tcp_set_congestion_control(struct sock *sk, const char *name); +void tcp_slow_start(struct tcp_sock *tp); +void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w); extern struct tcp_congestion_ops tcp_init_congestion_ops; -extern u32 tcp_reno_ssthresh(struct sock *sk); -extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight); -extern u32 tcp_reno_min_cwnd(const struct sock *sk); +u32 tcp_reno_ssthresh(struct sock *sk); +void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight); +u32 tcp_reno_min_cwnd(const struct sock *sk); extern struct tcp_congestion_ops tcp_reno; static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state) @@ -936,8 +933,8 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk) /* Use define here intentionally to get WARN_ON location shown at the caller */ #define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out) -extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh); -extern __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst); +void tcp_enter_cwr(struct sock *sk, const int set_ssthresh); +__u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst); /* The maximum number of MSS of available cwnd for which TSO defers * sending if not using sysctl_tcp_tso_win_divisor. @@ -963,7 +960,7 @@ static inline u32 tcp_wnd_end(const struct tcp_sock *tp) { return tp->snd_una + tp->snd_wnd; } -extern bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight); +bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight); static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss, const struct sk_buff *skb) @@ -1028,7 +1025,7 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp) #endif } -extern bool tcp_prequeue(struct sock *sk, struct sk_buff *skb); +bool tcp_prequeue(struct sock *sk, struct sk_buff *skb); #undef STATE_TRACE @@ -1039,9 +1036,9 @@ static const char *statename[]={ "Close Wait","Last ACK","Listen","Closing" }; #endif -extern void tcp_set_state(struct sock *sk, int state); +void tcp_set_state(struct sock *sk, int state); -extern void tcp_done(struct sock *sk); +void tcp_done(struct sock *sk); static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) { @@ -1049,13 +1046,12 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) rx_opt->num_sacks = 0; } -extern u32 tcp_default_init_rwnd(u32 mss); +u32 tcp_default_init_rwnd(u32 mss); /* Determine a window scaling and initial window to offer. */ -extern void tcp_select_initial_window(int __space, __u32 mss, - __u32 *rcv_wnd, __u32 *window_clamp, - int wscale_ok, __u8 *rcv_wscale, - __u32 init_rcv_wnd); +void tcp_select_initial_window(int __space, __u32 mss, __u32 *rcv_wnd, + __u32 *window_clamp, int wscale_ok, + __u8 *rcv_wscale, __u32 init_rcv_wnd); static inline int tcp_win_from_space(int space) { @@ -1099,7 +1095,7 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->loc_port = tcp_hdr(skb)->dest; } -extern void tcp_enter_memory_pressure(struct sock *sk); +void tcp_enter_memory_pressure(struct sock *sk); static inline int keepalive_intvl_when(const struct tcp_sock *tp) { @@ -1252,21 +1248,20 @@ struct tcp_md5sig_pool { }; /* - functions */ -extern int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, - const struct sock *sk, - const struct request_sock *req, - const struct sk_buff *skb); -extern int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, - int family, const u8 *newkey, - u8 newkeylen, gfp_t gfp); -extern int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, - int family); -extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, +int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, + const struct sock *sk, const struct request_sock *req, + const struct sk_buff *skb); +int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, + int family, const u8 *newkey, u8 newkeylen, gfp_t gfp); +int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, + int family); +struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, struct sock *addr_sk); #ifdef CONFIG_TCP_MD5SIG -extern struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, - const union tcp_md5_addr *addr, int family); +struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, + const union tcp_md5_addr *addr, + int family); #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key) #else static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, @@ -1278,27 +1273,26 @@ static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, #define tcp_twsk_md5_key(twsk) NULL #endif -extern bool tcp_alloc_md5sig_pool(void); +bool tcp_alloc_md5sig_pool(void); -extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void); +struct tcp_md5sig_pool *tcp_get_md5sig_pool(void); static inline void tcp_put_md5sig_pool(void) { local_bh_enable(); } -extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *); -extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *, - unsigned int header_len); -extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, - const struct tcp_md5sig_key *key); +int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *); +int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *, + unsigned int header_len); +int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, + const struct tcp_md5sig_key *key); /* From tcp_fastopen.c */ -extern void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, - struct tcp_fastopen_cookie *cookie, - int *syn_loss, unsigned long *last_syn_loss); -extern void tcp_fastopen_cache_set(struct sock *sk, u16 mss, - struct tcp_fastopen_cookie *cookie, - bool syn_lost); +void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, + struct tcp_fastopen_cookie *cookie, int *syn_loss, + unsigned long *last_syn_loss); +void tcp_fastopen_cache_set(struct sock *sk, u16 mss, + struct tcp_fastopen_cookie *cookie, bool syn_lost); struct tcp_fastopen_request { /* Fast Open cookie. Size 0 means a cookie request */ struct tcp_fastopen_cookie cookie; @@ -1309,8 +1303,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp); extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; int tcp_fastopen_reset_cipher(void *key, unsigned int len); -extern void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, - struct tcp_fastopen_cookie *foc); +void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, + struct tcp_fastopen_cookie *foc); #define TCP_FASTOPEN_KEY_LENGTH 16 @@ -1529,22 +1523,20 @@ struct tcp_iter_state { loff_t last_pos; }; -extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo); -extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo); +int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo); +void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo); extern struct request_sock_ops tcp_request_sock_ops; extern struct request_sock_ops tcp6_request_sock_ops; -extern void tcp_v4_destroy_sock(struct sock *sk); +void tcp_v4_destroy_sock(struct sock *sk); -extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, - netdev_features_t features); -extern struct sk_buff **tcp_gro_receive(struct sk_buff **head, - struct sk_buff *skb); -extern int tcp_gro_complete(struct sk_buff *skb); +struct sk_buff *tcp_tso_segment(struct sk_buff *skb, + netdev_features_t features); +struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb); +int tcp_gro_complete(struct sk_buff *skb); -extern void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, - __be32 daddr); +void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr); static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp) { @@ -1560,8 +1552,8 @@ static inline bool tcp_stream_memory_free(const struct sock *sk) } #ifdef CONFIG_PROC_FS -extern int tcp4_proc_init(void); -extern void tcp4_proc_exit(void); +int tcp4_proc_init(void); +void tcp4_proc_exit(void); #endif /* TCP af-specific functions */ @@ -1592,9 +1584,9 @@ struct tcp_request_sock_ops { #endif }; -extern int tcpv4_offload_init(void); +int tcpv4_offload_init(void); -extern void tcp_v4_init(void); -extern void tcp_init(void); +void tcp_v4_init(void); +void tcp_init(void); #endif /* _TCP_H */ -- cgit From 1a50bd064e1825ad0cc049be2d205ac6719f88e5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:36 -0700 Subject: udp.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/udp.h | 94 +++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/include/net/udp.h b/include/net/udp.h index ef2e0b7843a0..510b8cb4d1a7 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -79,7 +79,7 @@ struct udp_table { unsigned int log; }; extern struct udp_table udp_table; -extern void udp_table_init(struct udp_table *, const char *); +void udp_table_init(struct udp_table *, const char *); static inline struct udp_hslot *udp_hashslot(struct udp_table *table, struct net *net, unsigned int num) { @@ -162,52 +162,52 @@ static inline void udp_lib_hash(struct sock *sk) BUG(); } -extern void udp_lib_unhash(struct sock *sk); -extern void udp_lib_rehash(struct sock *sk, u16 new_hash); +void udp_lib_unhash(struct sock *sk); +void udp_lib_rehash(struct sock *sk, u16 new_hash); static inline void udp_lib_close(struct sock *sk, long timeout) { sk_common_release(sk); } -extern int udp_lib_get_port(struct sock *sk, unsigned short snum, - int (*)(const struct sock *,const struct sock *), - unsigned int hash2_nulladdr); +int udp_lib_get_port(struct sock *sk, unsigned short snum, + int (*)(const struct sock *, const struct sock *), + unsigned int hash2_nulladdr); /* net/ipv4/udp.c */ -extern int udp_get_port(struct sock *sk, unsigned short snum, - int (*saddr_cmp)(const struct sock *, - const struct sock *)); -extern void udp_err(struct sk_buff *, u32); -extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, - struct msghdr *msg, size_t len); -extern int udp_push_pending_frames(struct sock *sk); -extern void udp_flush_pending_frames(struct sock *sk); -extern void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst); -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 unsigned int udp_poll(struct file *file, struct socket *sock, - poll_table *wait); -extern struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, - netdev_features_t features); -extern int udp_lib_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen); -extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, unsigned int optlen, - int (*push_pending_frames)(struct sock *)); -extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, - int dif); -extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, - int dif, struct udp_table *tbl); -extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, - const struct in6_addr *daddr, __be16 dport, - int dif); -extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, - const struct in6_addr *daddr, __be16 dport, - int dif, struct udp_table *tbl); +int udp_get_port(struct sock *sk, unsigned short snum, + int (*saddr_cmp)(const struct sock *, + const struct sock *)); +void udp_err(struct sk_buff *, u32); +int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int udp_push_pending_frames(struct sock *sk); +void udp_flush_pending_frames(struct sock *sk); +void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst); +int udp_rcv(struct sk_buff *skb); +int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); +int udp_disconnect(struct sock *sk, int flags); +unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); +struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, + netdev_features_t features); +int udp_lib_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +int udp_lib_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen, + int (*push_pending_frames)(struct sock *)); +struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, int dif); +struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, int dif, + struct udp_table *tbl); +struct sock *udp6_lib_lookup(struct net *net, + const struct in6_addr *saddr, __be16 sport, + const struct in6_addr *daddr, __be16 dport, + int dif); +struct sock *__udp6_lib_lookup(struct net *net, + const struct in6_addr *saddr, __be16 sport, + const struct in6_addr *daddr, __be16 dport, + int dif, struct udp_table *tbl); /* * SNMP statistics for UDP and UDP-Lite @@ -259,19 +259,19 @@ struct udp_iter_state { }; #ifdef CONFIG_PROC_FS -extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo); -extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo); +int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo); +void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo); -extern int udp4_proc_init(void); -extern void udp4_proc_exit(void); +int udp4_proc_init(void); +void udp4_proc_exit(void); #endif -extern int udpv4_offload_init(void); +int udpv4_offload_init(void); -extern void udp_init(void); +void udp_init(void); -extern void udp_encap_enable(void); +void udp_encap_enable(void); #if IS_ENABLED(CONFIG_IPV6) -extern void udpv6_encap_enable(void); +void udpv6_encap_enable(void); #endif #endif /* _UDP_H */ -- cgit From 160734399f968e4ac4d2f1db844c9c85a4952e05 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:39 -0700 Subject: udplite.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/udplite.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/udplite.h b/include/net/udplite.h index 71375459a884..2caadabcd07b 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -126,7 +126,7 @@ static inline __wsum udplite_csum(struct sk_buff *skb) return skb_checksum(skb, off, len, 0); } -extern void udplite4_register(void); -extern int udplite_get_port(struct sock *sk, unsigned short snum, - int (*scmp)(const struct sock *, const struct sock *)); +void udplite4_register(void); +int udplite_get_port(struct sock *sk, unsigned short snum, + int (*scmp)(const struct sock *, const struct sock *)); #endif /* _UDPLITE_H */ -- cgit From 9e4638cdc894698db6e1de10565ae404748f16c5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:42 -0700 Subject: wext.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/wext.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/net/wext.h b/include/net/wext.h index 4f6e7423174c..345911965dbb 100644 --- a/include/net/wext.h +++ b/include/net/wext.h @@ -6,13 +6,13 @@ struct net; #ifdef CONFIG_WEXT_CORE -extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, - void __user *arg); -extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, - unsigned long arg); +int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, + void __user *arg); +int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, + unsigned long arg); -extern struct iw_statistics *get_wireless_stats(struct net_device *dev); -extern int call_commit_handler(struct net_device *dev); +struct iw_statistics *get_wireless_stats(struct net_device *dev); +int call_commit_handler(struct net_device *dev); #else static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, void __user *arg) @@ -27,8 +27,8 @@ static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, #endif #ifdef CONFIG_WEXT_PROC -extern int wext_proc_init(struct net *net); -extern void wext_proc_exit(struct net *net); +int wext_proc_init(struct net *net); +void wext_proc_exit(struct net *net); #else static inline int wext_proc_init(struct net *net) { -- cgit From 6dfd43d28c92a6d00a3bbccb2aa978de8c1c96b8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:45 -0700 Subject: wimax.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/wimax.h | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/net/wimax.h b/include/net/wimax.h index bbb74f990cab..98498e1daa06 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -438,9 +438,9 @@ struct wimax_dev { * * These functions are not exported to user space. */ -extern void wimax_dev_init(struct wimax_dev *); -extern int wimax_dev_add(struct wimax_dev *, struct net_device *); -extern void wimax_dev_rm(struct wimax_dev *); +void wimax_dev_init(struct wimax_dev *); +int wimax_dev_add(struct wimax_dev *, struct net_device *); +void wimax_dev_rm(struct wimax_dev *); static inline struct wimax_dev *net_dev_to_wimax(struct net_device *net_dev) @@ -454,8 +454,8 @@ struct device *wimax_dev_to_dev(struct wimax_dev *wimax_dev) return wimax_dev->net_dev->dev.parent; } -extern void wimax_state_change(struct wimax_dev *, enum wimax_st); -extern enum wimax_st wimax_state_get(struct wimax_dev *); +void wimax_state_change(struct wimax_dev *, enum wimax_st); +enum wimax_st wimax_state_get(struct wimax_dev *); /* * Radio Switch state reporting. @@ -463,8 +463,8 @@ extern enum wimax_st wimax_state_get(struct wimax_dev *); * enum wimax_rf_state is declared in linux/wimax.h so the exports * to user space can use it. */ -extern void wimax_report_rfkill_hw(struct wimax_dev *, enum wimax_rf_state); -extern void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state); +void wimax_report_rfkill_hw(struct wimax_dev *, enum wimax_rf_state); +void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state); /* @@ -490,15 +490,14 @@ extern void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state); * send diagnostics information that a device-specific diagnostics * tool would be interested in. */ -extern struct sk_buff *wimax_msg_alloc(struct wimax_dev *, const char *, - const void *, size_t, gfp_t); -extern int wimax_msg_send(struct wimax_dev *, struct sk_buff *); -extern int wimax_msg(struct wimax_dev *, const char *, - const void *, size_t, gfp_t); +struct sk_buff *wimax_msg_alloc(struct wimax_dev *, const char *, const void *, + size_t, gfp_t); +int wimax_msg_send(struct wimax_dev *, struct sk_buff *); +int wimax_msg(struct wimax_dev *, const char *, const void *, size_t, gfp_t); -extern const void *wimax_msg_data_len(struct sk_buff *, size_t *); -extern const void *wimax_msg_data(struct sk_buff *); -extern ssize_t wimax_msg_len(struct sk_buff *); +const void *wimax_msg_data_len(struct sk_buff *, size_t *); +const void *wimax_msg_data(struct sk_buff *); +ssize_t wimax_msg_len(struct sk_buff *); /* @@ -513,7 +512,7 @@ extern ssize_t wimax_msg_len(struct sk_buff *); * device's control structure and (as such) the 'struct wimax_dev' is * referenced by the caller. */ -extern int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state); -extern int wimax_reset(struct wimax_dev *); +int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state); +int wimax_reset(struct wimax_dev *); #endif /* #ifndef __NET__WIMAX_H__ */ -- cgit From 5db50ee6e617c347a24b18ee229e44ba8d4d84a3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:49 -0700 Subject: x25.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/x25.h | 141 +++++++++++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/include/net/x25.h b/include/net/x25.h index b4a8a8923128..c383aa4edbf0 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -187,57 +187,57 @@ extern int sysctl_x25_clear_request_timeout; extern int sysctl_x25_ack_holdback_timeout; extern int sysctl_x25_forward; -extern int x25_parse_address_block(struct sk_buff *skb, - struct x25_address *called_addr, - struct x25_address *calling_addr); - -extern int x25_addr_ntoa(unsigned char *, struct x25_address *, - struct x25_address *); -extern int x25_addr_aton(unsigned char *, struct x25_address *, - struct x25_address *); -extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *); -extern void x25_destroy_socket_from_timer(struct sock *); -extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int); -extern void x25_kill_by_neigh(struct x25_neigh *); +int x25_parse_address_block(struct sk_buff *skb, + struct x25_address *called_addr, + struct x25_address *calling_addr); + +int x25_addr_ntoa(unsigned char *, struct x25_address *, struct x25_address *); +int x25_addr_aton(unsigned char *, struct x25_address *, struct x25_address *); +struct sock *x25_find_socket(unsigned int, struct x25_neigh *); +void x25_destroy_socket_from_timer(struct sock *); +int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int); +void x25_kill_by_neigh(struct x25_neigh *); /* x25_dev.c */ -extern void x25_send_frame(struct sk_buff *, struct x25_neigh *); -extern int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); -extern void x25_establish_link(struct x25_neigh *); -extern void x25_terminate_link(struct x25_neigh *); +void x25_send_frame(struct sk_buff *, struct x25_neigh *); +int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, + struct packet_type *, struct net_device *); +void x25_establish_link(struct x25_neigh *); +void x25_terminate_link(struct x25_neigh *); /* x25_facilities.c */ -extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, - struct x25_dte_facilities *, unsigned long *); -extern int x25_create_facilities(unsigned char *, struct x25_facilities *, - struct x25_dte_facilities *, unsigned long); -extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, - struct x25_facilities *, - struct x25_dte_facilities *); -extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *); +int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, + struct x25_dte_facilities *, unsigned long *); +int x25_create_facilities(unsigned char *, struct x25_facilities *, + struct x25_dte_facilities *, unsigned long); +int x25_negotiate_facilities(struct sk_buff *, struct sock *, + struct x25_facilities *, + struct x25_dte_facilities *); +void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *); /* x25_forward.c */ -extern void x25_clear_forward_by_lci(unsigned int lci); -extern void x25_clear_forward_by_dev(struct net_device *); -extern int x25_forward_data(int, struct x25_neigh *, struct sk_buff *); -extern int x25_forward_call(struct x25_address *, struct x25_neigh *, - struct sk_buff *, int); +void x25_clear_forward_by_lci(unsigned int lci); +void x25_clear_forward_by_dev(struct net_device *); +int x25_forward_data(int, struct x25_neigh *, struct sk_buff *); +int x25_forward_call(struct x25_address *, struct x25_neigh *, struct sk_buff *, + int); /* x25_in.c */ -extern int x25_process_rx_frame(struct sock *, struct sk_buff *); -extern int x25_backlog_rcv(struct sock *, struct sk_buff *); +int x25_process_rx_frame(struct sock *, struct sk_buff *); +int x25_backlog_rcv(struct sock *, struct sk_buff *); /* x25_link.c */ -extern void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short); -extern void x25_link_device_up(struct net_device *); -extern void x25_link_device_down(struct net_device *); -extern void x25_link_established(struct x25_neigh *); -extern void x25_link_terminated(struct x25_neigh *); -extern void x25_transmit_clear_request(struct x25_neigh *, unsigned int, unsigned char); -extern void x25_transmit_link(struct sk_buff *, struct x25_neigh *); -extern int x25_subscr_ioctl(unsigned int, void __user *); -extern struct x25_neigh *x25_get_neigh(struct net_device *); -extern void x25_link_free(void); +void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short); +void x25_link_device_up(struct net_device *); +void x25_link_device_down(struct net_device *); +void x25_link_established(struct x25_neigh *); +void x25_link_terminated(struct x25_neigh *); +void x25_transmit_clear_request(struct x25_neigh *, unsigned int, + unsigned char); +void x25_transmit_link(struct sk_buff *, struct x25_neigh *); +int x25_subscr_ioctl(unsigned int, void __user *); +struct x25_neigh *x25_get_neigh(struct net_device *); +void x25_link_free(void); /* x25_neigh.c */ static __inline__ void x25_neigh_hold(struct x25_neigh *nb) @@ -252,16 +252,16 @@ static __inline__ void x25_neigh_put(struct x25_neigh *nb) } /* x25_out.c */ -extern int x25_output(struct sock *, struct sk_buff *); -extern void x25_kick(struct sock *); -extern void x25_enquiry_response(struct sock *); +int x25_output(struct sock *, struct sk_buff *); +void x25_kick(struct sock *); +void x25_enquiry_response(struct sock *); /* x25_route.c */ -extern struct x25_route *x25_get_route(struct x25_address *addr); -extern struct net_device *x25_dev_get(char *); -extern void x25_route_device_down(struct net_device *dev); -extern int x25_route_ioctl(unsigned int, void __user *); -extern void x25_route_free(void); +struct x25_route *x25_get_route(struct x25_address *addr); +struct net_device *x25_dev_get(char *); +void x25_route_device_down(struct net_device *dev); +int x25_route_ioctl(unsigned int, void __user *); +void x25_route_free(void); static __inline__ void x25_route_hold(struct x25_route *rt) { @@ -275,30 +275,31 @@ static __inline__ void x25_route_put(struct x25_route *rt) } /* x25_subr.c */ -extern void x25_clear_queues(struct sock *); -extern void x25_frames_acked(struct sock *, unsigned short); -extern void x25_requeue_frames(struct sock *); -extern int x25_validate_nr(struct sock *, unsigned short); -extern void x25_write_internal(struct sock *, int); -extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); -extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char); +void x25_clear_queues(struct sock *); +void x25_frames_acked(struct sock *, unsigned short); +void x25_requeue_frames(struct sock *); +int x25_validate_nr(struct sock *, unsigned short); +void x25_write_internal(struct sock *, int); +int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, + int *); +void x25_disconnect(struct sock *, int, unsigned char, unsigned char); /* x25_timer.c */ -extern void x25_init_timers(struct sock *sk); -extern void x25_start_heartbeat(struct sock *); -extern void x25_start_t2timer(struct sock *); -extern void x25_start_t21timer(struct sock *); -extern void x25_start_t22timer(struct sock *); -extern void x25_start_t23timer(struct sock *); -extern void x25_stop_heartbeat(struct sock *); -extern void x25_stop_timer(struct sock *); -extern unsigned long x25_display_timer(struct sock *); -extern void x25_check_rbuf(struct sock *); +void x25_init_timers(struct sock *sk); +void x25_start_heartbeat(struct sock *); +void x25_start_t2timer(struct sock *); +void x25_start_t21timer(struct sock *); +void x25_start_t22timer(struct sock *); +void x25_start_t23timer(struct sock *); +void x25_stop_heartbeat(struct sock *); +void x25_stop_timer(struct sock *); +unsigned long x25_display_timer(struct sock *); +void x25_check_rbuf(struct sock *); /* sysctl_net_x25.c */ #ifdef CONFIG_SYSCTL -extern void x25_register_sysctl(void); -extern void x25_unregister_sysctl(void); +void x25_register_sysctl(void); +void x25_unregister_sysctl(void); #else static inline void x25_register_sysctl(void) {}; static inline void x25_unregister_sysctl(void) {}; @@ -318,6 +319,6 @@ extern rwlock_t x25_forward_list_lock; extern struct list_head x25_neigh_list; extern rwlock_t x25_neigh_list_lock; -extern int x25_proc_init(void); -extern void x25_proc_exit(void); +int x25_proc_init(void); +void x25_proc_exit(void); #endif -- cgit From d511337a1eda35ac9d8e373e1cca17d6182a75b7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:33:53 -0700 Subject: xfrm.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/xfrm.h | 375 +++++++++++++++++++++++++++-------------------------- 1 file changed, 190 insertions(+), 185 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e253bf0cc7ef..765746192724 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -307,15 +307,17 @@ struct xfrm_policy_afinfo { struct dst_entry *(*blackhole_route)(struct net *net, struct dst_entry *orig); }; -extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); -extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); -extern void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c); -extern void km_state_notify(struct xfrm_state *x, const struct km_event *c); +int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); +int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); +void km_policy_notify(struct xfrm_policy *xp, int dir, + const struct km_event *c); +void km_state_notify(struct xfrm_state *x, const struct km_event *c); struct xfrm_tmpl; -extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); -extern void km_state_expired(struct xfrm_state *x, int hard, u32 portid); -extern int __xfrm_state_delete(struct xfrm_state *x); +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, + struct xfrm_policy *pol); +void km_state_expired(struct xfrm_state *x, int hard, u32 portid); +int __xfrm_state_delete(struct xfrm_state *x); struct xfrm_state_afinfo { unsigned int family; @@ -344,12 +346,12 @@ struct xfrm_state_afinfo { void (*local_error)(struct sk_buff *skb, u32 mtu); }; -extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); -extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); -extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); -extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); +int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); +int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); +struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); +void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); -extern void xfrm_state_delete_tunnel(struct xfrm_state *x); +void xfrm_state_delete_tunnel(struct xfrm_state *x); struct xfrm_type { char *description; @@ -372,8 +374,8 @@ struct xfrm_type { u32 (*get_mtu)(struct xfrm_state *, int size); }; -extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family); -extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family); +int xfrm_register_type(const struct xfrm_type *type, unsigned short family); +int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family); struct xfrm_mode { /* @@ -434,8 +436,8 @@ enum { XFRM_MODE_FLAG_TUNNEL = 1, }; -extern int xfrm_register_mode(struct xfrm_mode *mode, int family); -extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family); +int xfrm_register_mode(struct xfrm_mode *mode, int family); +int xfrm_unregister_mode(struct xfrm_mode *mode, int family); static inline int xfrm_af2proto(unsigned int family) { @@ -595,8 +597,8 @@ struct xfrm_mgr { const struct xfrm_kmaddress *k); }; -extern int xfrm_register_km(struct xfrm_mgr *km); -extern int xfrm_unregister_km(struct xfrm_mgr *km); +int xfrm_register_km(struct xfrm_mgr *km); +int xfrm_unregister_km(struct xfrm_mgr *km); /* * This structure is used for the duration where packets are being @@ -713,23 +715,23 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid, audit_log_task_context(audit_buf); } -extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid); -extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid); -extern void xfrm_audit_state_add(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid); -extern void xfrm_audit_state_delete(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid); -extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x, - struct sk_buff *skb); -extern void xfrm_audit_state_replay(struct xfrm_state *x, - struct sk_buff *skb, __be32 net_seq); -extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family); -extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family, - __be32 net_spi, __be32 net_seq); -extern void xfrm_audit_state_icvfail(struct xfrm_state *x, - struct sk_buff *skb, u8 proto); +void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, kuid_t auid, + u32 ses, u32 secid); +void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, kuid_t auid, + u32 ses, u32 secid); +void xfrm_audit_state_add(struct xfrm_state *x, int result, kuid_t auid, + u32 ses, u32 secid); +void xfrm_audit_state_delete(struct xfrm_state *x, int result, kuid_t auid, + u32 ses, u32 secid); +void xfrm_audit_state_replay_overflow(struct xfrm_state *x, + struct sk_buff *skb); +void xfrm_audit_state_replay(struct xfrm_state *x, struct sk_buff *skb, + __be32 net_seq); +void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family); +void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family, __be32 net_spi, + __be32 net_seq); +void xfrm_audit_state_icvfail(struct xfrm_state *x, struct sk_buff *skb, + u8 proto); #else static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, @@ -784,7 +786,7 @@ static inline void xfrm_pol_hold(struct xfrm_policy *policy) atomic_inc(&policy->refcnt); } -extern void xfrm_policy_destroy(struct xfrm_policy *policy); +void xfrm_policy_destroy(struct xfrm_policy *policy); static inline void xfrm_pol_put(struct xfrm_policy *policy) { @@ -799,7 +801,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) xfrm_pol_put(pols[i]); } -extern void __xfrm_state_destroy(struct xfrm_state *); +void __xfrm_state_destroy(struct xfrm_state *); static inline void __xfrm_state_put(struct xfrm_state *x) { @@ -903,9 +905,8 @@ __be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli) return port; } -extern bool xfrm_selector_match(const struct xfrm_selector *sel, - const struct flowi *fl, - unsigned short family); +bool xfrm_selector_match(const struct xfrm_selector *sel, + const struct flowi *fl, unsigned short family); #ifdef CONFIG_SECURITY_NETWORK_XFRM /* If neither has a context --> match @@ -975,7 +976,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) } #endif -extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev); +void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev); struct sec_path { atomic_t refcnt; @@ -1000,7 +1001,7 @@ secpath_get(struct sec_path *sp) return sp; } -extern void __secpath_destroy(struct sec_path *sp); +void __secpath_destroy(struct sec_path *sp); static inline void secpath_put(struct sec_path *sp) @@ -1009,7 +1010,7 @@ secpath_put(struct sec_path *sp) __secpath_destroy(sp); } -extern struct sec_path *secpath_dup(struct sec_path *src); +struct sec_path *secpath_dup(struct sec_path *src); static inline void secpath_reset(struct sk_buff *skb) @@ -1059,7 +1060,8 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un } #ifdef CONFIG_XFRM -extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family); +int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, + unsigned short family); static inline int __xfrm_policy_check2(struct sock *sk, int dir, struct sk_buff *skb, @@ -1103,8 +1105,8 @@ static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir, return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1); } -extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, - unsigned int family, int reverse); +int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, + unsigned int family, int reverse); static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned int family) @@ -1119,7 +1121,7 @@ static inline int xfrm_decode_session_reverse(struct sk_buff *skb, return __xfrm_decode_session(skb, fl, family, 1); } -extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); +int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) { @@ -1140,7 +1142,7 @@ static inline int xfrm6_route_forward(struct sk_buff *skb) return xfrm_route_forward(skb, AF_INET6); } -extern int __xfrm_sk_clone_policy(struct sock *sk); +int __xfrm_sk_clone_policy(struct sock *sk); static inline int xfrm_sk_clone_policy(struct sock *sk) { @@ -1149,7 +1151,7 @@ static inline int xfrm_sk_clone_policy(struct sock *sk) return 0; } -extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir); +int xfrm_policy_delete(struct xfrm_policy *pol, int dir); static inline void xfrm_sk_free_policy(struct sock *sk) { @@ -1163,7 +1165,7 @@ static inline void xfrm_sk_free_policy(struct sock *sk) } } -extern void xfrm_garbage_collect(struct net *net); +void xfrm_garbage_collect(struct net *net); #else @@ -1363,16 +1365,16 @@ struct xfrm6_tunnel { int priority; }; -extern void xfrm_init(void); -extern void xfrm4_init(void); -extern int xfrm_state_init(struct net *net); -extern void xfrm_state_fini(struct net *net); -extern void xfrm4_state_init(void); +void xfrm_init(void); +void xfrm4_init(void); +int xfrm_state_init(struct net *net); +void xfrm_state_fini(struct net *net); +void xfrm4_state_init(void); #ifdef CONFIG_XFRM -extern int xfrm6_init(void); -extern void xfrm6_fini(void); -extern int xfrm6_state_init(void); -extern void xfrm6_state_fini(void); +int xfrm6_init(void); +void xfrm6_fini(void); +int xfrm6_state_init(void); +void xfrm6_state_fini(void); #else static inline int xfrm6_init(void) { @@ -1385,52 +1387,52 @@ static inline void xfrm6_fini(void) #endif #ifdef CONFIG_XFRM_STATISTICS -extern int xfrm_proc_init(struct net *net); -extern void xfrm_proc_fini(struct net *net); +int xfrm_proc_init(struct net *net); +void xfrm_proc_fini(struct net *net); #endif -extern int xfrm_sysctl_init(struct net *net); +int xfrm_sysctl_init(struct net *net); #ifdef CONFIG_SYSCTL -extern void xfrm_sysctl_fini(struct net *net); +void xfrm_sysctl_fini(struct net *net); #else static inline void xfrm_sysctl_fini(struct net *net) { } #endif -extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); -extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, - int (*func)(struct xfrm_state *, int, void*), void *); -extern void xfrm_state_walk_done(struct xfrm_state_walk *walk); -extern struct xfrm_state *xfrm_state_alloc(struct net *net); -extern struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr, - const xfrm_address_t *saddr, - const struct flowi *fl, - struct xfrm_tmpl *tmpl, - struct xfrm_policy *pol, int *err, - unsigned short family); -extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark, - xfrm_address_t *daddr, - xfrm_address_t *saddr, - unsigned short family, - u8 mode, u8 proto, u32 reqid); -extern int xfrm_state_check_expire(struct xfrm_state *x); -extern void xfrm_state_insert(struct xfrm_state *x); -extern int xfrm_state_add(struct xfrm_state *x); -extern int xfrm_state_update(struct xfrm_state *x); -extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark, - const xfrm_address_t *daddr, __be32 spi, - u8 proto, unsigned short family); -extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark, - const xfrm_address_t *daddr, - const xfrm_address_t *saddr, - u8 proto, - unsigned short family); +void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); +int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, + int (*func)(struct xfrm_state *, int, void*), void *); +void xfrm_state_walk_done(struct xfrm_state_walk *walk); +struct xfrm_state *xfrm_state_alloc(struct net *net); +struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr, + const xfrm_address_t *saddr, + const struct flowi *fl, + struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err, + unsigned short family); +struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark, + xfrm_address_t *daddr, + xfrm_address_t *saddr, + unsigned short family, + u8 mode, u8 proto, u32 reqid); +int xfrm_state_check_expire(struct xfrm_state *x); +void xfrm_state_insert(struct xfrm_state *x); +int xfrm_state_add(struct xfrm_state *x); +int xfrm_state_update(struct xfrm_state *x); +struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark, + const xfrm_address_t *daddr, __be32 spi, + u8 proto, unsigned short family); +struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark, + const xfrm_address_t *daddr, + const xfrm_address_t *saddr, + u8 proto, + unsigned short family); #ifdef CONFIG_XFRM_SUB_POLICY -extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, - int n, unsigned short family); -extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, - int n, unsigned short family); +int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, + unsigned short family); +int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, + unsigned short family); #else static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, unsigned short family) @@ -1462,68 +1464,68 @@ struct xfrmk_spdinfo { u32 spdhmcnt; }; -extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, - u32 seq); -extern int xfrm_state_delete(struct xfrm_state *x); -extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); -extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); -extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); -extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); -extern int xfrm_init_replay(struct xfrm_state *x); -extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); -extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay); -extern int xfrm_init_state(struct xfrm_state *x); -extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, - int encap_type); -extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr); -extern int xfrm_output_resume(struct sk_buff *skb, int err); -extern int xfrm_output(struct sk_buff *skb); -extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb); -extern void xfrm_local_error(struct sk_buff *skb, int mtu); -extern int xfrm4_extract_header(struct sk_buff *skb); -extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, - int encap_type); -extern int xfrm4_transport_finish(struct sk_buff *skb, int async); -extern int xfrm4_rcv(struct sk_buff *skb); +struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq); +int xfrm_state_delete(struct xfrm_state *x); +int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); +void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); +void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); +u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); +int xfrm_init_replay(struct xfrm_state *x); +int xfrm_state_mtu(struct xfrm_state *x, int mtu); +int __xfrm_init_state(struct xfrm_state *x, bool init_replay); +int xfrm_init_state(struct xfrm_state *x); +int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb); +int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type); +int xfrm_input_resume(struct sk_buff *skb, int nexthdr); +int xfrm_output_resume(struct sk_buff *skb, int err); +int xfrm_output(struct sk_buff *skb); +int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb); +void xfrm_local_error(struct sk_buff *skb, int mtu); +int xfrm4_extract_header(struct sk_buff *skb); +int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb); +int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, + int encap_type); +int xfrm4_transport_finish(struct sk_buff *skb, int async); +int xfrm4_rcv(struct sk_buff *skb); static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) { return xfrm4_rcv_encap(skb, nexthdr, spi, 0); } -extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm4_output(struct sk_buff *skb); -extern int xfrm4_output_finish(struct sk_buff *skb); -extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); -extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); -extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); -extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); -extern void xfrm4_local_error(struct sk_buff *skb, u32 mtu); -extern int xfrm6_extract_header(struct sk_buff *skb); -extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); -extern int xfrm6_transport_finish(struct sk_buff *skb, int async); -extern int xfrm6_rcv(struct sk_buff *skb); -extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, - xfrm_address_t *saddr, u8 proto); -extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); -extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); -extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); -extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); -extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); -extern int xfrm6_output(struct sk_buff *skb); -extern int xfrm6_output_finish(struct sk_buff *skb); -extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, - u8 **prevhdr); -extern void xfrm6_local_error(struct sk_buff *skb, u32 mtu); +int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); +int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); +int xfrm4_output(struct sk_buff *skb); +int xfrm4_output_finish(struct sk_buff *skb); +int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); +int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); +int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); +int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); +void xfrm4_local_error(struct sk_buff *skb, u32 mtu); +int xfrm6_extract_header(struct sk_buff *skb); +int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); +int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); +int xfrm6_transport_finish(struct sk_buff *skb, int async); +int xfrm6_rcv(struct sk_buff *skb); +int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, + xfrm_address_t *saddr, u8 proto); +int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); +int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, + unsigned short family); +__be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); +__be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); +int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); +int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); +int xfrm6_output(struct sk_buff *skb); +int xfrm6_output_finish(struct sk_buff *skb); +int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, + u8 **prevhdr); +void xfrm6_local_error(struct sk_buff *skb, u32 mtu); #ifdef CONFIG_XFRM -extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); -extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen); +int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); +int xfrm_user_policy(struct sock *sk, int optname, + u8 __user *optval, int optlen); #else static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) { @@ -1540,59 +1542,62 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp); -extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type); -extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, - int (*func)(struct xfrm_policy *, int, int, void*), void *); -extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); +void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type); +int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, + int (*func)(struct xfrm_policy *, int, int, void*), + void *); +void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err); -struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err); +struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, + u32 id, int delete, int *err); int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); -extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); +int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto, const xfrm_address_t *daddr, const xfrm_address_t *saddr, int create, unsigned short family); -extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); +int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); #ifdef CONFIG_XFRM_MIGRATE -extern int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, - const struct xfrm_migrate *m, int num_bundles, - const struct xfrm_kmaddress *k); -extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); -extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, - struct xfrm_migrate *m); -extern int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_bundles, - struct xfrm_kmaddress *k); +int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + const struct xfrm_migrate *m, int num_bundles, + const struct xfrm_kmaddress *k); +struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m); +struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, + struct xfrm_migrate *m); +int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + struct xfrm_migrate *m, int num_bundles, + struct xfrm_kmaddress *k); #endif -extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); -extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid); -extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); - -extern void xfrm_input_init(void); -extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq); - -extern void xfrm_probe_algs(void); -extern int xfrm_count_pfkey_auth_supported(void); -extern int xfrm_count_pfkey_enc_supported(void); -extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx); -extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx); -extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id); -extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id); -extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id); -extern struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe); -extern struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe); -extern struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe); -extern struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len, - int probe); +int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); +void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid); +int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, + xfrm_address_t *addr); + +void xfrm_input_init(void); +int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq); + +void xfrm_probe_algs(void); +int xfrm_count_pfkey_auth_supported(void); +int xfrm_count_pfkey_enc_supported(void); +struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx); +struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx); +struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id); +struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id); +struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id); +struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe); +struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe); +struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe); +struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len, + int probe); static inline bool xfrm6_addr_equal(const xfrm_address_t *a, const xfrm_address_t *b) -- cgit From e74e58f8d2015ac6b4e7a65c0acde8a499d46574 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:37:36 -0700 Subject: bluetooth: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/bluetooth/bluetooth.h | 16 ++++++++-------- include/net/bluetooth/hci_core.h | 23 +++++++++++------------ include/net/bluetooth/rfcomm.h | 4 ++-- 3 files changed, 21 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 10d43d8c7037..13d6c3929759 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -331,16 +331,16 @@ out: int bt_to_errno(__u16 code); -extern int hci_sock_init(void); -extern void hci_sock_cleanup(void); +int hci_sock_init(void); +void hci_sock_cleanup(void); -extern int bt_sysfs_init(void); -extern void bt_sysfs_cleanup(void); +int bt_sysfs_init(void); +void bt_sysfs_cleanup(void); -extern int bt_procfs_init(struct net *net, const char *name, - struct bt_sock_list* sk_list, - int (* seq_show)(struct seq_file *, void *)); -extern void bt_procfs_cleanup(struct net *net, const char *name); +int bt_procfs_init(struct net *net, const char *name, + struct bt_sock_list *sk_list, + int (*seq_show)(struct seq_file *, void *)); +void bt_procfs_cleanup(struct net *net, const char *name); extern struct dentry *bt_debugfs; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3ede820d328f..5769061e6533 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -367,18 +367,17 @@ extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_cb_list_lock; /* ----- HCI interface to upper protocols ----- */ -extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); -extern int l2cap_disconn_ind(struct hci_conn *hcon); -extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); -extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); -extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, - u16 flags); - -extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); -extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); -extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); -extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); +int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); +void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); +int l2cap_disconn_ind(struct hci_conn *hcon); +void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); +int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); +int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); + +int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); +void sco_connect_cfm(struct hci_conn *hcon, __u8 status); +void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); +int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); /* ----- Inquiry cache ----- */ #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */ diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 7afd4199d6b6..b7f43e76a5c5 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -256,8 +256,8 @@ static inline void rfcomm_dlc_put(struct rfcomm_dlc *d) rfcomm_dlc_free(d); } -extern void __rfcomm_dlc_throttle(struct rfcomm_dlc *d); -extern void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d); +void __rfcomm_dlc_throttle(struct rfcomm_dlc *d); +void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d); static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d) { -- cgit From a22b8f4b57af5a4bdda2039d82845285b2a2b7ec Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:37:40 -0700 Subject: caif_hsi.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/caif/caif_hsi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h index 4795e817afe5..097f69cfaa75 100644 --- a/include/net/caif/caif_hsi.h +++ b/include/net/caif/caif_hsi.h @@ -195,6 +195,6 @@ enum ifla_caif_hsi { __IFLA_CAIF_HSI_MAX }; -extern struct cfhsi_ops *cfhsi_get_ops(void); +struct cfhsi_ops *cfhsi_get_ops(void); #endif /* CAIF_HSI_H_ */ -- cgit From 0e418f94d3fcdc79c88841f3338e768e1b0966a1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:37:44 -0700 Subject: irda: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/irda/ircomm_tty.h | 14 +++++++------- include/net/irda/irda.h | 21 ++++++++++----------- include/net/irda/irlap_event.h | 2 +- include/net/irda/irlap_frame.h | 4 ++-- 4 files changed, 20 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index 80ffde3bb164..0224402260a7 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -105,13 +105,13 @@ struct ircomm_tty_cb { void ircomm_tty_start(struct tty_struct *tty); void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self); -extern int ircomm_tty_tiocmget(struct tty_struct *tty); -extern int ircomm_tty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -extern int ircomm_tty_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg); -extern void ircomm_tty_set_termios(struct tty_struct *tty, - struct ktermios *old_termios); +int ircomm_tty_tiocmget(struct tty_struct *tty); +int ircomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear); +int ircomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg); +void ircomm_tty_set_termios(struct tty_struct *tty, + struct ktermios *old_termios); #endif diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index 3bed61d379a8..a059465101ff 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -112,20 +112,19 @@ do { if(!(expr)) { \ struct net_device; struct packet_type; -extern void irda_proc_register(void); -extern void irda_proc_unregister(void); +void irda_proc_register(void); +void irda_proc_unregister(void); -extern int irda_sysctl_register(void); -extern void irda_sysctl_unregister(void); +int irda_sysctl_register(void); +void irda_sysctl_unregister(void); -extern int irsock_init(void); -extern void irsock_cleanup(void); +int irsock_init(void); +void irsock_cleanup(void); -extern int irda_nl_register(void); -extern void irda_nl_unregister(void); +int irda_nl_register(void); +void irda_nl_unregister(void); -extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *ptype, - struct net_device *orig_dev); +int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype, struct net_device *orig_dev); #endif /* NET_IRDA_H */ diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h index 4c90824c50fb..f9d88da97af2 100644 --- a/include/net/irda/irlap_event.h +++ b/include/net/irda/irlap_event.h @@ -126,6 +126,6 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info); void irlap_print_event(IRLAP_EVENT event); -extern int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb); +int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb); #endif diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h index 6b1dc4f8eca5..57173ae398ae 100644 --- a/include/net/irda/irlap_frame.h +++ b/include/net/irda/irlap_frame.h @@ -163,7 +163,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command); void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb, __u8 caddr, int command); -extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self, - struct sk_buff *skb); +int irlap_insert_qos_negotiation_params(struct irlap_cb *self, + struct sk_buff *skb); #endif -- cgit From 4e77be4637641c92468dd5de39cba774bed7d6ba Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:37:48 -0700 Subject: netfilter: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 6 +-- include/net/netfilter/ipv4/nf_defrag_ipv4.h | 2 +- include/net/netfilter/ipv6/nf_defrag_ipv6.h | 17 +++---- include/net/netfilter/nf_conntrack.h | 69 +++++++++++--------------- include/net/netfilter/nf_conntrack_acct.h | 12 ++--- include/net/netfilter/nf_conntrack_core.h | 69 ++++++++++++-------------- include/net/netfilter/nf_conntrack_ecache.h | 22 ++++---- include/net/netfilter/nf_conntrack_extend.h | 2 +- include/net/netfilter/nf_conntrack_helper.h | 40 ++++++++------- include/net/netfilter/nf_conntrack_l3proto.h | 16 +++--- include/net/netfilter/nf_conntrack_l4proto.h | 32 ++++++------ include/net/netfilter/nf_conntrack_seqadj.h | 30 +++++------ include/net/netfilter/nf_conntrack_synproxy.h | 28 +++++------ include/net/netfilter/nf_conntrack_timeout.h | 4 +- include/net/netfilter/nf_conntrack_timestamp.h | 8 +-- include/net/netfilter/nf_nat.h | 10 ++-- include/net/netfilter/nf_nat_core.h | 8 ++- include/net/netfilter/nf_nat_helper.h | 29 ++++------- include/net/netfilter/nf_nat_l3proto.h | 23 ++++----- include/net/netfilter/nf_nat_l4proto.h | 30 +++++------ include/net/netfilter/nf_queue.h | 2 +- include/net/netfilter/xt_rateest.h | 4 +- 22 files changed, 217 insertions(+), 246 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 7573d52a4346..6c3d12e2949f 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -16,9 +16,9 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; -extern int nf_conntrack_ipv4_compat_init(void); -extern void nf_conntrack_ipv4_compat_fini(void); +int nf_conntrack_ipv4_compat_init(void); +void nf_conntrack_ipv4_compat_fini(void); -extern void need_ipv4_conntrack(void); +void need_ipv4_conntrack(void); #endif /*_NF_CONNTRACK_IPV4_H*/ diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h index 6b00ea38546b..f01ef208dff6 100644 --- a/include/net/netfilter/ipv4/nf_defrag_ipv4.h +++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h @@ -1,6 +1,6 @@ #ifndef _NF_DEFRAG_IPV4_H #define _NF_DEFRAG_IPV4_H -extern void nf_defrag_ipv4_enable(void); +void nf_defrag_ipv4_enable(void); #endif /* _NF_DEFRAG_IPV4_H */ diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h index fd79c9a1779d..5613412e7dc2 100644 --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h @@ -1,15 +1,14 @@ #ifndef _NF_DEFRAG_IPV6_H #define _NF_DEFRAG_IPV6_H -extern void nf_defrag_ipv6_enable(void); - -extern int nf_ct_frag6_init(void); -extern void nf_ct_frag6_cleanup(void); -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, - struct net_device *in, - struct net_device *out, - int (*okfn)(struct sk_buff *)); +void nf_defrag_ipv6_enable(void); + +int nf_ct_frag6_init(void); +void nf_ct_frag6_cleanup(void); +struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); +void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, + struct net_device *in, struct net_device *out, + int (*okfn)(struct sk_buff *)); struct inet_frags_ctl; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 0c1288a50e8b..01ea6eed1bb1 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -139,15 +139,13 @@ static inline struct net *nf_ct_net(const struct nf_conn *ct) } /* Alter reply tuple (maybe alter helper). */ -extern void -nf_conntrack_alter_reply(struct nf_conn *ct, - const struct nf_conntrack_tuple *newreply); +void nf_conntrack_alter_reply(struct nf_conn *ct, + const struct nf_conntrack_tuple *newreply); /* Is this tuple taken? (ignoring any belonging to the given conntrack). */ -extern int -nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack); +int nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, + const struct nf_conn *ignored_conntrack); /* Return conntrack_info and tuple hash for given skb. */ static inline struct nf_conn * @@ -165,37 +163,34 @@ static inline void nf_ct_put(struct nf_conn *ct) } /* Protocol module loading */ -extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); -extern void nf_ct_l3proto_module_put(unsigned short l3proto); +int nf_ct_l3proto_try_module_get(unsigned short l3proto); +void nf_ct_l3proto_module_put(unsigned short l3proto); /* * Allocate a hashtable of hlist_head (if nulls == 0), * or hlist_nulls_head (if nulls == 1) */ -extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls); +void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls); -extern void nf_ct_free_hashtable(void *hash, unsigned int size); +void nf_ct_free_hashtable(void *hash, unsigned int size); -extern struct nf_conntrack_tuple_hash * +struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, u16 zone, const struct nf_conntrack_tuple *tuple); -extern int nf_conntrack_hash_check_insert(struct nf_conn *ct); +int nf_conntrack_hash_check_insert(struct nf_conn *ct); bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); -extern void nf_conntrack_flush_report(struct net *net, u32 portid, int report); +void nf_conntrack_flush_report(struct net *net, u32 portid, int report); -extern bool nf_ct_get_tuplepr(const struct sk_buff *skb, - unsigned int nhoff, u_int16_t l3num, - struct nf_conntrack_tuple *tuple); -extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, - const struct nf_conntrack_tuple *orig); +bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, + u_int16_t l3num, struct nf_conntrack_tuple *tuple); +bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, + const struct nf_conntrack_tuple *orig); -extern void __nf_ct_refresh_acct(struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - const struct sk_buff *skb, - unsigned long extra_jiffies, - int do_acct); +void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + const struct sk_buff *skb, + unsigned long extra_jiffies, int do_acct); /* Refresh conntrack for this many jiffies and do accounting */ static inline void nf_ct_refresh_acct(struct nf_conn *ct, @@ -214,10 +209,8 @@ static inline void nf_ct_refresh(struct nf_conn *ct, __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0); } -extern bool __nf_ct_kill_acct(struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - const struct sk_buff *skb, - int do_acct); +bool __nf_ct_kill_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + const struct sk_buff *skb, int do_acct); /* kill conntrack and do accounting */ static inline bool nf_ct_kill_acct(struct nf_conn *ct, @@ -244,19 +237,17 @@ static inline struct nf_conn *nf_ct_untracked_get(void) { return &__raw_get_cpu_var(nf_conntrack_untracked); } -extern void nf_ct_untracked_status_or(unsigned long bits); +void nf_ct_untracked_status_or(unsigned long bits); /* Iterate over all conntracks: if iter returns true, it's deleted. */ -extern void -nf_ct_iterate_cleanup(struct net *net, - int (*iter)(struct nf_conn *i, void *data), - void *data, u32 portid, int report); -extern void nf_conntrack_free(struct nf_conn *ct); -extern struct nf_conn * -nf_conntrack_alloc(struct net *net, u16 zone, - const struct nf_conntrack_tuple *orig, - const struct nf_conntrack_tuple *repl, - gfp_t gfp); +void nf_ct_iterate_cleanup(struct net *net, + int (*iter)(struct nf_conn *i, void *data), + void *data, u32 portid, int report); +void nf_conntrack_free(struct nf_conn *ct); +struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone, + const struct nf_conntrack_tuple *orig, + const struct nf_conntrack_tuple *repl, + gfp_t gfp); static inline int nf_ct_is_template(const struct nf_conn *ct) { @@ -287,7 +278,7 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) struct kernel_param; -extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); +int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_max; extern unsigned int nf_conntrack_hash_rnd; diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h index 2bdb7a15fe06..fef44edf49c1 100644 --- a/include/net/netfilter/nf_conntrack_acct.h +++ b/include/net/netfilter/nf_conntrack_acct.h @@ -42,8 +42,8 @@ struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp) return acct; }; -extern unsigned int -seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir); +unsigned int seq_print_acct(struct seq_file *s, const struct nf_conn *ct, + int dir); /* Check if connection tracking accounting is enabled */ static inline bool nf_ct_acct_enabled(struct net *net) @@ -57,9 +57,9 @@ static inline void nf_ct_set_acct(struct net *net, bool enable) net->ct.sysctl_acct = enable; } -extern int nf_conntrack_acct_pernet_init(struct net *net); -extern void nf_conntrack_acct_pernet_fini(struct net *net); +int nf_conntrack_acct_pernet_init(struct net *net); +void nf_conntrack_acct_pernet_fini(struct net *net); -extern int nf_conntrack_acct_init(void); -extern void nf_conntrack_acct_fini(void); +int nf_conntrack_acct_init(void); +void nf_conntrack_acct_fini(void); #endif /* _NF_CONNTRACK_ACCT_H */ diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index fb2b6234e937..15308b8eb5b5 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -20,49 +20,42 @@ /* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use of connection tracking. */ -extern unsigned int nf_conntrack_in(struct net *net, - u_int8_t pf, - unsigned int hooknum, - struct sk_buff *skb); - -extern int nf_conntrack_init_net(struct net *net); -extern void nf_conntrack_cleanup_net(struct net *net); -extern void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list); - -extern int nf_conntrack_proto_pernet_init(struct net *net); -extern void nf_conntrack_proto_pernet_fini(struct net *net); - -extern int nf_conntrack_proto_init(void); -extern void nf_conntrack_proto_fini(void); - -extern int nf_conntrack_init_start(void); -extern void nf_conntrack_cleanup_start(void); - -extern void nf_conntrack_init_end(void); -extern void nf_conntrack_cleanup_end(void); - -extern bool -nf_ct_get_tuple(const struct sk_buff *skb, - unsigned int nhoff, - unsigned int dataoff, - u_int16_t l3num, - u_int8_t protonum, - struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_l4proto *l4proto); - -extern bool -nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, - const struct nf_conntrack_tuple *orig, - const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_l4proto *l4proto); +unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, + struct sk_buff *skb); + +int nf_conntrack_init_net(struct net *net); +void nf_conntrack_cleanup_net(struct net *net); +void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list); + +int nf_conntrack_proto_pernet_init(struct net *net); +void nf_conntrack_proto_pernet_fini(struct net *net); + +int nf_conntrack_proto_init(void); +void nf_conntrack_proto_fini(void); + +int nf_conntrack_init_start(void); +void nf_conntrack_cleanup_start(void); + +void nf_conntrack_init_end(void); +void nf_conntrack_cleanup_end(void); + +bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, + unsigned int dataoff, u_int16_t l3num, u_int8_t protonum, + struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_l3proto *l3proto, + const struct nf_conntrack_l4proto *l4proto); + +bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, + const struct nf_conntrack_tuple *orig, + const struct nf_conntrack_l3proto *l3proto, + const struct nf_conntrack_l4proto *l4proto); /* Find a connection corresponding to a tuple. */ -extern struct nf_conntrack_tuple_hash * +struct nf_conntrack_tuple_hash * nf_conntrack_find_get(struct net *net, u16 zone, const struct nf_conntrack_tuple *tuple); -extern int __nf_conntrack_confirm(struct sk_buff *skb); +int __nf_conntrack_confirm(struct sk_buff *skb); /* Confirm a connection: returns NF_DROP if packet must be dropped. */ static inline int nf_conntrack_confirm(struct sk_buff *skb) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 092dc651689f..0e3d08e4b1d3 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -68,10 +68,12 @@ struct nf_ct_event_notifier { int (*fcn)(unsigned int events, struct nf_ct_event *item); }; -extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb); -extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb); +int nf_conntrack_register_notifier(struct net *net, + struct nf_ct_event_notifier *nb); +void nf_conntrack_unregister_notifier(struct net *net, + struct nf_ct_event_notifier *nb); -extern void nf_ct_deliver_cached_events(struct nf_conn *ct); +void nf_ct_deliver_cached_events(struct nf_conn *ct); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) @@ -166,8 +168,10 @@ struct nf_exp_event_notifier { int (*fcn)(unsigned int events, struct nf_exp_event *item); }; -extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb); -extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb); +int nf_ct_expect_register_notifier(struct net *net, + struct nf_exp_event_notifier *nb); +void nf_ct_expect_unregister_notifier(struct net *net, + struct nf_exp_event_notifier *nb); static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, @@ -207,11 +211,11 @@ nf_ct_expect_event(enum ip_conntrack_expect_events event, nf_ct_expect_event_report(event, exp, 0, 0); } -extern int nf_conntrack_ecache_pernet_init(struct net *net); -extern void nf_conntrack_ecache_pernet_fini(struct net *net); +int nf_conntrack_ecache_pernet_init(struct net *net); +void nf_conntrack_ecache_pernet_fini(struct net *net); -extern int nf_conntrack_ecache_init(void); -extern void nf_conntrack_ecache_fini(void); +int nf_conntrack_ecache_init(void); +void nf_conntrack_ecache_fini(void); #else /* CONFIG_NF_CONNTRACK_EVENTS */ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 88a1d4060d52..86372ae0ee84 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -73,7 +73,7 @@ static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id) ((id##_TYPE *)__nf_ct_ext_find((ext), (id))) /* Destroy all relationships */ -extern void __nf_ct_ext_destroy(struct nf_conn *ct); +void __nf_ct_ext_destroy(struct nf_conn *ct); static inline void nf_ct_ext_destroy(struct nf_conn *ct) { if (ct->ext) diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 26c4ae5bfbb8..6cf614bc0029 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -52,21 +52,24 @@ struct nf_conntrack_helper { unsigned int queue_num; /* For user-space helpers. */ }; -extern struct nf_conntrack_helper * -__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum); +struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name, + u16 l3num, u8 protonum); -extern struct nf_conntrack_helper * -nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum); +struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name, + u16 l3num, + u8 protonum); -extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); -extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); +int nf_conntrack_helper_register(struct nf_conntrack_helper *); +void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); -extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conntrack_helper *helper, gfp_t gfp); +struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, + struct nf_conntrack_helper *helper, + gfp_t gfp); -extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, - gfp_t flags); +int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, + gfp_t flags); -extern void nf_ct_helper_destroy(struct nf_conn *ct); +void nf_ct_helper_destroy(struct nf_conn *ct); static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) { @@ -82,17 +85,16 @@ static inline void *nfct_help_data(const struct nf_conn *ct) return (void *)help->data; } -extern int nf_conntrack_helper_pernet_init(struct net *net); -extern void nf_conntrack_helper_pernet_fini(struct net *net); +int nf_conntrack_helper_pernet_init(struct net *net); +void nf_conntrack_helper_pernet_fini(struct net *net); -extern int nf_conntrack_helper_init(void); -extern void nf_conntrack_helper_fini(void); +int nf_conntrack_helper_init(void); +void nf_conntrack_helper_fini(void); -extern int nf_conntrack_broadcast_help(struct sk_buff *skb, - unsigned int protoff, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int timeout); +int nf_conntrack_broadcast_help(struct sk_buff *skb, unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int timeout); struct nf_ct_helper_expectfn { struct list_head head; diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 3bb89eac3fa1..3efab704b7eb 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -77,17 +77,17 @@ struct nf_conntrack_l3proto { extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX]; /* Protocol pernet registration. */ -extern int nf_ct_l3proto_pernet_register(struct net *net, - struct nf_conntrack_l3proto *proto); -extern void nf_ct_l3proto_pernet_unregister(struct net *net, - struct nf_conntrack_l3proto *proto); +int nf_ct_l3proto_pernet_register(struct net *net, + struct nf_conntrack_l3proto *proto); +void nf_ct_l3proto_pernet_unregister(struct net *net, + struct nf_conntrack_l3proto *proto); /* Protocol global registration. */ -extern int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto); -extern void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto); +int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto); +void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto); -extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); -extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); +struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); +void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); /* Existing built-in protocols */ extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic; diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index b411d7b17dec..4c8d573830b7 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -114,22 +114,22 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; #define MAX_NF_CT_PROTO 256 -extern struct nf_conntrack_l4proto * -__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto); +struct nf_conntrack_l4proto *__nf_ct_l4proto_find(u_int16_t l3proto, + u_int8_t l4proto); -extern struct nf_conntrack_l4proto * -nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto); -extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); +struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u_int16_t l3proto, + u_int8_t l4proto); +void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); /* Protocol pernet registration. */ -extern int nf_ct_l4proto_pernet_register(struct net *net, - struct nf_conntrack_l4proto *proto); -extern void nf_ct_l4proto_pernet_unregister(struct net *net, - struct nf_conntrack_l4proto *proto); +int nf_ct_l4proto_pernet_register(struct net *net, + struct nf_conntrack_l4proto *proto); +void nf_ct_l4proto_pernet_unregister(struct net *net, + struct nf_conntrack_l4proto *proto); /* Protocol global registration. */ -extern int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto); -extern void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto); +int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto); +void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto); static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn) { @@ -140,11 +140,11 @@ static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn) } /* Generic netlink helpers */ -extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple); -extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[], - struct nf_conntrack_tuple *t); -extern int nf_ct_port_nlattr_tuple_size(void); +int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple); +int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[], + struct nf_conntrack_tuple *t); +int nf_ct_port_nlattr_tuple_size(void); extern const struct nla_policy nf_ct_port_nla_policy[]; #ifdef CONFIG_SYSCTL diff --git a/include/net/netfilter/nf_conntrack_seqadj.h b/include/net/netfilter/nf_conntrack_seqadj.h index f6177a5fe0ca..4b3362991a25 100644 --- a/include/net/netfilter/nf_conntrack_seqadj.h +++ b/include/net/netfilter/nf_conntrack_seqadj.h @@ -30,22 +30,18 @@ static inline struct nf_conn_seqadj *nfct_seqadj_ext_add(struct nf_conn *ct) return nf_ct_ext_add(ct, NF_CT_EXT_SEQADJ, GFP_ATOMIC); } -extern int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo, - s32 off); -extern int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo, - __be32 seq, s32 off); -extern void nf_ct_tcp_seqadj_set(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - s32 off); - -extern int nf_ct_seq_adjust(struct sk_buff *skb, - struct nf_conn *ct, enum ip_conntrack_info ctinfo, - unsigned int protoff); -extern s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, - u32 seq); - -extern int nf_conntrack_seqadj_init(void); -extern void nf_conntrack_seqadj_fini(void); +int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + s32 off); +int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + __be32 seq, s32 off); +void nf_ct_tcp_seqadj_set(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, s32 off); + +int nf_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, unsigned int protoff); +s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, u32 seq); + +int nf_conntrack_seqadj_init(void); +void nf_conntrack_seqadj_fini(void); #endif /* _NF_CONNTRACK_SEQADJ_H */ diff --git a/include/net/netfilter/nf_conntrack_synproxy.h b/include/net/netfilter/nf_conntrack_synproxy.h index 806f54a290d6..968186642bb1 100644 --- a/include/net/netfilter/nf_conntrack_synproxy.h +++ b/include/net/netfilter/nf_conntrack_synproxy.h @@ -56,22 +56,20 @@ struct synproxy_options { struct tcphdr; struct xt_synproxy_info; -extern void synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, - const struct tcphdr *th, - struct synproxy_options *opts); -extern unsigned int synproxy_options_size(const struct synproxy_options *opts); -extern void synproxy_build_options(struct tcphdr *th, - const struct synproxy_options *opts); +void synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, + const struct tcphdr *th, + struct synproxy_options *opts); +unsigned int synproxy_options_size(const struct synproxy_options *opts); +void synproxy_build_options(struct tcphdr *th, + const struct synproxy_options *opts); -extern void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info, - struct synproxy_options *opts); -extern void synproxy_check_timestamp_cookie(struct synproxy_options *opts); +void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info, + struct synproxy_options *opts); +void synproxy_check_timestamp_cookie(struct synproxy_options *opts); -extern unsigned int synproxy_tstamp_adjust(struct sk_buff *skb, - unsigned int protoff, - struct tcphdr *th, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - const struct nf_conn_synproxy *synproxy); +unsigned int synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff, + struct tcphdr *th, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + const struct nf_conn_synproxy *synproxy); #endif /* _NF_CONNTRACK_SYNPROXY_H */ diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h index d23aceb16d94..62308713dd7f 100644 --- a/include/net/netfilter/nf_conntrack_timeout.h +++ b/include/net/netfilter/nf_conntrack_timeout.h @@ -76,8 +76,8 @@ nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, } #ifdef CONFIG_NF_CONNTRACK_TIMEOUT -extern int nf_conntrack_timeout_init(void); -extern void nf_conntrack_timeout_fini(void); +int nf_conntrack_timeout_init(void); +void nf_conntrack_timeout_fini(void); #else static inline int nf_conntrack_timeout_init(void) { diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h index b00461413efd..300ae2209f25 100644 --- a/include/net/netfilter/nf_conntrack_timestamp.h +++ b/include/net/netfilter/nf_conntrack_timestamp.h @@ -48,11 +48,11 @@ static inline void nf_ct_set_tstamp(struct net *net, bool enable) } #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP -extern int nf_conntrack_tstamp_pernet_init(struct net *net); -extern void nf_conntrack_tstamp_pernet_fini(struct net *net); +int nf_conntrack_tstamp_pernet_init(struct net *net); +void nf_conntrack_tstamp_pernet_fini(struct net *net); -extern int nf_conntrack_tstamp_init(void); -extern void nf_conntrack_tstamp_fini(void); +int nf_conntrack_tstamp_init(void); +void nf_conntrack_tstamp_fini(void); #else static inline int nf_conntrack_tstamp_pernet_init(struct net *net) { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 59a192420053..c29b4e545f87 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -41,13 +41,13 @@ struct nf_conn_nat { }; /* Set up the info structure to map into this range. */ -extern unsigned int nf_nat_setup_info(struct nf_conn *ct, - const struct nf_nat_range *range, - enum nf_nat_manip_type maniptype); +unsigned int nf_nat_setup_info(struct nf_conn *ct, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype); /* Is this tuple already taken? (not by us)*/ -extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack); +int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, + const struct nf_conn *ignored_conntrack); static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) { diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index 972e1e47ec79..fbfd1ba4254e 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -7,12 +7,10 @@ /* This header used to share core functionality between the standalone NAT module, and the compatibility layer's use of NAT for masquerading. */ -extern unsigned int nf_nat_packet(struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - struct sk_buff *skb); +unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + unsigned int hooknum, struct sk_buff *skb); -extern int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family); +int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family); static inline int nf_nat_initialized(struct nf_conn *ct, enum nf_nat_manip_type manip) diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index 404324d1d0c4..01bcc6bfbcc9 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h @@ -7,14 +7,11 @@ struct sk_buff; /* These return true or false. */ -extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int protoff, - unsigned int match_offset, - unsigned int match_len, - const char *rep_buffer, - unsigned int rep_len, bool adjust); +int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int protoff, unsigned int match_offset, + unsigned int match_len, const char *rep_buffer, + unsigned int rep_len, bool adjust); static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct, @@ -30,18 +27,14 @@ static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb, rep_buffer, rep_len, true); } -extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int protoff, - unsigned int match_offset, - unsigned int match_len, - const char *rep_buffer, - unsigned int rep_len); +int nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int protoff, unsigned int match_offset, + unsigned int match_len, const char *rep_buffer, + unsigned int rep_len); /* Setup NAT on this expected conntrack so it follows master, but goes * to port ct->master->saved_proto. */ -extern void nf_nat_follow_master(struct nf_conn *ct, - struct nf_conntrack_expect *this); +void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this); #endif diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index bd3b97e02c82..5a2919b2e09a 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -35,18 +35,15 @@ struct nf_nat_l3proto { struct nf_nat_range *range); }; -extern int nf_nat_l3proto_register(const struct nf_nat_l3proto *); -extern void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *); -extern const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto); - -extern int nf_nat_icmp_reply_translation(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum); -extern int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - unsigned int hdrlen); +int nf_nat_l3proto_register(const struct nf_nat_l3proto *); +void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *); +const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto); + +int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum); +int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, unsigned int hdrlen); #endif /* _NF_NAT_L3PROTO_H */ diff --git a/include/net/netfilter/nf_nat_l4proto.h b/include/net/netfilter/nf_nat_l4proto.h index 24feb68d1bcc..12f4cc841b6e 100644 --- a/include/net/netfilter/nf_nat_l4proto.h +++ b/include/net/netfilter/nf_nat_l4proto.h @@ -42,10 +42,11 @@ struct nf_nat_l4proto { }; /* Protocol registration. */ -extern int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto); -extern void nf_nat_l4proto_unregister(u8 l3proto, const struct nf_nat_l4proto *l4proto); +int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto); +void nf_nat_l4proto_unregister(u8 l3proto, + const struct nf_nat_l4proto *l4proto); -extern const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto); +const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto); /* Built-in protocols. */ extern const struct nf_nat_l4proto nf_nat_l4proto_tcp; @@ -54,19 +55,18 @@ extern const struct nf_nat_l4proto nf_nat_l4proto_icmp; extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6; extern const struct nf_nat_l4proto nf_nat_l4proto_unknown; -extern bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple, - enum nf_nat_manip_type maniptype, - const union nf_conntrack_man_proto *min, - const union nf_conntrack_man_proto *max); +bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max); -extern void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, - struct nf_conntrack_tuple *tuple, - const struct nf_nat_range *range, - enum nf_nat_manip_type maniptype, - const struct nf_conn *ct, - u16 *rover); +void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, + struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct, u16 *rover); -extern int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], - struct nf_nat_range *range); +int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], + struct nf_nat_range *range); #endif /*_NF_NAT_L4PROTO_H*/ diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index aaba4bbcdda0..c1d5b3e34a21 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -28,7 +28,7 @@ struct nf_queue_handler { void nf_register_queue_handler(const struct nf_queue_handler *qh); void nf_unregister_queue_handler(void); -extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); +void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); bool nf_queue_entry_get_refs(struct nf_queue_entry *entry); void nf_queue_entry_release_refs(struct nf_queue_entry *entry); diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h index 495c71f66e7e..79f45e19f31e 100644 --- a/include/net/netfilter/xt_rateest.h +++ b/include/net/netfilter/xt_rateest.h @@ -16,7 +16,7 @@ struct xt_rateest { struct rcu_head rcu; }; -extern struct xt_rateest *xt_rateest_lookup(const char *name); -extern void xt_rateest_put(struct xt_rateest *est); +struct xt_rateest *xt_rateest_lookup(const char *name); +void xt_rateest_put(struct xt_rateest *est); #endif /* _XT_RATEEST_H */ -- cgit From 7b584460689d4326d2d1664271ab0c56b56d4328 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Sep 2013 11:37:59 -0700 Subject: sctp: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 3794c5ad20fe..c5fe80697f8d 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -90,12 +90,11 @@ /* * sctp/protocol.c */ -extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *, - sctp_scope_t, gfp_t gfp, - int flags); -extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); -extern int sctp_register_pf(struct sctp_pf *, sa_family_t); -extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int); +int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *, + sctp_scope_t, gfp_t gfp, int flags); +struct sctp_pf *sctp_get_pf_specific(sa_family_t family); +int sctp_register_pf(struct sctp_pf *, sa_family_t); +void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int); /* * sctp/socket.c @@ -110,7 +109,7 @@ void sctp_sock_rfree(struct sk_buff *skb); void sctp_copy_sock(struct sock *newsk, struct sock *sk, struct sctp_association *asoc); extern struct percpu_counter sctp_sockets_allocated; -extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); +int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); /* * sctp/primitive.c -- cgit From eeb446581ba23a5a36b4f5c7bfa2b1f8f7c9fb66 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 28 Nov 2012 18:17:25 -0500 Subject: ARM: GIC: function to retrieve the physical address of the SGIR In order to have early assembly code signal other CPUs in the system, we need to get the physical address for the SGIR register used to send IPIs. Because the register will be used with a precomputed CPU interface ID number, there is no need for any locking in the assembly code where this register is written to. Signed-off-by: Nicolas Pitre --- drivers/irqchip/irq-gic.c | 29 +++++++++++++++++++++++++++++ include/linux/irqchip/arm-gic.h | 1 + 2 files changed, 30 insertions(+) (limited to 'include') diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 6365b59181ee..09fdf3d574cd 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -769,6 +769,33 @@ void gic_migrate_target(unsigned int new_cpu_id) } } } + +/* + * gic_get_sgir_physaddr - get the physical address for the SGI register + * + * REturn the physical address of the SGI register to be used + * by some early assembly code when the kernel is not yet available. + */ +static unsigned long gic_dist_physaddr; + +unsigned long gic_get_sgir_physaddr(void) +{ + if (!gic_dist_physaddr) + return 0; + return gic_dist_physaddr + GIC_DIST_SOFTINT; +} + +void __init gic_init_physaddr(struct device_node *node) +{ + struct resource res; + if (of_address_to_resource(node, 0, &res) == 0) { + gic_dist_physaddr = res.start; + pr_info("GIC physical location is %#lx\n", gic_dist_physaddr); + } +} + +#else +#define gic_init_physaddr(node) do { } while (0) #endif static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, @@ -952,6 +979,8 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) percpu_offset = 0; gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node); + if (!gic_cnt) + gic_init_physaddr(node); if (parent) { irq = irq_of_parse_and_map(node, 0); diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 46544e381bf9..dc30835099e3 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -78,6 +78,7 @@ static inline void gic_init(unsigned int nr, int start, int gic_get_cpu_id(unsigned int cpu); void gic_migrate_target(unsigned int new_cpu_id); +unsigned long gic_get_sgir_physaddr(void); #endif /* __ASSEMBLY */ -- cgit From 14d2ca615a85e2dbc744c12c296affd35f119fa7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 28 Nov 2012 18:48:19 -0500 Subject: ARM: GIC: interface to send a SGI directly The regular gic_raise_softirq() takes as input a CPU mask which is not adequate when we need to send an IPI to a CPU which is not represented in the kernel to GIC mapping. That is the case with the b.L switcher when GIC migration to the inbound CPU has not yet occurred. Signed-off-by: Nicolas Pitre --- drivers/irqchip/irq-gic.c | 14 ++++++++++++++ include/linux/irqchip/arm-gic.h | 1 + 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 09fdf3d574cd..9031171c141b 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -673,6 +673,20 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) #endif #ifdef CONFIG_BL_SWITCHER +/* + * gic_send_sgi - send a SGI directly to given CPU interface number + * + * cpu_id: the ID for the destination CPU interface + * irq: the IPI number to send a SGI for + */ +void gic_send_sgi(unsigned int cpu_id, unsigned int irq) +{ + BUG_ON(cpu_id >= NR_GIC_CPU_IF); + cpu_id = 1 << cpu_id; + /* this always happens on GIC0 */ + writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); +} + /* * gic_get_cpu_id - get the CPU interface ID for the specified CPU * diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index dc30835099e3..cac496b1e279 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -76,6 +76,7 @@ static inline void gic_init(unsigned int nr, int start, gic_init_bases(nr, start, dist, cpu, 0, NULL); } +void gic_send_sgi(unsigned int cpu_id, unsigned int irq); int gic_get_cpu_id(unsigned int cpu); void gic_migrate_target(unsigned int new_cpu_id); unsigned long gic_get_sgir_physaddr(void); -- cgit From 1bfbddb6f3a0dbb8c3996d1c4d4911d695737c15 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Mon, 14 May 2012 17:40:07 +0100 Subject: ARM: bL_switcher: Basic trace events support This patch adds simple trace events to the b.L switcher code to allow tracing of CPU migration events. To make use of the trace events, you will need: CONFIG_FTRACE=y CONFIG_ENABLE_DEFAULT_TRACERS=y The following events are added: * power:cpu_migrate_begin * power:cpu_migrate_finish each with the following data: u64 timestamp; u32 cpu_hwid; power:cpu_migrate_begin occurs immediately before the switcher-specific migration operations start. power:cpu_migrate_finish occurs immediately when migration is completed. The cpu_hwid field contains the ID fields of the MPIDR. * For power:cpu_migrate_begin, cpu_hwid is the ID of the outbound physical CPU (equivalent to (from_phys_cpu,from_phys_cluster)). * For power:cpu_migrate_finish, cpu_hwid is the ID of the inbound physical CPU (equivalent to (to_phys_cpu,to_phys_cluster)). By design, the cpu_hwid field is masked in the same way as the device tree cpu node reg property, allowing direct correlation to the DT description of the hardware. The timestamp is added in order to minimise timing noise. An accurate system-wide clock should be used for generating this (hopefully getnstimeofday is appropriate, but it could be changed). It could be any monotonic shared clock, since the aim is to allow accurate deltas to be computed. We don't necessarily care about accurate synchronisation with wall clock time. In practice, each switch takes place on a single logical CPU, and the trace infrastructure should guarantee that events are well-ordered with respect to a single logical CPU. Signed-off-by: Dave Martin Signed-off-by: Nicolas Pitre --- arch/arm/common/bL_switcher.c | 17 ++++++++ include/trace/events/power_cpu_migrate.h | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 include/trace/events/power_cpu_migrate.h (limited to 'include') diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index dc53eb8dcc81..7002de360d23 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,10 +34,14 @@ #include #include +#include #include #include #include +#define CREATE_TRACE_POINTS +#include + /* * Use our own MPIDR accessors as the generic ones in asm/cputype.h have @@ -51,6 +56,16 @@ static int read_mpidr(void) return id & MPIDR_HWID_BITMASK; } +/* + * Get a global nanosecond time stamp for tracing. + */ +static s64 get_ns(void) +{ + struct timespec ts; + getnstimeofday(&ts); + return timespec_to_ns(&ts); +} + /* * bL switcher core code. */ @@ -208,6 +223,7 @@ static int bL_switch_to(unsigned int new_cluster_id) */ local_irq_disable(); local_fiq_disable(); + trace_cpu_migrate_begin(get_ns(), ob_mpidr); /* redirect GIC's SGIs to our counterpart */ gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]); @@ -250,6 +266,7 @@ static int bL_switch_to(unsigned int new_cluster_id) tdev->evtdev->next_event, 1); } + trace_cpu_migrate_finish(get_ns(), ib_mpidr); local_fiq_enable(); local_irq_enable(); diff --git a/include/trace/events/power_cpu_migrate.h b/include/trace/events/power_cpu_migrate.h new file mode 100644 index 000000000000..3694af0f5bc5 --- /dev/null +++ b/include/trace/events/power_cpu_migrate.h @@ -0,0 +1,66 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM power + +#if !defined(_TRACE_POWER_CPU_MIGRATE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_POWER_CPU_MIGRATE_H + +#include + +#define __cpu_migrate_proto \ + TP_PROTO(u64 timestamp, \ + u32 cpu_hwid) +#define __cpu_migrate_args \ + TP_ARGS(timestamp, \ + cpu_hwid) + +DECLARE_EVENT_CLASS(cpu_migrate, + + __cpu_migrate_proto, + __cpu_migrate_args, + + TP_STRUCT__entry( + __field(u64, timestamp ) + __field(u32, cpu_hwid ) + ), + + TP_fast_assign( + __entry->timestamp = timestamp; + __entry->cpu_hwid = cpu_hwid; + ), + + TP_printk("timestamp=%llu cpu_hwid=0x%08lX", + (unsigned long long)__entry->timestamp, + (unsigned long)__entry->cpu_hwid + ) +); + +#define __define_cpu_migrate_event(name) \ + DEFINE_EVENT(cpu_migrate, cpu_migrate_##name, \ + __cpu_migrate_proto, \ + __cpu_migrate_args \ + ) + +__define_cpu_migrate_event(begin); +__define_cpu_migrate_event(finish); + +#undef __define_cpu_migrate +#undef __cpu_migrate_proto +#undef __cpu_migrate_args + +/* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */ +#ifndef _PWR_CPU_MIGRATE_EVENT_AVOID_DOUBLE_DEFINING +#define _PWR_CPU_MIGRATE_EVENT_AVOID_DOUBLE_DEFINING + +/* + * Set from_phys_cpu and to_phys_cpu to CPU_MIGRATE_ALL_CPUS to indicate + * a whole-cluster migration: + */ +#define CPU_MIGRATE_ALL_CPUS 0x80000000U +#endif + +#endif /* _TRACE_POWER_CPU_MIGRATE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE power_cpu_migrate +#include -- cgit From b09bbe5b1267b6af22a9584d614f5eec5d74f405 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Wed, 6 Feb 2013 15:45:23 +0000 Subject: ARM: bL_switcher/trace: Add trace trigger for trace bootstrapping When tracing switching, an external tracer needs a way to bootstrap its knowledge of the logical<->physical CPU mapping. This patch adds a sysfs attribute trace_trigger. A write to this attribute will generate a power:cpu_migrate_current event for each online CPU, indicating the current physical CPU for each logical CPU. Activating or deactivating the switcher also generates these events, so that the tracer knows about the resulting remapping of affected CPUs. Signed-off-by: Dave Martin --- arch/arm/common/bL_switcher.c | 36 ++++++++++++++++++++++++++++++++ include/trace/events/power_cpu_migrate.h | 1 + 2 files changed, 37 insertions(+) (limited to 'include') diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index 7002de360d23..f0dc025077d5 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -531,6 +532,25 @@ static int bL_switcher_halve_cpus(void) return 0; } +static void bL_switcher_trace_trigger_cpu(void *__always_unused info) +{ + trace_cpu_migrate_current(get_ns(), read_mpidr()); +} + +static int bL_switcher_trace_trigger(void) +{ + int ret; + + preempt_disable(); + + bL_switcher_trace_trigger_cpu(NULL); + ret = smp_call_function(bL_switcher_trace_trigger_cpu, NULL, true); + + preempt_enable(); + + return ret; +} + static int bL_switcher_enable(void) { int cpu, ret; @@ -553,6 +573,8 @@ static int bL_switcher_enable(void) if (ret) goto error; + bL_switcher_trace_trigger(); + for_each_online_cpu(cpu) { struct bL_thread *t = &bL_threads[cpu]; spin_lock_init(&t->lock); @@ -637,6 +659,8 @@ static void bL_switcher_disable(void) } bL_switcher_restore_cpus(); + bL_switcher_trace_trigger(); + bL_activation_notify(BL_NOTIFY_POST_DISABLE); out: @@ -670,11 +694,23 @@ static ssize_t bL_switcher_active_store(struct kobject *kobj, return (ret >= 0) ? count : ret; } +static ssize_t bL_switcher_trace_trigger_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int ret = bL_switcher_trace_trigger(); + + return ret ? ret : count; +} + static struct kobj_attribute bL_switcher_active_attr = __ATTR(active, 0644, bL_switcher_active_show, bL_switcher_active_store); +static struct kobj_attribute bL_switcher_trace_trigger_attr = + __ATTR(trace_trigger, 0200, NULL, bL_switcher_trace_trigger_store); + static struct attribute *bL_switcher_attrs[] = { &bL_switcher_active_attr.attr, + &bL_switcher_trace_trigger_attr.attr, NULL, }; diff --git a/include/trace/events/power_cpu_migrate.h b/include/trace/events/power_cpu_migrate.h index 3694af0f5bc5..f76dd4de625e 100644 --- a/include/trace/events/power_cpu_migrate.h +++ b/include/trace/events/power_cpu_migrate.h @@ -42,6 +42,7 @@ DECLARE_EVENT_CLASS(cpu_migrate, __define_cpu_migrate_event(begin); __define_cpu_migrate_event(finish); +__define_cpu_migrate_event(current); #undef __define_cpu_migrate #undef __cpu_migrate_proto -- cgit From ad4d35f865408a494f0a4c02b1c7ebd3f80f5dbf Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 5 Sep 2013 15:55:26 +0800 Subject: [SCSI] csiostor: Use pcie_capability_clear_and_set_word() to simplify code pci_is_pcie() and pcie_capability_clear_and_set_word() make it trivial to set the PCIe Completion Timeout, so just fold the csio_set_pcie_completion_timeout() function into its caller. [bhelgaas: changelog, fold csio_set_pcie_completion_timeout() into caller] Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Cc: Jiang Liu Cc: "James E.J. Bottomley" Cc: Naresh Kumar Inna Cc: "David S. Miller" Cc: Jesper Juhl --- drivers/scsi/csiostor/csio_hw.c | 22 ++++------------------ include/uapi/linux/pci_regs.h | 3 ++- 2 files changed, 6 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index 0eb35b9b3784..0eaec4748957 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -852,22 +852,6 @@ csio_hw_get_flash_params(struct csio_hw *hw) return 0; } -static void -csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range) -{ - uint16_t val; - int pcie_cap; - - if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) { - pci_read_config_word(hw->pdev, - pcie_cap + PCI_EXP_DEVCTL2, &val); - val &= 0xfff0; - val |= range ; - pci_write_config_word(hw->pdev, - pcie_cap + PCI_EXP_DEVCTL2, val); - } -} - /*****************************************************************************/ /* HW State machine assists */ /*****************************************************************************/ @@ -2069,8 +2053,10 @@ csio_hw_configure(struct csio_hw *hw) goto out; } - /* Set pci completion timeout value to 4 seconds. */ - csio_set_pcie_completion_timeout(hw, 0xd); + /* Set PCIe completion timeout to 4 seconds */ + if (pci_is_pcie(hw->pdev)) + pcie_capability_clear_and_set_word(hw->pdev, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_COMP_TIMEOUT, 0xd); hw->chip_ops->chip_set_mem_win(hw, MEMWIN_CSIOSTOR); diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index baa7852468ef..1a38377a0032 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -558,7 +558,8 @@ #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */ #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */ #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ -#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ +#define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */ +#define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */ #define PCI_EXP_DEVCTL2_IDO_REQ_EN 0x0100 /* Allow IDO for requests */ #define PCI_EXP_DEVCTL2_IDO_CMP_EN 0x0200 /* Allow IDO for completions */ #define PCI_EXP_DEVCTL2_LTR_EN 0x0400 /* Enable LTR mechanism */ -- cgit From ca9f62ac783bf88c54143f8065adc0fc8df859c1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:34 +0800 Subject: ACPI / processor: Introduce apic_id in struct processor to save parsed APIC id For cpu hot add, we evaluate _MAT or parse MADT twice to get APIC id, here is the code logic: acpi_processor_add() acpi_processor_get_info() acpi_get_cpuid() will evaluate _MAT or parse MADT; acpi_processor_hotadd_init() acpi_map_lsapic() will evaluate _MAT again; This can be done more effectively, this patch introduces apic_id in struct processor to save parsed APIC id, and then we can use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 4 +++- drivers/acpi/processor_core.c | 26 +++++++++++++++++++++----- include/acpi/processor.h | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f29e06efa479..f89f914cb97e 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -270,7 +270,9 @@ static int acpi_processor_get_info(struct acpi_device *device) device_declaration = 1; pr->acpi_id = value; } - cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); + pr->apic_id = acpi_get_apicid(pr->handle, device_declaration, + pr->acpi_id); + cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index cf34d903f4fb..b3171f30b319 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -162,16 +162,23 @@ exit: return apic_id; } -int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id) { -#ifdef CONFIG_SMP - int i; -#endif - int apic_id = -1; + int apic_id; apic_id = map_mat_entry(handle, type, acpi_id); if (apic_id == -1) apic_id = map_madt_entry(type, acpi_id); + + return apic_id; +} + +int acpi_map_cpuid(int apic_id, u32 acpi_id) +{ +#ifdef CONFIG_SMP + int i; +#endif + if (apic_id == -1) { /* * On UP processor, there is no _MAT or MADT table. @@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) #endif return -1; } + +int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +{ + int apic_id; + + apic_id = acpi_get_apicid(handle, type, acpi_id); + + return acpi_map_cpuid(apic_id, acpi_id); +} EXPORT_SYMBOL_GPL(acpi_get_cpuid); static bool __init processor_physically_present(acpi_handle handle) diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 66096d06925e..7816e45f5d5a 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -199,6 +199,7 @@ struct acpi_processor_flags { struct acpi_processor { acpi_handle handle; u32 acpi_id; + u32 apic_id; u32 id; u32 pblk; int performance_platform_limit; @@ -314,6 +315,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) /* in processor_core.c */ void acpi_processor_set_pdc(acpi_handle handle); +int acpi_get_apicid(acpi_handle, int type, u32 acpi_id); +int acpi_map_cpuid(int apic_id, u32 acpi_id); int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id); /* in processor_throttling.c */ -- cgit From d536bf3dc97417471e2c5098837a1cddd7fbb3c7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:35 +0800 Subject: ACPI / processor: use apic_id and remove duplicated _MAT evaluation Since APIC id is saved in processor struct, just use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- arch/ia64/kernel/acpi.c | 38 ++++---------------------------------- arch/x86/kernel/acpi/boot.c | 38 +++----------------------------------- drivers/acpi/acpi_processor.c | 2 +- include/linux/acpi.h | 2 +- 4 files changed, 9 insertions(+), 71 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 5eb71d22c3d5..59d52e3aef12 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -882,40 +882,10 @@ __init void prefill_possible_map(void) set_cpu_possible(i, true); } -static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - struct acpi_madt_local_sapic *lsapic; cpumask_t tmp_map; - int cpu, physid; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) - return -EINVAL; - - if (!buffer.length || !buffer.pointer) - return -EINVAL; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER) - { - kfree(buffer.pointer); - return -EINVAL; - } - - lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer; - - if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) || - (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) { - kfree(buffer.pointer); - return -EINVAL; - } - - physid = ((lsapic->id << 8) | (lsapic->eid)); - - kfree(buffer.pointer); - buffer.length = ACPI_ALLOCATE_BUFFER; - buffer.pointer = NULL; + int cpu; cpumask_complement(&tmp_map, cpu_present_mask); cpu = cpumask_first(&tmp_map); @@ -934,9 +904,9 @@ static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) } /* wrapper to silence section mismatch warning */ -int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - return _acpi_map_lsapic(handle, pcpu); + return _acpi_map_lsapic(handle, physid, pcpu); } EXPORT_SYMBOL(acpi_map_lsapic); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 40c76604199f..f6dbb2f5e39f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -614,44 +614,12 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) #endif } -static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - struct acpi_madt_local_apic *lapic; cpumask_var_t tmp_map, new_map; - u8 physid; int cpu; int retval = -ENOMEM; - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) - return -EINVAL; - - if (!buffer.length || !buffer.pointer) - return -EINVAL; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER || - obj->buffer.length < sizeof(*lapic)) { - kfree(buffer.pointer); - return -EINVAL; - } - - lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; - - if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || - !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { - kfree(buffer.pointer); - return -EINVAL; - } - - physid = lapic->id; - - kfree(buffer.pointer); - buffer.length = ACPI_ALLOCATE_BUFFER; - buffer.pointer = NULL; - lapic = NULL; - if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) goto out; @@ -689,9 +657,9 @@ out: } /* wrapper to silence section mismatch warning */ -int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - return _acpi_map_lsapic(handle, pcpu); + return _acpi_map_lsapic(handle, physid, pcpu); } EXPORT_SYMBOL(acpi_map_lsapic); diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f89f914cb97e..66c9b702894b 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -181,7 +181,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr) cpu_maps_update_begin(); cpu_hotplug_begin(); - ret = acpi_map_lsapic(pr->handle, &pr->id); + ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id); if (ret) goto out; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a5db4aeefa36..3bc74141453f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -116,7 +116,7 @@ void acpi_numa_arch_fixup(void); #ifdef CONFIG_ACPI_HOTPLUG_CPU /* Arch dependent functions for cpu hotplug support */ -int acpi_map_lsapic(acpi_handle handle, int *pcpu); +int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu); int acpi_unmap_lsapic(int cpu); #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -- cgit From dedf1e4dfd5477b4315ad451b4be0ff8d9f7e85f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:05:53 -0600 Subject: ACPI: Write _OSC bit field definitions in hex Update _OSC definition comments to correspond to the 1-based spec wording (DWORD 1, etc.) Write _OSC field #defines as hex to make clear that they are bits in a 32-bit DWORD, not arbitrary values. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/acpi.h | 54 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a5db4aeefa36..164ba10ddcb3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -304,39 +304,39 @@ struct acpi_osc_context { #define OSC_SUPPORT_TYPE 1 #define OSC_CONTROL_TYPE 2 -/* _OSC DW0 Definition */ -#define OSC_QUERY_ENABLE 1 -#define OSC_REQUEST_ERROR 2 -#define OSC_INVALID_UUID_ERROR 4 -#define OSC_INVALID_REVISION_ERROR 8 -#define OSC_CAPABILITIES_MASK_ERROR 16 +/* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */ +#define OSC_QUERY_ENABLE 0x00000001 /* input */ +#define OSC_REQUEST_ERROR 0x00000002 /* return */ +#define OSC_INVALID_UUID_ERROR 0x00000004 /* return */ +#define OSC_INVALID_REVISION_ERROR 0x00000008 /* return */ +#define OSC_CAPABILITIES_MASK_ERROR 0x00000010 /* return */ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); -/* platform-wide _OSC bits */ -#define OSC_SB_PAD_SUPPORT 1 -#define OSC_SB_PPC_OST_SUPPORT 2 -#define OSC_SB_PR3_SUPPORT 4 -#define OSC_SB_HOTPLUG_OST_SUPPORT 8 -#define OSC_SB_APEI_SUPPORT 16 +/* Platform-Wide Capabilities _OSC: Capabilities DWORD 2: Support Field */ +#define OSC_SB_PAD_SUPPORT 0x00000001 +#define OSC_SB_PPC_OST_SUPPORT 0x00000002 +#define OSC_SB_PR3_SUPPORT 0x00000004 +#define OSC_SB_HOTPLUG_OST_SUPPORT 0x00000008 +#define OSC_SB_APEI_SUPPORT 0x00000010 +#define OSC_SB_CPC_SUPPORT 0x00000020 extern bool osc_sb_apei_support_acked; -/* PCI defined _OSC bits */ -/* _OSC DW1 Definition (OS Support Fields) */ -#define OSC_EXT_PCI_CONFIG_SUPPORT 1 -#define OSC_ACTIVE_STATE_PWR_SUPPORT 2 -#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4 -#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8 -#define OSC_MSI_SUPPORT 16 -#define OSC_PCI_SUPPORT_MASKS 0x1f - -/* _OSC DW1 Definition (OS Control Fields) */ -#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1 -#define OSC_SHPC_NATIVE_HP_CONTROL 2 -#define OSC_PCI_EXPRESS_PME_CONTROL 4 -#define OSC_PCI_EXPRESS_AER_CONTROL 8 -#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16 +/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */ +#define OSC_EXT_PCI_CONFIG_SUPPORT 0x00000001 +#define OSC_ACTIVE_STATE_PWR_SUPPORT 0x00000002 +#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 0x00000004 +#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 0x00000008 +#define OSC_MSI_SUPPORT 0x00000010 +#define OSC_PCI_SUPPORT_MASKS 0x0000001f + +/* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */ +#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 0x00000001 +#define OSC_SHPC_NATIVE_HP_CONTROL 0x00000002 +#define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004 +#define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008 +#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 0x00000010 #define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ OSC_SHPC_NATIVE_HP_CONTROL | \ -- cgit From b938a229c85a567de7dba2d806d9f63a7c90483e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:05:54 -0600 Subject: ACPI: Rename OSC_QUERY_TYPE to OSC_QUERY_DWORD OSC_QUERY_TYPE isn't a "type"; it's an index into the _OSC Capabilities Buffer of DWORDs. Rename OSC_QUERY_TYPE, OSC_SUPPORT_TYPE, and OSC_CONTROL_TYPE to OSC_QUERY_DWORD, etc., to make this clear. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/apei/apei-base.c | 6 +++--- drivers/acpi/bus.c | 18 +++++++++--------- drivers/acpi/pci_root.c | 14 +++++++------- include/linux/acpi.h | 7 ++++--- 4 files changed, 23 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 46f80e2c92f7..6d2c49b86b7f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -758,9 +758,9 @@ int apei_osc_setup(void) .cap.pointer = capbuf, }; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = 1; - capbuf[OSC_CONTROL_TYPE] = 0; + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = 1; + capbuf[OSC_CONTROL_DWORD] = 0; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)) || ACPI_FAILURE(acpi_run_osc(handle, &context))) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b587ec8257b2..fbcfaa682c15 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -255,7 +255,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) acpi_print_osc_error(handle, context, "_OSC invalid revision"); if (errors & OSC_CAPABILITIES_MASK_ERROR) { - if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] + if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD] & OSC_QUERY_ENABLE) goto out_success; status = AE_SUPPORT; @@ -295,30 +295,30 @@ static void acpi_bus_osc_support(void) }; acpi_handle handle; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; #endif #ifdef ACPI_HOTPLUG_OST - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; #endif if (!ghes_disable) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; - if (context.ret.length > OSC_SUPPORT_TYPE) + if (context.ret.length > OSC_SUPPORT_DWORD) osc_sb_apei_support_acked = - capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT; + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f425653..323afd7ccfbf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -158,14 +158,14 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, support &= OSC_PCI_SUPPORT_MASKS; support |= root->osc_support_set; - capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = support; + capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_DWORD] = support; if (control) { *control &= OSC_PCI_CONTROL_MASKS; - capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; + capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set; } else { /* Run _OSC query only with existing controls. */ - capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; + capbuf[OSC_CONTROL_DWORD] = root->osc_control_set; } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); @@ -357,9 +357,9 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) goto out; } - capbuf[OSC_QUERY_TYPE] = 0; - capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; - capbuf[OSC_CONTROL_TYPE] = ctrl; + capbuf[OSC_QUERY_DWORD] = 0; + capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set; + capbuf[OSC_CONTROL_DWORD] = ctrl; status = acpi_pci_run_osc(handle, capbuf, mask); if (ACPI_SUCCESS(status)) root->osc_control_set = *mask; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 164ba10ddcb3..d220d1465d9b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -300,9 +300,10 @@ struct acpi_osc_context { struct acpi_buffer ret; /* free by caller if success */ }; -#define OSC_QUERY_TYPE 0 -#define OSC_SUPPORT_TYPE 1 -#define OSC_CONTROL_TYPE 2 +/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */ +#define OSC_QUERY_DWORD 0 /* DWORD 1 */ +#define OSC_SUPPORT_DWORD 1 /* DWORD 2 */ +#define OSC_CONTROL_DWORD 2 /* DWORD 3 */ /* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */ #define OSC_QUERY_ENABLE 0x00000001 /* input */ -- cgit From c8678473609b0271ffa0963af82e575312e882cb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:05:55 -0600 Subject: ACPI: Tidy acpi_run_osc() declarations Move the acpi_run_osc() prototype next to the related structure and update comments. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/acpi.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d220d1465d9b..a2f501c0a4f4 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -294,12 +294,14 @@ void __init acpi_nvs_nosave_s3(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context { - char *uuid_str; /* uuid string */ + char *uuid_str; /* UUID string */ int rev; - struct acpi_buffer cap; /* arg2/arg3 */ - struct acpi_buffer ret; /* free by caller if success */ + struct acpi_buffer cap; /* list of DWORD capabilities */ + struct acpi_buffer ret; /* free by caller if success */ }; +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); + /* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */ #define OSC_QUERY_DWORD 0 /* DWORD 1 */ #define OSC_SUPPORT_DWORD 1 /* DWORD 2 */ @@ -312,8 +314,6 @@ struct acpi_osc_context { #define OSC_INVALID_REVISION_ERROR 0x00000008 /* return */ #define OSC_CAPABILITIES_MASK_ERROR 0x00000010 /* return */ -acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); - /* Platform-Wide Capabilities _OSC: Capabilities DWORD 2: Support Field */ #define OSC_SB_PAD_SUPPORT 0x00000001 #define OSC_SB_PPC_OST_SUPPORT 0x00000002 -- cgit From b4481934167430d82ea9c857cf95276460e4b607 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:22:11 -0600 Subject: ACPI: Remove unused OSC_PCI_NATIVE_HOTPLUG OSC_PCI_NATIVE_HOTPLUG is completely unused, so remove it. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/acpi.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a2f501c0a4f4..ca072e3927a2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -345,9 +345,6 @@ extern bool osc_sb_apei_support_acked; OSC_PCI_EXPRESS_AER_CONTROL | \ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) -#define OSC_PCI_NATIVE_HOTPLUG (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ - OSC_SHPC_NATIVE_HP_CONTROL) - extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req); -- cgit From 335b15097d571007b125eb9fe4ef1f84e61bd31d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:24:24 -0600 Subject: ACPI: Write OSC_PCI_CONTROL_MASKS like OSC_PCI_SUPPORT_MASKS We write OSC_PCI_SUPPORT_MASKS as a simple 0x1f, so do the same for OSC_PCI_CONTROL_MASKS. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/acpi.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ca072e3927a2..bb4e7701b26b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -338,12 +338,7 @@ extern bool osc_sb_apei_support_acked; #define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004 #define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008 #define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 0x00000010 - -#define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ - OSC_SHPC_NATIVE_HP_CONTROL | \ - OSC_PCI_EXPRESS_PME_CONTROL | \ - OSC_PCI_EXPRESS_AER_CONTROL | \ - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) +#define OSC_PCI_CONTROL_MASKS 0x0000001f extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req); -- cgit From 7dab9ef4f0823072a3c9afdb3b373c9f2f38848b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Sep 2013 15:07:39 -0600 Subject: PCI/ACPI: Name _OSC #defines more consistently Make PCI Host Bridge _OSC #defines more consistent. No functional change. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 19 +++++++++---------- drivers/pci/hotplug/acpi_pcihp.c | 2 +- drivers/pci/hotplug/shpchp.h | 2 +- include/linux/acpi.h | 12 ++++++------ 4 files changed, 17 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 323afd7ccfbf..28dd55509789 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -49,10 +49,10 @@ static int acpi_pci_root_add(struct acpi_device *device, const struct acpi_device_id *not_used); static void acpi_pci_root_remove(struct acpi_device *device); -#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ - | OSC_ACTIVE_STATE_PWR_SUPPORT \ - | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ - | OSC_MSI_SUPPORT) +#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ + | OSC_PCI_ASPM_SUPPORT \ + | OSC_PCI_CLOCK_PM_SUPPORT \ + | OSC_PCI_MSI_SUPPORT) static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, @@ -439,13 +439,12 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_pci_osc_support(root, flags); if (pci_ext_cfg_avail()) - flags |= OSC_EXT_PCI_CONFIG_SUPPORT; + flags |= OSC_PCI_EXT_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) { - flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + flags |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; } if (pci_msi_enabled()) - flags |= OSC_MSI_SUPPORT; + flags |= OSC_PCI_MSI_SUPPORT; if (flags != base_flags) { status = acpi_pci_osc_support(root, flags); if (ACPI_FAILURE(status)) { @@ -458,7 +457,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + flags = OSC_PCI_EXPRESS_CAPABILITY_CONTROL | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_PME_CONTROL; @@ -474,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device, "Requesting ACPI _OSC control (0x%02x)\n", flags); status = acpi_pci_osc_control_set(handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + OSC_PCI_EXPRESS_CAPABILITY_CONTROL); if (ACPI_SUCCESS(status)) { dev_info(&device->dev, "ACPI _OSC control (0x%02x) granted\n", flags); diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 2a47e82821da..f8140164ec0b 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -338,7 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) acpi_handle chandle, handle; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; - flags &= OSC_SHPC_NATIVE_HP_CONTROL; + flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL; if (!flags) { err("Invalid flags %u specified!\n", flags); return -EINVAL; diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e260f207a90e..d876e4b3c6a9 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -191,7 +191,7 @@ static inline const char *slot_name(struct slot *slot) #include static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) { - u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; + u32 flags = OSC_PCI_SHPC_NATIVE_HP_CONTROL; return acpi_get_hp_hw_control_from_firmware(dev, flags); } #else diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bb4e7701b26b..e2e52cf53224 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -325,19 +325,19 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); extern bool osc_sb_apei_support_acked; /* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */ -#define OSC_EXT_PCI_CONFIG_SUPPORT 0x00000001 -#define OSC_ACTIVE_STATE_PWR_SUPPORT 0x00000002 -#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 0x00000004 +#define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001 +#define OSC_PCI_ASPM_SUPPORT 0x00000002 +#define OSC_PCI_CLOCK_PM_SUPPORT 0x00000004 #define OSC_PCI_SEGMENT_GROUPS_SUPPORT 0x00000008 -#define OSC_MSI_SUPPORT 0x00000010 +#define OSC_PCI_MSI_SUPPORT 0x00000010 #define OSC_PCI_SUPPORT_MASKS 0x0000001f /* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */ #define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 0x00000001 -#define OSC_SHPC_NATIVE_HP_CONTROL 0x00000002 +#define OSC_PCI_SHPC_NATIVE_HP_CONTROL 0x00000002 #define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004 #define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008 -#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 0x00000010 +#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL 0x00000010 #define OSC_PCI_CONTROL_MASKS 0x0000001f extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, -- cgit From 30095207072665503a5f6c769d16be26de38fa6a Mon Sep 17 00:00:00 2001 From: Naresh Bhat Date: Mon, 23 Sep 2013 09:51:46 +0800 Subject: ACPICA: Linux-specific header: enable "aarch64" 64-bit build. Add support for the __aarch64__ define for 64-bit builds. Signed-off-by: Naresh Bhat Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- include/acpi/platform/aclinux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 68534ef86ec8..fda0f3e35c03 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -87,7 +87,7 @@ #define ACPI_FLUSH_CPU_CACHE() #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread)) -#if defined(__ia64__) || defined(__x86_64__) +#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__) #define ACPI_MACHINE_WIDTH 64 #define COMPILER_DEPENDENT_INT64 long #define COMPILER_DEPENDENT_UINT64 unsigned long -- cgit From a2fd4b4b4e2884405c54a91514b0fad3853aea01 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:05 +0800 Subject: ACPICA: Add support for host-installed SCI handlers. This change adds support to allow hosts to install System Control Interrupt handlers. Certain ACPI functionality requires the host to handle raw SCIs. For example, the "SCI Doorbell" that is defined for memory power state support requires the host device driver to handle SCIs to examine if the doorbell has been activated. Multiple SCI handlers can be installed to allow for future expansion. Debugger support is included. Lv Zheng, Bob Moore. ACPICA BZ 1032. Bug summary: It is reported when the PCC (Platform Communication Channel, via MPST table, defined in ACPI specification 5.0) subchannel responds to the host, it issues an SCI and the host must probe the subchannel for channel status. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1032 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 3 +- drivers/acpi/acpica/acevents.h | 6 +- drivers/acpi/acpica/acglobal.h | 1 + drivers/acpi/acpica/aclocal.h | 8 +++ drivers/acpi/acpica/evgpeutil.c | 2 +- drivers/acpi/acpica/evmisc.c | 14 ++-- drivers/acpi/acpica/evsci.c | 80 +++++++++++++++++++++-- drivers/acpi/acpica/evxface.c | 139 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utglobal.c | 3 +- include/acpi/acpixf.h | 13 +++- include/acpi/actypes.h | 3 + 11 files changed, 249 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 9feba08c29fe..30c2d6911386 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -113,11 +113,12 @@ void acpi_db_display_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) + ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) /* * dbconvert - miscellaneous conversion routines */ - acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); +acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index ab0e97710381..3ae5fd02ae64 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, */ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context); -u32 acpi_ev_install_sci_handler(void); +u32 acpi_ev_sci_dispatch(void); -acpi_status acpi_ev_remove_sci_handler(void); +u32 acpi_ev_install_sci_handler(void); -u32 acpi_ev_initialize_SCI(u32 program_SCI); +acpi_status acpi_ev_remove_all_sci_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void)) #endif /* __ACEVENTS_H__ */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index c9ad2e1f1ee1..0fba431f4fcb 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler; ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; +ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list; /* Owner ID support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0ed00669cd21..be9e30ee6048 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -398,6 +398,14 @@ struct acpi_simple_repair_info { * ****************************************************************************/ +/* Dispatch info for each host-installed SCI handler */ + +struct acpi_sci_handler_info { + struct acpi_sci_handler_info *next; + acpi_sci_handler address; /* Address of handler */ + void *context; /* Context to be passed to handler */ +}; + /* Dispatch info for each GPE -- either a method or handler, cannot be both */ struct acpi_gpe_handler_info { diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index b24dbb80fab8..d52339090b60 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * * FUNCTION: acpi_ev_get_gpe_xrupt_block * - * PARAMETERS: interrupt_number - Interrupt for a GPE block + * PARAMETERS: interrupt_number - Interrupt for a GPE block * * RETURN: A GPE interrupt block * diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 1b111ef74903..a5687540e9a6 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -264,13 +264,6 @@ void acpi_ev_terminate(void) status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - /* Remove SCI handler */ - - status = acpi_ev_remove_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); - } - status = acpi_ev_remove_global_lock_handler(); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, @@ -280,6 +273,13 @@ void acpi_ev_terminate(void) acpi_gbl_events_initialized = FALSE; } + /* Remove SCI handlers */ + + status = acpi_ev_remove_all_sci_handlers(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); + } + /* Deallocate all handler objects installed within GPE info structs */ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b905acf7aacd..b2f0fb2f57b4 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -52,6 +52,52 @@ ACPI_MODULE_NAME("evsci") /* Local prototypes */ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); +/******************************************************************************* + * + * FUNCTION: acpi_ev_sci_dispatch + * + * PARAMETERS: None + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. + * + ******************************************************************************/ + +u32 acpi_ev_sci_dispatch(void) +{ + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_NAME(ev_sci_dispatch); + + /* Are there any host-installed SCI handlers? */ + + if (!acpi_gbl_sci_handler_list) { + return (int_status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Invoke all host-installed SCI handlers */ + + sci_handler = acpi_gbl_sci_handler_list; + while (sci_handler) { + + /* Invoke the installed handler (at interrupt level) */ + + int_status |= sci_handler->address((u32)acpi_gbl_FADT. + sci_interrupt, + sci_handler->context); + + sci_handler = sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return (int_status); +} + /******************************************************************************* * * FUNCTION: acpi_ev_sci_xrupt_handler @@ -89,6 +135,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + /* Invoke all host-installed SCI handlers */ + + interrupt_handled |= acpi_ev_sci_dispatch(); + return_UINT32(interrupt_handled); } @@ -112,14 +162,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* - * We are guaranteed by the ACPI CA initialization/shutdown code that + * We are guaranteed by the ACPICA initialization/shutdown code that * if this interrupt handler is installed, ACPI is enabled. */ /* GPEs: Check for and dispatch any GPEs that have occurred */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); } @@ -150,15 +199,15 @@ u32 acpi_ev_install_sci_handler(void) /****************************************************************************** * - * FUNCTION: acpi_ev_remove_sci_handler + * FUNCTION: acpi_ev_remove_all_sci_handlers * * PARAMETERS: none * - * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not * installed to begin with * * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be - * taken. + * taken. Remove all host-installed SCI handlers. * * Note: It doesn't seem important to disable all events or set the event * enable registers to their original values. The OS should disable @@ -167,11 +216,13 @@ u32 acpi_ev_install_sci_handler(void) * ******************************************************************************/ -acpi_status acpi_ev_remove_sci_handler(void) +acpi_status acpi_ev_remove_all_sci_handlers(void) { + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; acpi_status status; - ACPI_FUNCTION_TRACE(ev_remove_sci_handler); + ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers); /* Just let the OS remove the handler and disable the level */ @@ -179,6 +230,21 @@ acpi_status acpi_ev_remove_sci_handler(void) acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, acpi_ev_sci_xrupt_handler); + if (!acpi_gbl_sci_handler_list) { + return (status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Free all host-installed SCI handlers */ + + while (acpi_gbl_sci_handler_list) { + sci_handler = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = sci_handler->next; + ACPI_FREE(sci_handler); + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index ca5fba99c33b..6f56146a6f88 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -383,6 +383,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ #if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: acpi_install_sci_handler + * + * PARAMETERS: address - Address of the handler + * context - Value passed to the handler on each SCI + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a System Control Interrupt. + * + ******************************************************************************/ +acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) +{ + struct acpi_sci_handler_info *new_sci_handler; + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Allocate and init a handler object */ + + new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info)); + if (!new_sci_handler) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_sci_handler->address = address; + new_sci_handler->context = context; + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Lock list during installation */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + sci_handler = acpi_gbl_sci_handler_list; + + /* Ensure handler does not already exist */ + + while (sci_handler) { + if (address == sci_handler->address) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + sci_handler = sci_handler->next; + } + + /* Install the new handler into the global list (at head) */ + + new_sci_handler->next = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = new_sci_handler; + + unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + exit: + if (ACPI_FAILURE(status)) { + ACPI_FREE(new_sci_handler); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_remove_sci_handler + * + * PARAMETERS: address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a System Control Interrupt. + * + ******************************************************************************/ + +acpi_status acpi_remove_sci_handler(acpi_sci_handler address) +{ + struct acpi_sci_handler_info *prev_sci_handler; + struct acpi_sci_handler_info *next_sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Remove the SCI handler with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + prev_sci_handler = NULL; + next_sci_handler = acpi_gbl_sci_handler_list; + while (next_sci_handler) { + if (next_sci_handler->address == address) { + + /* Unlink and free the SCI handler info block */ + + if (prev_sci_handler) { + prev_sci_handler->next = next_sci_handler->next; + } else { + acpi_gbl_sci_handler_list = + next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + ACPI_FREE(next_sci_handler); + goto unlock_and_exit; + } + + prev_sci_handler = next_sci_handler; + next_sci_handler = next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + status = AE_NOT_EXIST; + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_install_global_event_handler @@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) * Can be used to update event counters, etc. * ******************************************************************************/ + acpi_status acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d6f26bf8a062..046d5b059c07 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void) #if (!ACPI_REDUCED_HARDWARE) - /* GPE support */ + /* GPE/SCI support */ acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; @@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void) acpi_current_gpe_count = 0; acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 85bfdbe17805..55a4d3ae1477 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -280,9 +280,16 @@ acpi_status acpi_install_initialization_handler(acpi_init_handler handler, u32 function); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status - acpi_install_global_event_handler - (acpi_gbl_event_handler handler, void *context)) - + acpi_install_sci_handler(acpi_sci_handler + address, + void *context)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_remove_sci_handler(acpi_sci_handler + address)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_install_global_event_handler + (acpi_gbl_event_handler handler, + void *context)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_fixed_event_handler(u32 acpi_event, diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index b748aefce929..850f75027fb6 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -945,6 +945,9 @@ typedef void /* * Various handlers and callback procedures */ +typedef +u32 (*acpi_sci_handler) (u32 interrupt_number, void *context); + typedef void (*acpi_gbl_event_handler) (u32 event_type, acpi_handle device, -- cgit From cacba8657351f709ab3cb53a2b207f513f14054c Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:34 +0800 Subject: ACPICA: Tables: Cleanup RSDP signature codes. This patch introduces new macors to handle RSDP signature and cleans up the affected codes. Lv Zheng. Some updates are only used for ACPICA utilities which are not shipped in the kernel yet. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbprint.c | 2 +- drivers/acpi/acpica/tbxfroot.c | 3 +-- include/acpi/actypes.h | 5 +++++ 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 499759a23b41..9a47715af1f3 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -138,7 +138,7 @@ acpi_tb_print_table_header(acpi_physical_address address, ACPI_INFO((AE_INFO, "%4.4s %p %05X", header->signature, ACPI_CAST_PTR(void, address), header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { /* RSDP has no common fields */ diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 948c95e80d44..1c95fabbe6a4 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP, - sizeof(ACPI_SIG_RSDP) - 1) != 0) { + if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { /* Nope, BAD Signature */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 850f75027fb6..54006720af8e 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -474,6 +474,11 @@ typedef u64 acpi_integer; #define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE)) #endif +/* Support for the special RSDP signature (8 characters) */ + +#define ACPI_VALIDATE_RSDP_SIG(a) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8)) +#define ACPI_MAKE_RSDP_SIG(dest) (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) + /******************************************************************************* * * Miscellaneous constants -- cgit From 31e93a166c7cfa6d5ff0bae0c19f0541f06f2260 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:40 +0800 Subject: ACPICA: Cleanup exception codes. This patch adds AE_ACCESS for EACCES or EPERM. Some error prompts are also cleaned up in this patch. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- include/acpi/acexcep.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index cf051e05a8fe..4e280bd226dd 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -125,8 +125,9 @@ struct acpi_exception_info { #define AE_NO_HANDLER EXCEP_ENV (0x001A) #define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B) #define AE_NOT_CONFIGURED EXCEP_ENV (0x001C) +#define AE_ACCESS EXCEP_ENV (0x001D) -#define AE_CODE_ENV_MAX 0x001C +#define AE_CODE_ENV_MAX 0x001D /* * Programmer exceptions @@ -227,7 +228,7 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"), EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"), EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"), - EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"), + EXCEP_TXT("AE_NOT_FOUND", "A requested entity is not found"), EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"), EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"), EXCEP_TXT("AE_TYPE", "The object type is incorrect"), @@ -259,7 +260,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { EXCEP_TXT("AE_OWNER_ID_LIMIT", "There are no more Owner IDs available for ACPI tables or control methods"), EXCEP_TXT("AE_NOT_CONFIGURED", - "The interface is not part of the current subsystem configuration") + "The interface is not part of the current subsystem configuration"), + EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation") }; static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = { -- cgit From c53ae3a60c2494a160140d09637f543562626365 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:45 +0800 Subject: ACPICA: SCI Handlers: Update handler interface, eliminate unnecessary argument. The SCI interrupt number is not needed for the SCI handlers, and was just unnecessary overhead. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evsci.c | 4 +--- include/acpi/actypes.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b2f0fb2f57b4..94d9ebddf575 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -87,9 +87,7 @@ u32 acpi_ev_sci_dispatch(void) /* Invoke the installed handler (at interrupt level) */ - int_status |= sci_handler->address((u32)acpi_gbl_FADT. - sci_interrupt, - sci_handler->context); + int_status |= sci_handler->address(sci_handler->context); sci_handler = sci_handler->next; } diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 54006720af8e..f6abf23ad0a7 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -951,7 +951,7 @@ typedef void * Various handlers and callback procedures */ typedef -u32 (*acpi_sci_handler) (u32 interrupt_number, void *context); +u32 (*acpi_sci_handler) (void *context); typedef void (*acpi_gbl_event_handler) (u32 event_type, -- cgit From 94d7ba991fe0dd245babc8f227ad5fabe234303f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:53 +0800 Subject: ACPICA: Update version to 20130823. Version 20130823. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 55a4d3ae1477..c7b1475422b3 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20130725 +#define ACPI_CA_VERSION 0x20130823 #include #include -- cgit From 2ff2a7d03bbe472ed44a8380dbdbea490d81c59d Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 23 Sep 2013 16:57:03 +0800 Subject: cgroup: kill css_id The only user of css_id was memcg, and it has been convered to use cgroup->id, so kill css_id. Signed-off-by: Li Zefan Reviewed-by: Michal Hocko Acked-by: Tejun Heo Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 37 -------- kernel/cgroup.c | 248 +------------------------------------------------ 2 files changed, 1 insertion(+), 284 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 3561d305b1e0..39c1d9469677 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -612,11 +612,6 @@ struct cgroup_subsys { int subsys_id; int disabled; int early_init; - /* - * True if this subsys uses ID. ID is not available before cgroup_init() - * (not available in early_init time.) - */ - bool use_id; /* * If %false, this subsystem is properly hierarchical - @@ -642,9 +637,6 @@ struct cgroup_subsys { */ struct cgroupfs_root *root; struct list_head sibling; - /* used when use_id == true */ - struct idr idr; - spinlock_t id_lock; /* list of cftype_sets */ struct list_head cftsets; @@ -875,35 +867,6 @@ int css_scan_tasks(struct cgroup_subsys_state *css, int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from); -/* - * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works - * if cgroup_subsys.use_id == true. It can be used for looking up and scanning. - * CSS ID is assigned at cgroup allocation (create) automatically - * and removed when subsys calls free_css_id() function. This is because - * the lifetime of cgroup_subsys_state is subsys's matter. - * - * Looking up and scanning function should be called under rcu_read_lock(). - * Taking cgroup_mutex is not necessary for following calls. - * But the css returned by this routine can be "not populated yet" or "being - * destroyed". The caller should check css and cgroup's status. - */ - -/* - * Typically Called at ->destroy(), or somewhere the subsys frees - * cgroup_subsys_state. - */ -void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css); - -/* Find a cgroup_subsys_state which has given ID */ - -struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id); - -/* Returns true if root is ancestor of cg */ -bool css_is_ancestor(struct cgroup_subsys_state *cg, - const struct cgroup_subsys_state *root); - -/* Get id and depth of css */ -unsigned short css_id(struct cgroup_subsys_state *css); struct cgroup_subsys_state *css_from_dir(struct dentry *dentry, struct cgroup_subsys *ss); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2418b6e71a85..a5629f1df13a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -124,38 +124,6 @@ struct cfent { struct simple_xattrs xattrs; }; -/* - * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when - * cgroup_subsys->use_id != 0. - */ -#define CSS_ID_MAX (65535) -struct css_id { - /* - * The css to which this ID points. This pointer is set to valid value - * after cgroup is populated. If cgroup is removed, this will be NULL. - * This pointer is expected to be RCU-safe because destroy() - * is called after synchronize_rcu(). But for safe use, css_tryget() - * should be used for avoiding race. - */ - struct cgroup_subsys_state __rcu *css; - /* - * ID of this css. - */ - unsigned short id; - /* - * Depth in hierarchy which this ID belongs to. - */ - unsigned short depth; - /* - * ID is freed by RCU. (and lookup routine is RCU safe.) - */ - struct rcu_head rcu_head; - /* - * Hierarchy of CSS ID belongs to. - */ - unsigned short stack[0]; /* Array of Length (depth+1) */ -}; - /* * cgroup_event represents events which userspace want to receive. */ @@ -387,9 +355,6 @@ struct cgrp_cset_link { static struct css_set init_css_set; static struct cgrp_cset_link init_cgrp_cset_link; -static int cgroup_init_idr(struct cgroup_subsys *ss, - struct cgroup_subsys_state *css); - /* * css_set_lock protects the list of css_set objects, and the chain of * tasks off each css_set. Nests outside task->alloc_lock due to @@ -841,8 +806,6 @@ static struct backing_dev_info cgroup_backing_dev_info = { .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; -static int alloc_css_id(struct cgroup_subsys_state *child_css); - static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb) { struct inode *inode = new_inode(sb); @@ -4242,21 +4205,6 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) goto err; } } - - /* This cgroup is ready now */ - for_each_root_subsys(cgrp->root, ss) { - struct cgroup_subsys_state *css = cgroup_css(cgrp, ss); - struct css_id *id = rcu_dereference_protected(css->id, true); - - /* - * Update id->css pointer and make this css visible from - * CSS ID functions. This pointer will be dereferened - * from RCU-read-side without locks. - */ - if (id) - rcu_assign_pointer(id->css, css); - } - return 0; err: cgroup_clear_dir(cgrp, subsys_mask); @@ -4325,7 +4273,6 @@ static void init_css(struct cgroup_subsys_state *css, struct cgroup_subsys *ss, css->cgroup = cgrp; css->ss = ss; css->flags = 0; - css->id = NULL; if (cgrp->parent) css->parent = cgroup_css(cgrp->parent, ss); @@ -4457,12 +4404,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, goto err_free_all; init_css(css, ss, cgrp); - - if (ss->use_id) { - err = alloc_css_id(css); - if (err) - goto err_free_all; - } } /* @@ -4927,12 +4868,6 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) /* our new subsystem will be attached to the dummy hierarchy. */ init_css(css, ss, cgroup_dummy_top); - /* init_idr must be after init_css() because it sets css->id. */ - if (ss->use_id) { - ret = cgroup_init_idr(ss, css); - if (ret) - goto err_unload; - } /* * Now we need to entangle the css into the existing css_sets. unlike @@ -4998,9 +4933,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) offline_css(cgroup_css(cgroup_dummy_top, ss)); - if (ss->use_id) - idr_destroy(&ss->idr); - /* deassign the subsys_id */ cgroup_subsys[ss->subsys_id] = NULL; @@ -5027,8 +4959,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) /* * remove subsystem's css from the cgroup_dummy_top and free it - * need to free before marking as null because ss->css_free needs - * the cgrp->subsys pointer to find their state. note that this - * also takes care of freeing the css_id. + * the cgrp->subsys pointer to find their state. */ ss->css_free(cgroup_css(cgroup_dummy_top, ss)); RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL); @@ -5099,8 +5030,6 @@ int __init cgroup_init(void) for_each_builtin_subsys(ss, i) { if (!ss->early_init) cgroup_init_subsys(ss); - if (ss->use_id) - cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]); } /* allocate id for the dummy hierarchy */ @@ -5520,181 +5449,6 @@ static int __init cgroup_disable(char *str) } __setup("cgroup_disable=", cgroup_disable); -/* - * Functons for CSS ID. - */ - -/* to get ID other than 0, this should be called when !cgroup_is_dead() */ -unsigned short css_id(struct cgroup_subsys_state *css) -{ - struct css_id *cssid; - - /* - * This css_id() can return correct value when somone has refcnt - * on this or this is under rcu_read_lock(). Once css->id is allocated, - * it's unchanged until freed. - */ - cssid = rcu_dereference_raw(css->id); - - if (cssid) - return cssid->id; - return 0; -} -EXPORT_SYMBOL_GPL(css_id); - -/** - * css_is_ancestor - test "root" css is an ancestor of "child" - * @child: the css to be tested. - * @root: the css supporsed to be an ancestor of the child. - * - * Returns true if "root" is an ancestor of "child" in its hierarchy. Because - * this function reads css->id, the caller must hold rcu_read_lock(). - * But, considering usual usage, the csses should be valid objects after test. - * Assuming that the caller will do some action to the child if this returns - * returns true, the caller must take "child";s reference count. - * If "child" is valid object and this returns true, "root" is valid, too. - */ - -bool css_is_ancestor(struct cgroup_subsys_state *child, - const struct cgroup_subsys_state *root) -{ - struct css_id *child_id; - struct css_id *root_id; - - child_id = rcu_dereference(child->id); - if (!child_id) - return false; - root_id = rcu_dereference(root->id); - if (!root_id) - return false; - if (child_id->depth < root_id->depth) - return false; - if (child_id->stack[root_id->depth] != root_id->id) - return false; - return true; -} - -void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css) -{ - struct css_id *id = rcu_dereference_protected(css->id, true); - - /* When this is called before css_id initialization, id can be NULL */ - if (!id) - return; - - BUG_ON(!ss->use_id); - - rcu_assign_pointer(id->css, NULL); - rcu_assign_pointer(css->id, NULL); - spin_lock(&ss->id_lock); - idr_remove(&ss->idr, id->id); - spin_unlock(&ss->id_lock); - kfree_rcu(id, rcu_head); -} -EXPORT_SYMBOL_GPL(free_css_id); - -/* - * This is called by init or create(). Then, calls to this function are - * always serialized (By cgroup_mutex() at create()). - */ - -static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth) -{ - struct css_id *newid; - int ret, size; - - BUG_ON(!ss->use_id); - - size = sizeof(*newid) + sizeof(unsigned short) * (depth + 1); - newid = kzalloc(size, GFP_KERNEL); - if (!newid) - return ERR_PTR(-ENOMEM); - - idr_preload(GFP_KERNEL); - spin_lock(&ss->id_lock); - /* Don't use 0. allocates an ID of 1-65535 */ - ret = idr_alloc(&ss->idr, newid, 1, CSS_ID_MAX + 1, GFP_NOWAIT); - spin_unlock(&ss->id_lock); - idr_preload_end(); - - /* Returns error when there are no free spaces for new ID.*/ - if (ret < 0) - goto err_out; - - newid->id = ret; - newid->depth = depth; - return newid; -err_out: - kfree(newid); - return ERR_PTR(ret); - -} - -static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss, - struct cgroup_subsys_state *rootcss) -{ - struct css_id *newid; - - spin_lock_init(&ss->id_lock); - idr_init(&ss->idr); - - newid = get_new_cssid(ss, 0); - if (IS_ERR(newid)) - return PTR_ERR(newid); - - newid->stack[0] = newid->id; - RCU_INIT_POINTER(newid->css, rootcss); - RCU_INIT_POINTER(rootcss->id, newid); - return 0; -} - -static int alloc_css_id(struct cgroup_subsys_state *child_css) -{ - struct cgroup_subsys_state *parent_css = css_parent(child_css); - struct css_id *child_id, *parent_id; - int i, depth; - - parent_id = rcu_dereference_protected(parent_css->id, true); - depth = parent_id->depth + 1; - - child_id = get_new_cssid(child_css->ss, depth); - if (IS_ERR(child_id)) - return PTR_ERR(child_id); - - for (i = 0; i < depth; i++) - child_id->stack[i] = parent_id->stack[i]; - child_id->stack[depth] = child_id->id; - /* - * child_id->css pointer will be set after this cgroup is available - * see cgroup_populate_dir() - */ - rcu_assign_pointer(child_css->id, child_id); - - return 0; -} - -/** - * css_lookup - lookup css by id - * @ss: cgroup subsys to be looked into. - * @id: the id - * - * Returns pointer to cgroup_subsys_state if there is valid one with id. - * NULL if not. Should be called under rcu_read_lock() - */ -struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id) -{ - struct css_id *cssid = NULL; - - BUG_ON(!ss->use_id); - cssid = idr_find(&ss->idr, id); - - if (unlikely(!cssid)) - return NULL; - - return rcu_dereference(cssid->css); -} -EXPORT_SYMBOL_GPL(css_lookup); - /** * css_from_dir - get corresponding css from the dentry of a cgroup dir * @dentry: directory dentry of interest -- cgit From 118150f22d6b4431a1fe2e715de314a5d93836f5 Mon Sep 17 00:00:00 2001 From: KV Sujith Date: Sun, 18 Aug 2013 10:48:58 +0530 Subject: gpio: davinci: move to platform device Modify DaVinci GPIO driver to become a platform device driver. The driver does not have platform driver structure or a probe. Instead, it has pure_initcall function for initialization. The platform specific informaiton is obtained using the DaVinci specific davinci_soc_info structure. This is a problem for Device Tree (DT) implementation. As a first stage of DT conversion, we implement a probe. Additional notes: - The driver registration happens as postcore_initcall. This is required since machine init functions like da850_lcd_hw_init() make use of GPIO. - Start using devres APIs for simpler error handling. Signed-off-by: KV Sujith [avinashphilip@ti.com: Move global definition of "davinci_gpio_controller" to local] Signed-off-by: Philip Avinash Acked-by: Linus Walleij [nsekhar@ti.com: drop unused structure member, rebase to new clean-up patch and fix error messages] Signed-off-by: Sekhar Nori Signed-off-by: Lad, Prabhakar --- arch/arm/mach-davinci/include/mach/gpio-davinci.h | 1 + drivers/gpio/gpio-davinci.c | 119 +++++++++++++++------- include/linux/platform_data/gpio-davinci.h | 25 +++++ 3 files changed, 107 insertions(+), 38 deletions(-) create mode 100644 include/linux/platform_data/gpio-davinci.h (limited to 'include') diff --git a/arch/arm/mach-davinci/include/mach/gpio-davinci.h b/arch/arm/mach-davinci/include/mach/gpio-davinci.h index 1fdd1fd35448..551ba43a763e 100644 --- a/arch/arm/mach-davinci/include/mach/gpio-davinci.h +++ b/arch/arm/mach-davinci/include/mach/gpio-davinci.h @@ -60,6 +60,7 @@ struct davinci_gpio_controller { void __iomem *set_data; void __iomem *clr_data; void __iomem *in_data; + unsigned gpio_irq; }; /* The __gpio_to_controller() and __gpio_mask() functions inline to constants diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index cb947a1266ae..8847adf392b7 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -15,8 +15,9 @@ #include #include #include - -#include +#include +#include +#include struct davinci_gpio_regs { u32 dir; @@ -36,10 +37,9 @@ struct davinci_gpio_regs { #define chip2controller(chip) \ container_of(chip, struct davinci_gpio_controller, chip) -static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; static void __iomem *gpio_base; -static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) +static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio) { void __iomem *ptr; @@ -67,7 +67,7 @@ static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) return g; } -static int __init davinci_gpio_irq_setup(void); +static int davinci_gpio_irq_setup(struct platform_device *pdev); /*--------------------------------------------------------------------------*/ @@ -133,33 +133,53 @@ davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); } -static int __init davinci_gpio_setup(void) +static int davinci_gpio_probe(struct platform_device *pdev) { int i, base; unsigned ngpio; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs *regs; - - if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) - return 0; + struct davinci_gpio_controller *chips; + struct davinci_gpio_platform_data *pdata; + struct davinci_gpio_regs __iomem *regs; + struct device *dev = &pdev->dev; + struct resource *res; + + pdata = dev->platform_data; + if (!pdata) { + dev_err(dev, "No platform data found\n"); + return -EINVAL; + } /* * The gpio banks conceptually expose a segmented bitmap, * and "ngpio" is one more than the largest zero-based * bit index that's valid. */ - ngpio = soc_info->gpio_num; + ngpio = pdata->ngpio; if (ngpio == 0) { - pr_err("GPIO setup: how many GPIOs?\n"); + dev_err(dev, "How many GPIOs?\n"); return -EINVAL; } if (WARN_ON(DAVINCI_N_GPIO < ngpio)) ngpio = DAVINCI_N_GPIO; - gpio_base = ioremap(soc_info->gpio_base, SZ_4K); - if (WARN_ON(!gpio_base)) + chips = devm_kzalloc(dev, + ngpio * sizeof(struct davinci_gpio_controller), + GFP_KERNEL); + if (!chips) { + dev_err(dev, "Memory allocation failed\n"); return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Invalid memory resource\n"); + return -EBUSY; + } + + gpio_base = devm_ioremap_resource(dev, res); + if (IS_ERR(gpio_base)) + return PTR_ERR(gpio_base); for (i = 0, base = 0; base < ngpio; i++, base += 32) { chips[i].chip.label = "DaVinci"; @@ -185,13 +205,10 @@ static int __init davinci_gpio_setup(void) gpiochip_add(&chips[i].chip); } - soc_info->gpio_ctlrs = chips; - soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - - davinci_gpio_irq_setup(); + platform_set_drvdata(pdev, chips); + davinci_gpio_irq_setup(pdev); return 0; } -pure_initcall(davinci_gpio_setup); /*--------------------------------------------------------------------------*/ /* @@ -304,14 +321,14 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) { - struct davinci_soc_info *soc_info = &davinci_soc_info; + struct davinci_gpio_controller *d = chip2controller(chip); /* * NOTE: we assume for now that only irqs in the first gpio_chip * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). */ - if (offset < soc_info->gpio_unbanked) - return soc_info->gpio_irq + offset; + if (offset < d->irq_base) + return d->gpio_irq + offset; else return -ENODEV; } @@ -320,12 +337,11 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) { struct davinci_gpio_controller *d; struct davinci_gpio_regs __iomem *g; - struct davinci_soc_info *soc_info = &davinci_soc_info; u32 mask; d = (struct davinci_gpio_controller *)data->handler_data; g = (struct davinci_gpio_regs __iomem *)d->regs; - mask = __gpio_mask(data->irq - soc_info->gpio_irq); + mask = __gpio_mask(data->irq - d->gpio_irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) return -EINVAL; @@ -346,24 +362,33 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) * (dm6446) can be set appropriately for GPIOV33 pins. */ -static int __init davinci_gpio_irq_setup(void) +static int davinci_gpio_irq_setup(struct platform_device *pdev) { unsigned gpio, irq, bank; struct clk *clk; u32 binten = 0; unsigned ngpio, bank_irq; - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_gpio_regs __iomem *g; + struct device *dev = &pdev->dev; + struct resource *res; + struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); + struct davinci_gpio_platform_data *pdata = dev->platform_data; + struct davinci_gpio_regs __iomem *g; - ngpio = soc_info->gpio_num; + ngpio = pdata->ngpio; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "Invalid IRQ resource\n"); + return -EBUSY; + } - bank_irq = soc_info->gpio_irq; - if (bank_irq == 0) { - printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); - return -EINVAL; + bank_irq = res->start; + + if (!bank_irq) { + dev_err(dev, "Invalid IRQ resource\n"); + return -ENODEV; } - clk = clk_get(NULL, "gpio"); + clk = devm_clk_get(dev, "gpio"); if (IS_ERR(clk)) { printk(KERN_ERR "Error %ld getting gpio clock?\n", PTR_ERR(clk)); @@ -379,9 +404,9 @@ static int __init davinci_gpio_irq_setup(void) */ for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { chips[bank].chip.to_irq = gpio_to_irq_banked; - chips[bank].irq_base = soc_info->gpio_unbanked + chips[bank].irq_base = pdata->gpio_unbanked ? -EINVAL - : (soc_info->intc_irq_num + gpio); + : (pdata->intc_irq_num + gpio); } /* @@ -389,7 +414,7 @@ static int __init davinci_gpio_irq_setup(void) * controller only handling trigger modes. We currently assume no * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. */ - if (soc_info->gpio_unbanked) { + if (pdata->gpio_unbanked) { static struct irq_chip_type gpio_unbanked; /* pass "bank 0" GPIO IRQs to AINTC */ @@ -409,7 +434,7 @@ static int __init davinci_gpio_irq_setup(void) __raw_writel(~0, &g->set_rising); /* set the direct IRQs up to use that irqchip */ - for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { + for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { irq_set_chip(irq, &gpio_unbanked.chip); irq_set_handler_data(irq, &chips[gpio / 32]); irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); @@ -464,3 +489,21 @@ done: return 0; } + +static struct platform_driver davinci_gpio_driver = { + .probe = davinci_gpio_probe, + .driver = { + .name = "davinci_gpio", + .owner = THIS_MODULE, + }, +}; + +/** + * GPIO driver registration needs to be done before machine_init functions + * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall. + */ +static int __init davinci_gpio_drv_reg(void) +{ + return platform_driver_register(&davinci_gpio_driver); +} +postcore_initcall(davinci_gpio_drv_reg); diff --git a/include/linux/platform_data/gpio-davinci.h b/include/linux/platform_data/gpio-davinci.h new file mode 100644 index 000000000000..2fcc125af1aa --- /dev/null +++ b/include/linux/platform_data/gpio-davinci.h @@ -0,0 +1,25 @@ +/* + * DaVinci GPIO Platform Related Defines + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DAVINCI_GPIO_PLATFORM_H +#define __DAVINCI_GPIO_PLATFORM_H + +struct davinci_gpio_platform_data { + u32 ngpio; + u32 gpio_unbanked; + u32 intc_irq_num; +}; + +#endif -- cgit From a5b4bd2874d9032b42db8cc4880058576c561b06 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:14 +0100 Subject: KEYS: Use bool in make_key_ref() and is_key_possessed() Make make_key_ref() take a bool possession parameter and make is_key_possessed() return a bool. Signed-off-by: David Howells --- Documentation/security/keys.txt | 7 +++---- include/linux/key.h | 4 ++-- security/keys/keyring.c | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 7b4145d00452..9ede67084f0b 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -865,15 +865,14 @@ encountered: calling processes has a searchable link to the key from one of its keyrings. There are three functions for dealing with these: - key_ref_t make_key_ref(const struct key *key, - unsigned long possession); + key_ref_t make_key_ref(const struct key *key, bool possession); struct key *key_ref_to_ptr(const key_ref_t key_ref); - unsigned long is_key_possessed(const key_ref_t key_ref); + bool is_key_possessed(const key_ref_t key_ref); The first function constructs a key reference from a key pointer and - possession information (which must be 0 or 1 and not any other value). + possession information (which must be true or false). The second function retrieves the key pointer from a reference and the third retrieves the possession flag. diff --git a/include/linux/key.h b/include/linux/key.h index 4dfde1161c5e..51bce2950de4 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -99,7 +99,7 @@ struct keyring_name; typedef struct __key_reference_with_attributes *key_ref_t; static inline key_ref_t make_key_ref(const struct key *key, - unsigned long possession) + bool possession) { return (key_ref_t) ((unsigned long) key | possession); } @@ -109,7 +109,7 @@ static inline struct key *key_ref_to_ptr(const key_ref_t key_ref) return (struct key *) ((unsigned long) key_ref & ~1UL); } -static inline unsigned long is_key_possessed(const key_ref_t key_ref) +static inline bool is_key_possessed(const key_ref_t key_ref) { return (unsigned long) key_ref & 1UL; } diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 6ece7f2e5707..f78406372ebe 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -329,9 +329,10 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, struct keyring_list *keylist; struct timespec now; - unsigned long possessed, kflags; + unsigned long kflags; struct key *keyring, *key; key_ref_t key_ref; + bool possessed; long err; int sp, nkeys, kix; @@ -542,8 +543,8 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, key_perm_t perm) { struct keyring_list *klist; - unsigned long possessed; struct key *keyring, *key; + bool possessed; int nkeys, loop; keyring = key_ref_to_ptr(keyring_ref); -- cgit From 16feef4340172b7dbb9cba60850e78fa6388adf1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:15 +0100 Subject: KEYS: Consolidate the concept of an 'index key' for key access Consolidate the concept of an 'index key' for accessing keys. The index key is the search term needed to find a key directly - basically the key type and the key description. We can add to that the description length. This will be useful when turning a keyring into an associative array rather than just a pointer block. Signed-off-by: David Howells --- include/linux/key.h | 21 +++++++++---- security/keys/internal.h | 8 ++--- security/keys/key.c | 72 +++++++++++++++++++++++---------------------- security/keys/keyring.c | 37 +++++++++++------------ security/keys/request_key.c | 12 +++++--- 5 files changed, 83 insertions(+), 67 deletions(-) (limited to 'include') diff --git a/include/linux/key.h b/include/linux/key.h index 51bce2950de4..d573e820a23d 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -82,6 +82,12 @@ struct key_owner; struct keyring_list; struct keyring_name; +struct keyring_index_key { + struct key_type *type; + const char *description; + size_t desc_len; +}; + /*****************************************************************************/ /* * key reference with possession attribute handling @@ -129,7 +135,6 @@ struct key { struct list_head graveyard_link; struct rb_node serial_node; }; - struct key_type *type; /* type of key */ struct rw_semaphore sem; /* change vs change sem */ struct key_user *user; /* owner of this key */ void *security; /* security data for this key */ @@ -163,12 +168,18 @@ struct key { #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ - /* the description string - * - this is used to match a key against search criteria - * - this should be a printable string + /* the key type and key description string + * - the desc is used to match a key against search criteria + * - it should be a printable string * - eg: for krb5 AFS, this might be "afs@REDHAT.COM" */ - char *description; + union { + struct keyring_index_key index_key; + struct { + struct key_type *type; /* type of key */ + char *description; + }; + }; /* type specific data * - this is used by the keyring type to index the name diff --git a/security/keys/internal.h b/security/keys/internal.h index 490aef5ba34b..77441dd1f9d4 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -89,19 +89,17 @@ extern struct key_type *key_type_lookup(const char *type); extern void key_type_put(struct key_type *ktype); extern int __key_link_begin(struct key *keyring, - const struct key_type *type, - const char *description, + const struct keyring_index_key *index_key, unsigned long *_prealloc); extern int __key_link_check_live_key(struct key *keyring, struct key *key); extern void __key_link(struct key *keyring, struct key *key, unsigned long *_prealloc); extern void __key_link_end(struct key *keyring, - struct key_type *type, + const struct keyring_index_key *index_key, unsigned long prealloc); extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, - const struct key_type *type, - const char *description, + const struct keyring_index_key *index_key, key_perm_t perm); extern struct key *keyring_search_instkey(struct key *keyring, diff --git a/security/keys/key.c b/security/keys/key.c index 8fb7c7bd4657..7e6bc396bb23 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -242,8 +242,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, } } - desclen = strlen(desc) + 1; - quotalen = desclen + type->def_datalen; + desclen = strlen(desc); + quotalen = desclen + 1 + type->def_datalen; /* get hold of the key tracking for this user */ user = key_user_lookup(uid); @@ -277,7 +277,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, goto no_memory_2; if (desc) { - key->description = kmemdup(desc, desclen, GFP_KERNEL); + key->index_key.desc_len = desclen; + key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); if (!key->description) goto no_memory_3; } @@ -285,7 +286,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, atomic_set(&key->usage, 1); init_rwsem(&key->sem); lockdep_set_class(&key->sem, &type->lock_class); - key->type = type; + key->index_key.type = type; key->user = user; key->quotalen = quotalen; key->datalen = type->def_datalen; @@ -489,8 +490,7 @@ int key_instantiate_and_link(struct key *key, } if (keyring) { - ret = __key_link_begin(keyring, key->type, key->description, - &prealloc); + ret = __key_link_begin(keyring, &key->index_key, &prealloc); if (ret < 0) goto error_free_preparse; } @@ -499,7 +499,7 @@ int key_instantiate_and_link(struct key *key, &prealloc); if (keyring) - __key_link_end(keyring, key->type, prealloc); + __key_link_end(keyring, &key->index_key, prealloc); error_free_preparse: if (key->type->preparse) @@ -548,8 +548,7 @@ int key_reject_and_link(struct key *key, ret = -EBUSY; if (keyring) - link_ret = __key_link_begin(keyring, key->type, - key->description, &prealloc); + link_ret = __key_link_begin(keyring, &key->index_key, &prealloc); mutex_lock(&key_construction_mutex); @@ -581,7 +580,7 @@ int key_reject_and_link(struct key *key, mutex_unlock(&key_construction_mutex); if (keyring) - __key_link_end(keyring, key->type, prealloc); + __key_link_end(keyring, &key->index_key, prealloc); /* wake up anyone waiting for a key to be constructed */ if (awaken) @@ -780,25 +779,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_perm_t perm, unsigned long flags) { - unsigned long prealloc; + struct keyring_index_key index_key = { + .description = description, + }; struct key_preparsed_payload prep; const struct cred *cred = current_cred(); - struct key_type *ktype; + unsigned long prealloc; struct key *keyring, *key = NULL; key_ref_t key_ref; int ret; /* look up the key type to see if it's one of the registered kernel * types */ - ktype = key_type_lookup(type); - if (IS_ERR(ktype)) { + index_key.type = key_type_lookup(type); + if (IS_ERR(index_key.type)) { key_ref = ERR_PTR(-ENODEV); goto error; } key_ref = ERR_PTR(-EINVAL); - if (!ktype->match || !ktype->instantiate || - (!description && !ktype->preparse)) + if (!index_key.type->match || !index_key.type->instantiate || + (!index_key.description && !index_key.type->preparse)) goto error_put_type; keyring = key_ref_to_ptr(keyring_ref); @@ -812,21 +813,22 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, memset(&prep, 0, sizeof(prep)); prep.data = payload; prep.datalen = plen; - prep.quotalen = ktype->def_datalen; - if (ktype->preparse) { - ret = ktype->preparse(&prep); + prep.quotalen = index_key.type->def_datalen; + if (index_key.type->preparse) { + ret = index_key.type->preparse(&prep); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_put_type; } - if (!description) - description = prep.description; + if (!index_key.description) + index_key.description = prep.description; key_ref = ERR_PTR(-EINVAL); - if (!description) + if (!index_key.description) goto error_free_prep; } + index_key.desc_len = strlen(index_key.description); - ret = __key_link_begin(keyring, ktype, description, &prealloc); + ret = __key_link_begin(keyring, &index_key, &prealloc); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_free_prep; @@ -844,9 +846,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, * key of the same type and description in the destination keyring and * update that instead if possible */ - if (ktype->update) { - key_ref = __keyring_search_one(keyring_ref, ktype, description, - 0); + if (index_key.type->update) { + key_ref = __keyring_search_one(keyring_ref, &index_key, 0); if (!IS_ERR(key_ref)) goto found_matching_key; } @@ -856,16 +857,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; perm |= KEY_USR_VIEW; - if (ktype->read) + if (index_key.type->read) perm |= KEY_POS_READ; - if (ktype == &key_type_keyring || ktype->update) + if (index_key.type == &key_type_keyring || + index_key.type->update) perm |= KEY_POS_WRITE; } /* allocate a new key */ - key = key_alloc(ktype, description, cred->fsuid, cred->fsgid, cred, - perm, flags); + key = key_alloc(index_key.type, index_key.description, + cred->fsuid, cred->fsgid, cred, perm, flags); if (IS_ERR(key)) { key_ref = ERR_CAST(key); goto error_link_end; @@ -882,12 +884,12 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_link_end: - __key_link_end(keyring, ktype, prealloc); + __key_link_end(keyring, &index_key, prealloc); error_free_prep: - if (ktype->preparse) - ktype->free_preparse(&prep); + if (index_key.type->preparse) + index_key.type->free_preparse(&prep); error_put_type: - key_type_put(ktype); + key_type_put(index_key.type); error: return key_ref; @@ -895,7 +897,7 @@ error: /* we found a matching key, so we're going to try to update it * - we can drop the locks first as we have the key pinned */ - __key_link_end(keyring, ktype, prealloc); + __key_link_end(keyring, &index_key, prealloc); key_ref = __key_update(key_ref, &prep); goto error_free_prep; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f78406372ebe..c7f59f9dd7b6 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -538,8 +538,7 @@ EXPORT_SYMBOL(keyring_search); * to the returned key reference. */ key_ref_t __keyring_search_one(key_ref_t keyring_ref, - const struct key_type *ktype, - const char *description, + const struct keyring_index_key *index_key, key_perm_t perm) { struct keyring_list *klist; @@ -558,9 +557,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, smp_rmb(); for (loop = 0; loop < nkeys ; loop++) { key = rcu_dereference(klist->keys[loop]); - if (key->type == ktype && + if (key->type == index_key->type && (!key->type->match || - key->type->match(key, description)) && + key->type->match(key, index_key->description)) && key_permission(make_key_ref(key, possessed), perm) == 0 && !(key->flags & ((1 << KEY_FLAG_INVALIDATED) | @@ -747,8 +746,8 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) /* * Preallocate memory so that a key can be linked into to a keyring. */ -int __key_link_begin(struct key *keyring, const struct key_type *type, - const char *description, unsigned long *_prealloc) +int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, + unsigned long *_prealloc) __acquires(&keyring->sem) __acquires(&keyring_serialise_link_sem) { @@ -759,7 +758,8 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, size_t size; int loop, lru, ret; - kenter("%d,%s,%s,", key_serial(keyring), type->name, description); + kenter("%d,%s,%s,", + key_serial(keyring), index_key->type->name, index_key->description); if (keyring->type != &key_type_keyring) return -ENOTDIR; @@ -772,7 +772,7 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, /* serialise link/link calls to prevent parallel calls causing a cycle * when linking two keyring in opposite orders */ - if (type == &key_type_keyring) + if (index_key->type == &key_type_keyring) down_write(&keyring_serialise_link_sem); klist = rcu_dereference_locked_keyring(keyring); @@ -784,8 +784,8 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, for (loop = klist->nkeys - 1; loop >= 0; loop--) { struct key *key = rcu_deref_link_locked(klist, loop, keyring); - if (key->type == type && - strcmp(key->description, description) == 0) { + if (key->type == index_key->type && + strcmp(key->description, index_key->description) == 0) { /* Found a match - we'll replace the link with * one to the new key. We record the slot * position. @@ -865,7 +865,7 @@ error_quota: key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); error_sem: - if (type == &key_type_keyring) + if (index_key->type == &key_type_keyring) up_write(&keyring_serialise_link_sem); error_krsem: up_write(&keyring->sem); @@ -957,16 +957,17 @@ void __key_link(struct key *keyring, struct key *key, * * Must be called with __key_link_begin() having being called. */ -void __key_link_end(struct key *keyring, struct key_type *type, +void __key_link_end(struct key *keyring, + const struct keyring_index_key *index_key, unsigned long prealloc) __releases(&keyring->sem) __releases(&keyring_serialise_link_sem) { - BUG_ON(type == NULL); - BUG_ON(type->name == NULL); - kenter("%d,%s,%lx", keyring->serial, type->name, prealloc); + BUG_ON(index_key->type == NULL); + BUG_ON(index_key->type->name == NULL); + kenter("%d,%s,%lx", keyring->serial, index_key->type->name, prealloc); - if (type == &key_type_keyring) + if (index_key->type == &key_type_keyring) up_write(&keyring_serialise_link_sem); if (prealloc) { @@ -1007,12 +1008,12 @@ int key_link(struct key *keyring, struct key *key) key_check(keyring); key_check(key); - ret = __key_link_begin(keyring, key->type, key->description, &prealloc); + ret = __key_link_begin(keyring, &key->index_key, &prealloc); if (ret == 0) { ret = __key_link_check_live_key(keyring, key); if (ret == 0) __key_link(keyring, key, &prealloc); - __key_link_end(keyring, key->type, prealloc); + __key_link_end(keyring, &key->index_key, prealloc); } return ret; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 172115b38054..586cb79ee82d 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -352,6 +352,11 @@ static int construct_alloc_key(struct key_type *type, struct key_user *user, struct key **_key) { + const struct keyring_index_key index_key = { + .type = type, + .description = description, + .desc_len = strlen(description), + }; const struct cred *cred = current_cred(); unsigned long prealloc; struct key *key; @@ -379,8 +384,7 @@ static int construct_alloc_key(struct key_type *type, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); if (dest_keyring) { - ret = __key_link_begin(dest_keyring, type, description, - &prealloc); + ret = __key_link_begin(dest_keyring, &index_key, &prealloc); if (ret < 0) goto link_prealloc_failed; } @@ -400,7 +404,7 @@ static int construct_alloc_key(struct key_type *type, mutex_unlock(&key_construction_mutex); if (dest_keyring) - __key_link_end(dest_keyring, type, prealloc); + __key_link_end(dest_keyring, &index_key, prealloc); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); @@ -416,7 +420,7 @@ key_already_present: ret = __key_link_check_live_key(dest_keyring, key); if (ret == 0) __key_link(dest_keyring, key, &prealloc); - __key_link_end(dest_keyring, type, prealloc); + __key_link_end(dest_keyring, &index_key, prealloc); if (ret < 0) goto link_check_failed; } -- cgit From 4bdf0bc300314141e5475e145acb8b5ad846f00d Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:15 +0100 Subject: KEYS: Introduce a search context structure Search functions pass around a bunch of arguments, each of which gets copied with each call. Introduce a search context structure to hold these. Whilst we're at it, create a search flag that indicates whether the search should be directly to the description or whether it should iterate through all keys looking for a non-description match. This will be useful when keyrings use a generic data struct with generic routines to manage their content as the search terms can just be passed through to the iterator callback function. Also, for future use, the data to be supplied to the match function is separated from the description pointer in the search context. This makes it clear which is being supplied. Signed-off-by: David Howells --- include/linux/key-type.h | 5 ++ security/keys/internal.h | 40 +++++++------ security/keys/keyring.c | 70 +++++++++++------------ security/keys/proc.c | 17 ++++-- security/keys/process_keys.c | 117 +++++++++++++++++++-------------------- security/keys/request_key.c | 56 +++++++++---------- security/keys/request_key_auth.c | 14 +++-- security/keys/user_defined.c | 18 +++--- 8 files changed, 179 insertions(+), 158 deletions(-) (limited to 'include') diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 518a53afb9ea..f58737bcb050 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -63,6 +63,11 @@ struct key_type { */ size_t def_datalen; + /* Default key search algorithm. */ + unsigned def_lookup_type; +#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */ +#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */ + /* vet a description */ int (*vet_description)(const char *description); diff --git a/security/keys/internal.h b/security/keys/internal.h index 77441dd1f9d4..f4bf938b68b4 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -107,23 +107,31 @@ extern struct key *keyring_search_instkey(struct key *keyring, typedef int (*key_match_func_t)(const struct key *, const void *); +struct keyring_search_context { + struct keyring_index_key index_key; + const struct cred *cred; + key_match_func_t match; + const void *match_data; + unsigned flags; +#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ +#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ +#define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */ +#define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */ +#define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ +#define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ + + /* Internal stuff */ + int skipped_ret; + bool possessed; + key_ref_t result; + struct timespec now; +}; + extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, - const struct cred *cred, - struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check); - -extern key_ref_t search_my_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check, - const struct cred *cred); -extern key_ref_t search_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check, - const struct cred *cred); + struct keyring_search_context *ctx); + +extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx); +extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx); extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index c7f59f9dd7b6..b42f2d4f7f83 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -280,11 +280,7 @@ EXPORT_SYMBOL(keyring_alloc); /** * keyring_search_aux - Search a keyring tree for a key matching some criteria * @keyring_ref: A pointer to the keyring with possession indicator. - * @cred: The credentials to use for permissions checks. - * @type: The type of key to search for. - * @description: Parameter for @match. - * @match: Function to rule on whether or not a key is the one required. - * @no_state_check: Don't check if a matching key is bad + * @ctx: The keyring search context. * * Search the supplied keyring tree for a key that matches the criteria given. * The root keyring and any linked keyrings must grant Search permission to the @@ -314,11 +310,7 @@ EXPORT_SYMBOL(keyring_alloc); * @keyring_ref is propagated to the returned key reference. */ key_ref_t keyring_search_aux(key_ref_t keyring_ref, - const struct cred *cred, - struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check) + struct keyring_search_context *ctx) { struct { /* Need a separate keylist pointer for RCU purposes */ @@ -328,20 +320,18 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, } stack[KEYRING_SEARCH_MAX_DEPTH]; struct keyring_list *keylist; - struct timespec now; unsigned long kflags; struct key *keyring, *key; key_ref_t key_ref; - bool possessed; long err; int sp, nkeys, kix; keyring = key_ref_to_ptr(keyring_ref); - possessed = is_key_possessed(keyring_ref); + ctx->possessed = is_key_possessed(keyring_ref); key_check(keyring); /* top keyring must have search permission to begin the search */ - err = key_task_permission(keyring_ref, cred, KEY_SEARCH); + err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH); if (err < 0) { key_ref = ERR_PTR(err); goto error; @@ -353,7 +343,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, rcu_read_lock(); - now = current_kernel_time(); + ctx->now = current_kernel_time(); err = -EAGAIN; sp = 0; @@ -361,16 +351,17 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, * are looking for */ key_ref = ERR_PTR(-EAGAIN); kflags = keyring->flags; - if (keyring->type == type && match(keyring, description)) { + if (keyring->type == ctx->index_key.type && + ctx->match(keyring, ctx->match_data)) { key = keyring; - if (no_state_check) + if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK) goto found; /* check it isn't negative and hasn't expired or been * revoked */ if (kflags & (1 << KEY_FLAG_REVOKED)) goto error_2; - if (key->expiry && now.tv_sec >= key->expiry) + if (key->expiry && ctx->now.tv_sec >= key->expiry) goto error_2; key_ref = ERR_PTR(key->type_data.reject_error); if (kflags & (1 << KEY_FLAG_NEGATIVE)) @@ -384,7 +375,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, if (kflags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) || - (keyring->expiry && now.tv_sec >= keyring->expiry)) + (keyring->expiry && ctx->now.tv_sec >= keyring->expiry)) goto error_2; /* start processing a new keyring */ @@ -406,29 +397,29 @@ descend: kflags = key->flags; /* ignore keys not of this type */ - if (key->type != type) + if (key->type != ctx->index_key.type) continue; /* skip invalidated, revoked and expired keys */ - if (!no_state_check) { + if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) { if (kflags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED))) continue; - if (key->expiry && now.tv_sec >= key->expiry) + if (key->expiry && ctx->now.tv_sec >= key->expiry) continue; } /* keys that don't match */ - if (!match(key, description)) + if (!ctx->match(key, ctx->match_data)) continue; /* key must have search permissions */ - if (key_task_permission(make_key_ref(key, possessed), - cred, KEY_SEARCH) < 0) + if (key_task_permission(make_key_ref(key, ctx->possessed), + ctx->cred, KEY_SEARCH) < 0) continue; - if (no_state_check) + if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK) goto found; /* we set a different error code if we pass a negative key */ @@ -456,8 +447,8 @@ ascend: if (sp >= KEYRING_SEARCH_MAX_DEPTH) continue; - if (key_task_permission(make_key_ref(key, possessed), - cred, KEY_SEARCH) < 0) + if (key_task_permission(make_key_ref(key, ctx->possessed), + ctx->cred, KEY_SEARCH) < 0) continue; /* stack the current position */ @@ -489,12 +480,12 @@ not_this_keyring: /* we found a viable match */ found: atomic_inc(&key->usage); - key->last_used_at = now.tv_sec; - keyring->last_used_at = now.tv_sec; + key->last_used_at = ctx->now.tv_sec; + keyring->last_used_at = ctx->now.tv_sec; while (sp > 0) - stack[--sp].keyring->last_used_at = now.tv_sec; + stack[--sp].keyring->last_used_at = ctx->now.tv_sec; key_check(key); - key_ref = make_key_ref(key, possessed); + key_ref = make_key_ref(key, ctx->possessed); error_2: rcu_read_unlock(); error: @@ -514,11 +505,20 @@ key_ref_t keyring_search(key_ref_t keyring, struct key_type *type, const char *description) { - if (!type->match) + struct keyring_search_context ctx = { + .index_key.type = type, + .index_key.description = description, + .cred = current_cred(), + .match = type->match, + .match_data = description, + .flags = (type->def_lookup_type | + KEYRING_SEARCH_DO_STATE_CHECK), + }; + + if (!ctx.match) return ERR_PTR(-ENOKEY); - return keyring_search_aux(keyring, current->cred, - type, description, type->match, false); + return keyring_search_aux(keyring, &ctx); } EXPORT_SYMBOL(keyring_search); diff --git a/security/keys/proc.c b/security/keys/proc.c index 217b6855e815..88e9a466940f 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -182,7 +182,6 @@ static void proc_keys_stop(struct seq_file *p, void *v) static int proc_keys_show(struct seq_file *m, void *v) { - const struct cred *cred = current_cred(); struct rb_node *_p = v; struct key *key = rb_entry(_p, struct key, serial_node); struct timespec now; @@ -191,15 +190,23 @@ static int proc_keys_show(struct seq_file *m, void *v) char xbuf[12]; int rc; + struct keyring_search_context ctx = { + .index_key.type = key->type, + .index_key.description = key->description, + .cred = current_cred(), + .match = lookup_user_key_possessed, + .match_data = key, + .flags = (KEYRING_SEARCH_NO_STATE_CHECK | + KEYRING_SEARCH_LOOKUP_DIRECT), + }; + key_ref = make_key_ref(key, 0); /* determine if the key is possessed by this process (a test we can * skip if the key does not indicate the possessor can view it */ if (key->perm & KEY_POS_VIEW) { - skey_ref = search_my_process_keyrings(key->type, key, - lookup_user_key_possessed, - true, cred); + skey_ref = search_my_process_keyrings(&ctx); if (!IS_ERR(skey_ref)) { key_ref_put(skey_ref); key_ref = make_key_ref(key, 1); @@ -211,7 +218,7 @@ static int proc_keys_show(struct seq_file *m, void *v) * - the caller holds a spinlock, and thus the RCU read lock, making our * access to __current_cred() safe */ - rc = key_task_permission(key_ref, cred, KEY_VIEW); + rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW); if (rc < 0) return 0; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index a3410d605849..e68a3e0e7aa0 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -319,11 +319,7 @@ void key_fsgid_changed(struct task_struct *tsk) * In the case of a successful return, the possession attribute is set on the * returned key reference. */ -key_ref_t search_my_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check, - const struct cred *cred) +key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) { key_ref_t key_ref, ret, err; @@ -339,10 +335,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, err = ERR_PTR(-EAGAIN); /* search the thread keyring first */ - if (cred->thread_keyring) { + if (ctx->cred->thread_keyring) { key_ref = keyring_search_aux( - make_key_ref(cred->thread_keyring, 1), - cred, type, description, match, no_state_check); + make_key_ref(ctx->cred->thread_keyring, 1), ctx); if (!IS_ERR(key_ref)) goto found; @@ -358,10 +353,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, } /* search the process keyring second */ - if (cred->process_keyring) { + if (ctx->cred->process_keyring) { key_ref = keyring_search_aux( - make_key_ref(cred->process_keyring, 1), - cred, type, description, match, no_state_check); + make_key_ref(ctx->cred->process_keyring, 1), ctx); if (!IS_ERR(key_ref)) goto found; @@ -379,11 +373,11 @@ key_ref_t search_my_process_keyrings(struct key_type *type, } /* search the session keyring */ - if (cred->session_keyring) { + if (ctx->cred->session_keyring) { rcu_read_lock(); key_ref = keyring_search_aux( - make_key_ref(rcu_dereference(cred->session_keyring), 1), - cred, type, description, match, no_state_check); + make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1), + ctx); rcu_read_unlock(); if (!IS_ERR(key_ref)) @@ -402,10 +396,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type, } } /* or search the user-session keyring */ - else if (cred->user->session_keyring) { + else if (ctx->cred->user->session_keyring) { key_ref = keyring_search_aux( - make_key_ref(cred->user->session_keyring, 1), - cred, type, description, match, no_state_check); + make_key_ref(ctx->cred->user->session_keyring, 1), + ctx); if (!IS_ERR(key_ref)) goto found; @@ -437,19 +431,14 @@ found: * * Return same as search_my_process_keyrings(). */ -key_ref_t search_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - bool no_state_check, - const struct cred *cred) +key_ref_t search_process_keyrings(struct keyring_search_context *ctx) { struct request_key_auth *rka; key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; might_sleep(); - key_ref = search_my_process_keyrings(type, description, match, - no_state_check, cred); + key_ref = search_my_process_keyrings(ctx); if (!IS_ERR(key_ref)) goto found; err = key_ref; @@ -458,19 +447,21 @@ key_ref_t search_process_keyrings(struct key_type *type, * search the keyrings of the process mentioned there * - we don't permit access to request_key auth keys via this method */ - if (cred->request_key_auth && - cred == current_cred() && - type != &key_type_request_key_auth + if (ctx->cred->request_key_auth && + ctx->cred == current_cred() && + ctx->index_key.type != &key_type_request_key_auth ) { + const struct cred *cred = ctx->cred; + /* defend against the auth key being revoked */ down_read(&cred->request_key_auth->sem); - if (key_validate(cred->request_key_auth) == 0) { - rka = cred->request_key_auth->payload.data; + if (key_validate(ctx->cred->request_key_auth) == 0) { + rka = ctx->cred->request_key_auth->payload.data; - key_ref = search_process_keyrings(type, description, - match, no_state_check, - rka->cred); + ctx->cred = rka->cred; + key_ref = search_process_keyrings(ctx); + ctx->cred = cred; up_read(&cred->request_key_auth->sem); @@ -524,19 +515,23 @@ int lookup_user_key_possessed(const struct key *key, const void *target) key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, key_perm_t perm) { + struct keyring_search_context ctx = { + .match = lookup_user_key_possessed, + .flags = (KEYRING_SEARCH_NO_STATE_CHECK | + KEYRING_SEARCH_LOOKUP_DIRECT), + }; struct request_key_auth *rka; - const struct cred *cred; struct key *key; key_ref_t key_ref, skey_ref; int ret; try_again: - cred = get_current_cred(); + ctx.cred = get_current_cred(); key_ref = ERR_PTR(-ENOKEY); switch (id) { case KEY_SPEC_THREAD_KEYRING: - if (!cred->thread_keyring) { + if (!ctx.cred->thread_keyring) { if (!(lflags & KEY_LOOKUP_CREATE)) goto error; @@ -548,13 +543,13 @@ try_again: goto reget_creds; } - key = cred->thread_keyring; + key = ctx.cred->thread_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_PROCESS_KEYRING: - if (!cred->process_keyring) { + if (!ctx.cred->process_keyring) { if (!(lflags & KEY_LOOKUP_CREATE)) goto error; @@ -566,13 +561,13 @@ try_again: goto reget_creds; } - key = cred->process_keyring; + key = ctx.cred->process_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_SESSION_KEYRING: - if (!cred->session_keyring) { + if (!ctx.cred->session_keyring) { /* always install a session keyring upon access if one * doesn't exist yet */ ret = install_user_keyrings(); @@ -582,13 +577,13 @@ try_again: ret = join_session_keyring(NULL); else ret = install_session_keyring( - cred->user->session_keyring); + ctx.cred->user->session_keyring); if (ret < 0) goto error; goto reget_creds; - } else if (cred->session_keyring == - cred->user->session_keyring && + } else if (ctx.cred->session_keyring == + ctx.cred->user->session_keyring && lflags & KEY_LOOKUP_CREATE) { ret = join_session_keyring(NULL); if (ret < 0) @@ -597,32 +592,32 @@ try_again: } rcu_read_lock(); - key = rcu_dereference(cred->session_keyring); + key = rcu_dereference(ctx.cred->session_keyring); atomic_inc(&key->usage); rcu_read_unlock(); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_KEYRING: - if (!cred->user->uid_keyring) { + if (!ctx.cred->user->uid_keyring) { ret = install_user_keyrings(); if (ret < 0) goto error; } - key = cred->user->uid_keyring; + key = ctx.cred->user->uid_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_SESSION_KEYRING: - if (!cred->user->session_keyring) { + if (!ctx.cred->user->session_keyring) { ret = install_user_keyrings(); if (ret < 0) goto error; } - key = cred->user->session_keyring; + key = ctx.cred->user->session_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; @@ -633,7 +628,7 @@ try_again: goto error; case KEY_SPEC_REQKEY_AUTH_KEY: - key = cred->request_key_auth; + key = ctx.cred->request_key_auth; if (!key) goto error; @@ -642,20 +637,20 @@ try_again: break; case KEY_SPEC_REQUESTOR_KEYRING: - if (!cred->request_key_auth) + if (!ctx.cred->request_key_auth) goto error; - down_read(&cred->request_key_auth->sem); + down_read(&ctx.cred->request_key_auth->sem); if (test_bit(KEY_FLAG_REVOKED, - &cred->request_key_auth->flags)) { + &ctx.cred->request_key_auth->flags)) { key_ref = ERR_PTR(-EKEYREVOKED); key = NULL; } else { - rka = cred->request_key_auth->payload.data; + rka = ctx.cred->request_key_auth->payload.data; key = rka->dest_keyring; atomic_inc(&key->usage); } - up_read(&cred->request_key_auth->sem); + up_read(&ctx.cred->request_key_auth->sem); if (!key) goto error; key_ref = make_key_ref(key, 1); @@ -675,9 +670,13 @@ try_again: key_ref = make_key_ref(key, 0); /* check to see if we possess the key */ - skey_ref = search_process_keyrings(key->type, key, - lookup_user_key_possessed, - true, cred); + ctx.index_key.type = key->type; + ctx.index_key.description = key->description; + ctx.index_key.desc_len = strlen(key->description); + ctx.match_data = key; + kdebug("check possessed"); + skey_ref = search_process_keyrings(&ctx); + kdebug("possessed=%p", skey_ref); if (!IS_ERR(skey_ref)) { key_put(key); @@ -717,14 +716,14 @@ try_again: goto invalid_key; /* check the permissions */ - ret = key_task_permission(key_ref, cred, perm); + ret = key_task_permission(key_ref, ctx.cred, perm); if (ret < 0) goto invalid_key; key->last_used_at = current_kernel_time().tv_sec; error: - put_cred(cred); + put_cred(ctx.cred); return key_ref; invalid_key: @@ -735,7 +734,7 @@ invalid_key: /* if we attempted to install a keyring, then it may have caused new * creds to be installed */ reget_creds: - put_cred(cred); + put_cred(ctx.cred); goto try_again; } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 586cb79ee82d..ab75df4745af 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -345,38 +345,34 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) * May return a key that's already under construction instead if there was a * race between two thread calling request_key(). */ -static int construct_alloc_key(struct key_type *type, - const char *description, +static int construct_alloc_key(struct keyring_search_context *ctx, struct key *dest_keyring, unsigned long flags, struct key_user *user, struct key **_key) { - const struct keyring_index_key index_key = { - .type = type, - .description = description, - .desc_len = strlen(description), - }; - const struct cred *cred = current_cred(); unsigned long prealloc; struct key *key; key_perm_t perm; key_ref_t key_ref; int ret; - kenter("%s,%s,,,", type->name, description); + kenter("%s,%s,,,", + ctx->index_key.type->name, ctx->index_key.description); *_key = NULL; mutex_lock(&user->cons_lock); perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; perm |= KEY_USR_VIEW; - if (type->read) + if (ctx->index_key.type->read) perm |= KEY_POS_READ; - if (type == &key_type_keyring || type->update) + if (ctx->index_key.type == &key_type_keyring || + ctx->index_key.type->update) perm |= KEY_POS_WRITE; - key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, + key = key_alloc(ctx->index_key.type, ctx->index_key.description, + ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred, perm, flags); if (IS_ERR(key)) goto alloc_failed; @@ -384,7 +380,7 @@ static int construct_alloc_key(struct key_type *type, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); if (dest_keyring) { - ret = __key_link_begin(dest_keyring, &index_key, &prealloc); + ret = __key_link_begin(dest_keyring, &ctx->index_key, &prealloc); if (ret < 0) goto link_prealloc_failed; } @@ -394,8 +390,7 @@ static int construct_alloc_key(struct key_type *type, * waited for locks */ mutex_lock(&key_construction_mutex); - key_ref = search_process_keyrings(type, description, type->match, - false, cred); + key_ref = search_process_keyrings(ctx); if (!IS_ERR(key_ref)) goto key_already_present; @@ -404,7 +399,7 @@ static int construct_alloc_key(struct key_type *type, mutex_unlock(&key_construction_mutex); if (dest_keyring) - __key_link_end(dest_keyring, &index_key, prealloc); + __key_link_end(dest_keyring, &ctx->index_key, prealloc); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); @@ -420,7 +415,7 @@ key_already_present: ret = __key_link_check_live_key(dest_keyring, key); if (ret == 0) __key_link(dest_keyring, key, &prealloc); - __key_link_end(dest_keyring, &index_key, prealloc); + __key_link_end(dest_keyring, &ctx->index_key, prealloc); if (ret < 0) goto link_check_failed; } @@ -449,8 +444,7 @@ alloc_failed: /* * Commence key construction. */ -static struct key *construct_key_and_link(struct key_type *type, - const char *description, +static struct key *construct_key_and_link(struct keyring_search_context *ctx, const char *callout_info, size_t callout_len, void *aux, @@ -469,8 +463,7 @@ static struct key *construct_key_and_link(struct key_type *type, construct_get_dest_keyring(&dest_keyring); - ret = construct_alloc_key(type, description, dest_keyring, flags, user, - &key); + ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); key_user_put(user); if (ret == 0) { @@ -534,18 +527,24 @@ struct key *request_key_and_link(struct key_type *type, struct key *dest_keyring, unsigned long flags) { - const struct cred *cred = current_cred(); + struct keyring_search_context ctx = { + .index_key.type = type, + .index_key.description = description, + .cred = current_cred(), + .match = type->match, + .match_data = description, + .flags = KEYRING_SEARCH_LOOKUP_DIRECT, + }; struct key *key; key_ref_t key_ref; int ret; kenter("%s,%s,%p,%zu,%p,%p,%lx", - type->name, description, callout_info, callout_len, aux, - dest_keyring, flags); + ctx.index_key.type->name, ctx.index_key.description, + callout_info, callout_len, aux, dest_keyring, flags); /* search all the process keyrings for a key */ - key_ref = search_process_keyrings(type, description, type->match, - false, cred); + key_ref = search_process_keyrings(&ctx); if (!IS_ERR(key_ref)) { key = key_ref_to_ptr(key_ref); @@ -568,9 +567,8 @@ struct key *request_key_and_link(struct key_type *type, if (!callout_info) goto error; - key = construct_key_and_link(type, description, callout_info, - callout_len, aux, dest_keyring, - flags); + key = construct_key_and_link(&ctx, callout_info, callout_len, + aux, dest_keyring, flags); } error: diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 92077de555df..8d09852854ca 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -239,15 +239,17 @@ static int key_get_instantiation_authkey_match(const struct key *key, */ struct key *key_get_instantiation_authkey(key_serial_t target_id) { - const struct cred *cred = current_cred(); + struct keyring_search_context ctx = { + .index_key.type = &key_type_request_key_auth, + .cred = current_cred(), + .match = key_get_instantiation_authkey_match, + .match_data = (void *)(unsigned long)target_id, + .flags = KEYRING_SEARCH_LOOKUP_DIRECT, + }; struct key *authkey; key_ref_t authkey_ref; - authkey_ref = search_process_keyrings( - &key_type_request_key_auth, - (void *) (unsigned long) target_id, - key_get_instantiation_authkey_match, - false, cred); + authkey_ref = search_process_keyrings(&ctx); if (IS_ERR(authkey_ref)) { authkey = ERR_CAST(authkey_ref); diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 55dc88939185..faa2caeb593f 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -25,14 +25,15 @@ static int logon_vet_description(const char *desc); * arbitrary blob of data as the payload */ struct key_type key_type_user = { - .name = "user", - .instantiate = user_instantiate, - .update = user_update, - .match = user_match, - .revoke = user_revoke, - .destroy = user_destroy, - .describe = user_describe, - .read = user_read, + .name = "user", + .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, + .instantiate = user_instantiate, + .update = user_update, + .match = user_match, + .revoke = user_revoke, + .destroy = user_destroy, + .describe = user_describe, + .read = user_read, }; EXPORT_SYMBOL_GPL(key_type_user); @@ -45,6 +46,7 @@ EXPORT_SYMBOL_GPL(key_type_user); */ struct key_type key_type_logon = { .name = "logon", + .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .instantiate = user_instantiate, .update = user_update, .match = user_match, -- cgit From ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:16 +0100 Subject: KEYS: Define a __key_get() wrapper to use rather than atomic_inc() Define a __key_get() wrapper to use rather than atomic_inc() on the key usage count as this makes it easier to hook in refcount error debugging. Signed-off-by: David Howells --- Documentation/security/keys.txt | 13 ++++++++----- include/linux/key.h | 10 +++++++--- security/keys/key.c | 2 +- security/keys/keyring.c | 6 +++--- security/keys/process_keys.c | 16 ++++++++-------- 5 files changed, 27 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 9ede67084f0b..a4c33f1a7c6d 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -960,14 +960,17 @@ payload contents" for more information. the argument will not be parsed. -(*) Extra references can be made to a key by calling the following function: +(*) Extra references can be made to a key by calling one of the following + functions: + struct key *__key_get(struct key *key); struct key *key_get(struct key *key); - These need to be disposed of by calling key_put() when they've been - finished with. The key pointer passed in will be returned. If the pointer - is NULL or CONFIG_KEYS is not set then the key will not be dereferenced and - no increment will take place. + Keys so references will need to be disposed of by calling key_put() when + they've been finished with. The key pointer passed in will be returned. + + In the case of key_get(), if the pointer is NULL or CONFIG_KEYS is not set + then the key will not be dereferenced and no increment will take place. (*) A key's serial number can be obtained by calling: diff --git a/include/linux/key.h b/include/linux/key.h index d573e820a23d..ef596c7af585 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -219,13 +219,17 @@ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); extern void key_put(struct key *key); -static inline struct key *key_get(struct key *key) +static inline struct key *__key_get(struct key *key) { - if (key) - atomic_inc(&key->usage); + atomic_inc(&key->usage); return key; } +static inline struct key *key_get(struct key *key) +{ + return key ? __key_get(key) : key; +} + static inline void key_ref_put(key_ref_t key_ref) { key_put(key_ref_to_ptr(key_ref)); diff --git a/security/keys/key.c b/security/keys/key.c index 7e6bc396bb23..1e23cc288106 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -644,7 +644,7 @@ found: /* this races with key_put(), but that doesn't matter since key_put() * doesn't actually change the key */ - atomic_inc(&key->usage); + __key_get(key); error: spin_unlock(&key_serial_lock); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index b42f2d4f7f83..87eff32b53f4 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -479,7 +479,7 @@ not_this_keyring: /* we found a viable match */ found: - atomic_inc(&key->usage); + __key_get(key); key->last_used_at = ctx->now.tv_sec; keyring->last_used_at = ctx->now.tv_sec; while (sp > 0) @@ -573,7 +573,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, return ERR_PTR(-ENOKEY); found: - atomic_inc(&key->usage); + __key_get(key); keyring->last_used_at = key->last_used_at = current_kernel_time().tv_sec; rcu_read_unlock(); @@ -909,7 +909,7 @@ void __key_link(struct key *keyring, struct key *key, klist = rcu_dereference_locked_keyring(keyring); - atomic_inc(&key->usage); + __key_get(key); keyring->last_used_at = key->last_used_at = current_kernel_time().tv_sec; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e68a3e0e7aa0..68548ea6fe01 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -235,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) if (IS_ERR(keyring)) return PTR_ERR(keyring); } else { - atomic_inc(&keyring->usage); + __key_get(keyring); } /* install the keyring */ @@ -544,7 +544,7 @@ try_again: } key = ctx.cred->thread_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -562,7 +562,7 @@ try_again: } key = ctx.cred->process_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -593,7 +593,7 @@ try_again: rcu_read_lock(); key = rcu_dereference(ctx.cred->session_keyring); - atomic_inc(&key->usage); + __key_get(key); rcu_read_unlock(); key_ref = make_key_ref(key, 1); break; @@ -606,7 +606,7 @@ try_again: } key = ctx.cred->user->uid_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -618,7 +618,7 @@ try_again: } key = ctx.cred->user->session_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -632,7 +632,7 @@ try_again: if (!key) goto error; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -648,7 +648,7 @@ try_again: } else { rka = ctx.cred->request_key_auth->payload.data; key = rka->dest_keyring; - atomic_inc(&key->usage); + __key_get(key); } up_read(&ctx.cred->request_key_auth->sem); if (!key) -- cgit From 3cb989501c2688cacbb7dc4b0d353faf838f53a1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:17 +0100 Subject: Add a generic associative array implementation. Add a generic associative array implementation that can be used as the container for keyrings, thereby massively increasing the capacity available whilst also speeding up searching in keyrings that contain a lot of keys. This may also be useful in FS-Cache for tracking cookies. Documentation is added into Documentation/associative_array.txt Some of the properties of the implementation are: (1) Objects are opaque pointers. The implementation does not care where they point (if anywhere) or what they point to (if anything). [!] NOTE: Pointers to objects _must_ be zero in the two least significant bits. (2) Objects do not need to contain linkage blocks for use by the array. This permits an object to be located in multiple arrays simultaneously. Rather, the array is made up of metadata blocks that point to objects. (3) Objects are labelled as being one of two types (the type is a bool value). This information is stored in the array, but has no consequence to the array itself or its algorithms. (4) Objects require index keys to locate them within the array. (5) Index keys must be unique. Inserting an object with the same key as one already in the array will replace the old object. (6) Index keys can be of any length and can be of different lengths. (7) Index keys should encode the length early on, before any variation due to length is seen. (8) Index keys can include a hash to scatter objects throughout the array. (9) The array can iterated over. The objects will not necessarily come out in key order. (10) The array can be iterated whilst it is being modified, provided the RCU readlock is being held by the iterator. Note, however, under these circumstances, some objects may be seen more than once. If this is a problem, the iterator should lock against modification. Objects will not be missed, however, unless deleted. (11) Objects in the array can be looked up by means of their index key. (12) Objects can be looked up whilst the array is being modified, provided the RCU readlock is being held by the thread doing the look up. The implementation uses a tree of 16-pointer nodes internally that are indexed on each level by nibbles from the index key. To improve memory efficiency, shortcuts can be emplaced to skip over what would otherwise be a series of single-occupancy nodes. Further, nodes pack leaf object pointers into spare space in the node rather than making an extra branch until as such time an object needs to be added to a full node. Signed-off-by: David Howells --- Documentation/assoc_array.txt | 574 +++++++++++++ include/linux/assoc_array.h | 92 ++ include/linux/assoc_array_priv.h | 182 ++++ lib/Kconfig | 14 + lib/Makefile | 1 + lib/assoc_array.c | 1745 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 2608 insertions(+) create mode 100644 Documentation/assoc_array.txt create mode 100644 include/linux/assoc_array.h create mode 100644 include/linux/assoc_array_priv.h create mode 100644 lib/assoc_array.c (limited to 'include') diff --git a/Documentation/assoc_array.txt b/Documentation/assoc_array.txt new file mode 100644 index 000000000000..f4faec0f66e4 --- /dev/null +++ b/Documentation/assoc_array.txt @@ -0,0 +1,574 @@ + ======================================== + GENERIC ASSOCIATIVE ARRAY IMPLEMENTATION + ======================================== + +Contents: + + - Overview. + + - The public API. + - Edit script. + - Operations table. + - Manipulation functions. + - Access functions. + - Index key form. + + - Internal workings. + - Basic internal tree layout. + - Shortcuts. + - Splitting and collapsing nodes. + - Non-recursive iteration. + - Simultaneous alteration and iteration. + + +======== +OVERVIEW +======== + +This associative array implementation is an object container with the following +properties: + + (1) Objects are opaque pointers. The implementation does not care where they + point (if anywhere) or what they point to (if anything). + + [!] NOTE: Pointers to objects _must_ be zero in the least significant bit. + + (2) Objects do not need to contain linkage blocks for use by the array. This + permits an object to be located in multiple arrays simultaneously. + Rather, the array is made up of metadata blocks that point to objects. + + (3) Objects require index keys to locate them within the array. + + (4) Index keys must be unique. Inserting an object with the same key as one + already in the array will replace the old object. + + (5) Index keys can be of any length and can be of different lengths. + + (6) Index keys should encode the length early on, before any variation due to + length is seen. + + (7) Index keys can include a hash to scatter objects throughout the array. + + (8) The array can iterated over. The objects will not necessarily come out in + key order. + + (9) The array can be iterated over whilst it is being modified, provided the + RCU readlock is being held by the iterator. Note, however, under these + circumstances, some objects may be seen more than once. If this is a + problem, the iterator should lock against modification. Objects will not + be missed, however, unless deleted. + +(10) Objects in the array can be looked up by means of their index key. + +(11) Objects can be looked up whilst the array is being modified, provided the + RCU readlock is being held by the thread doing the look up. + +The implementation uses a tree of 16-pointer nodes internally that are indexed +on each level by nibbles from the index key in the same manner as in a radix +tree. To improve memory efficiency, shortcuts can be emplaced to skip over +what would otherwise be a series of single-occupancy nodes. Further, nodes +pack leaf object pointers into spare space in the node rather than making an +extra branch until as such time an object needs to be added to a full node. + + +============== +THE PUBLIC API +============== + +The public API can be found in . The associative array is +rooted on the following structure: + + struct assoc_array { + ... + }; + +The code is selected by enabling CONFIG_ASSOCIATIVE_ARRAY. + + +EDIT SCRIPT +----------- + +The insertion and deletion functions produce an 'edit script' that can later be +applied to effect the changes without risking ENOMEM. This retains the +preallocated metadata blocks that will be installed in the internal tree and +keeps track of the metadata blocks that will be removed from the tree when the +script is applied. + +This is also used to keep track of dead blocks and dead objects after the +script has been applied so that they can be freed later. The freeing is done +after an RCU grace period has passed - thus allowing access functions to +proceed under the RCU read lock. + +The script appears as outside of the API as a pointer of the type: + + struct assoc_array_edit; + +There are two functions for dealing with the script: + + (1) Apply an edit script. + + void assoc_array_apply_edit(struct assoc_array_edit *edit); + + This will perform the edit functions, interpolating various write barriers + to permit accesses under the RCU read lock to continue. The edit script + will then be passed to call_rcu() to free it and any dead stuff it points + to. + + (2) Cancel an edit script. + + void assoc_array_cancel_edit(struct assoc_array_edit *edit); + + This frees the edit script and all preallocated memory immediately. If + this was for insertion, the new object is _not_ released by this function, + but must rather be released by the caller. + +These functions are guaranteed not to fail. + + +OPERATIONS TABLE +---------------- + +Various functions take a table of operations: + + struct assoc_array_ops { + ... + }; + +This points to a number of methods, all of which need to be provided: + + (1) Get a chunk of index key from caller data: + + unsigned long (*get_key_chunk)(const void *index_key, int level); + + This should return a chunk of caller-supplied index key starting at the + *bit* position given by the level argument. The level argument will be a + multiple of ASSOC_ARRAY_KEY_CHUNK_SIZE and the function should return + ASSOC_ARRAY_KEY_CHUNK_SIZE bits. No error is possible. + + + (2) Get a chunk of an object's index key. + + unsigned long (*get_object_key_chunk)(const void *object, int level); + + As the previous function, but gets its data from an object in the array + rather than from a caller-supplied index key. + + + (3) See if this is the object we're looking for. + + bool (*compare_object)(const void *object, const void *index_key); + + Compare the object against an index key and return true if it matches and + false if it doesn't. + + + (4) Diff the index keys of two objects. + + int (*diff_objects)(const void *a, const void *b); + + Return the bit position at which the index keys of two objects differ or + -1 if they are the same. + + + (5) Free an object. + + void (*free_object)(void *object); + + Free the specified object. Note that this may be called an RCU grace + period after assoc_array_apply_edit() was called, so synchronize_rcu() may + be necessary on module unloading. + + +MANIPULATION FUNCTIONS +---------------------- + +There are a number of functions for manipulating an associative array: + + (1) Initialise an associative array. + + void assoc_array_init(struct assoc_array *array); + + This initialises the base structure for an associative array. It can't + fail. + + + (2) Insert/replace an object in an associative array. + + struct assoc_array_edit * + assoc_array_insert(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key, + void *object); + + This inserts the given object into the array. Note that the least + significant bit of the pointer must be zero as it's used to type-mark + pointers internally. + + If an object already exists for that key then it will be replaced with the + new object and the old one will be freed automatically. + + The index_key argument should hold index key information and is + passed to the methods in the ops table when they are called. + + This function makes no alteration to the array itself, but rather returns + an edit script that must be applied. -ENOMEM is returned in the case of + an out-of-memory error. + + The caller should lock exclusively against other modifiers of the array. + + + (3) Delete an object from an associative array. + + struct assoc_array_edit * + assoc_array_delete(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key); + + This deletes an object that matches the specified data from the array. + + The index_key argument should hold index key information and is + passed to the methods in the ops table when they are called. + + This function makes no alteration to the array itself, but rather returns + an edit script that must be applied. -ENOMEM is returned in the case of + an out-of-memory error. NULL will be returned if the specified object is + not found within the array. + + The caller should lock exclusively against other modifiers of the array. + + + (4) Delete all objects from an associative array. + + struct assoc_array_edit * + assoc_array_clear(struct assoc_array *array, + const struct assoc_array_ops *ops); + + This deletes all the objects from an associative array and leaves it + completely empty. + + This function makes no alteration to the array itself, but rather returns + an edit script that must be applied. -ENOMEM is returned in the case of + an out-of-memory error. + + The caller should lock exclusively against other modifiers of the array. + + + (5) Destroy an associative array, deleting all objects. + + void assoc_array_destroy(struct assoc_array *array, + const struct assoc_array_ops *ops); + + This destroys the contents of the associative array and leaves it + completely empty. It is not permitted for another thread to be traversing + the array under the RCU read lock at the same time as this function is + destroying it as no RCU deferral is performed on memory release - + something that would require memory to be allocated. + + The caller should lock exclusively against other modifiers and accessors + of the array. + + + (6) Garbage collect an associative array. + + int assoc_array_gc(struct assoc_array *array, + const struct assoc_array_ops *ops, + bool (*iterator)(void *object, void *iterator_data), + void *iterator_data); + + This iterates over the objects in an associative array and passes each one + to iterator(). If iterator() returns true, the object is kept. If it + returns false, the object will be freed. If the iterator() function + returns true, it must perform any appropriate refcount incrementing on the + object before returning. + + The internal tree will be packed down if possible as part of the iteration + to reduce the number of nodes in it. + + The iterator_data is passed directly to iterator() and is otherwise + ignored by the function. + + The function will return 0 if successful and -ENOMEM if there wasn't + enough memory. + + It is possible for other threads to iterate over or search the array under + the RCU read lock whilst this function is in progress. The caller should + lock exclusively against other modifiers of the array. + + +ACCESS FUNCTIONS +---------------- + +There are two functions for accessing an associative array: + + (1) Iterate over all the objects in an associative array. + + int assoc_array_iterate(const struct assoc_array *array, + int (*iterator)(const void *object, + void *iterator_data), + void *iterator_data); + + This passes each object in the array to the iterator callback function. + iterator_data is private data for that function. + + This may be used on an array at the same time as the array is being + modified, provided the RCU read lock is held. Under such circumstances, + it is possible for the iteration function to see some objects twice. If + this is a problem, then modification should be locked against. The + iteration algorithm should not, however, miss any objects. + + The function will return 0 if no objects were in the array or else it will + return the result of the last iterator function called. Iteration stops + immediately if any call to the iteration function results in a non-zero + return. + + + (2) Find an object in an associative array. + + void *assoc_array_find(const struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key); + + This walks through the array's internal tree directly to the object + specified by the index key.. + + This may be used on an array at the same time as the array is being + modified, provided the RCU read lock is held. + + The function will return the object if found (and set *_type to the object + type) or will return NULL if the object was not found. + + +INDEX KEY FORM +-------------- + +The index key can be of any form, but since the algorithms aren't told how long +the key is, it is strongly recommended that the index key includes its length +very early on before any variation due to the length would have an effect on +comparisons. + +This will cause leaves with different length keys to scatter away from each +other - and those with the same length keys to cluster together. + +It is also recommended that the index key begin with a hash of the rest of the +key to maximise scattering throughout keyspace. + +The better the scattering, the wider and lower the internal tree will be. + +Poor scattering isn't too much of a problem as there are shortcuts and nodes +can contain mixtures of leaves and metadata pointers. + +The index key is read in chunks of machine word. Each chunk is subdivided into +one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and +on a 64-bit CPU, 16 levels. Unless the scattering is really poor, it is +unlikely that more than one word of any particular index key will have to be +used. + + +================= +INTERNAL WORKINGS +================= + +The associative array data structure has an internal tree. This tree is +constructed of two types of metadata blocks: nodes and shortcuts. + +A node is an array of slots. Each slot can contain one of four things: + + (*) A NULL pointer, indicating that the slot is empty. + + (*) A pointer to an object (a leaf). + + (*) A pointer to a node at the next level. + + (*) A pointer to a shortcut. + + +BASIC INTERNAL TREE LAYOUT +-------------------------- + +Ignoring shortcuts for the moment, the nodes form a multilevel tree. The index +key space is strictly subdivided by the nodes in the tree and nodes occur on +fixed levels. For example: + + Level: 0 1 2 3 + =============== =============== =============== =============== + NODE D + NODE B NODE C +------>+---+ + +------>+---+ +------>+---+ | | 0 | + NODE A | | 0 | | | 0 | | +---+ + +---+ | +---+ | +---+ | : : + | 0 | | : : | : : | +---+ + +---+ | +---+ | +---+ | | f | + | 1 |---+ | 3 |---+ | 7 |---+ +---+ + +---+ +---+ +---+ + : : : : | 8 |---+ + +---+ +---+ +---+ | NODE E + | e |---+ | f | : : +------>+---+ + +---+ | +---+ +---+ | 0 | + | f | | | f | +---+ + +---+ | +---+ : : + | NODE F +---+ + +------>+---+ | f | + | 0 | NODE G +---+ + +---+ +------>+---+ + : : | | 0 | + +---+ | +---+ + | 6 |---+ : : + +---+ +---+ + : : | f | + +---+ +---+ + | f | + +---+ + +In the above example, there are 7 nodes (A-G), each with 16 slots (0-f). +Assuming no other meta data nodes in the tree, the key space is divided thusly: + + KEY PREFIX NODE + ========== ==== + 137* D + 138* E + 13[0-69-f]* C + 1[0-24-f]* B + e6* G + e[0-57-f]* F + [02-df]* A + +So, for instance, keys with the following example index keys will be found in +the appropriate nodes: + + INDEX KEY PREFIX NODE + =============== ======= ==== + 13694892892489 13 C + 13795289025897 137 D + 13889dde88793 138 E + 138bbb89003093 138 E + 1394879524789 12 C + 1458952489 1 B + 9431809de993ba - A + b4542910809cd - A + e5284310def98 e F + e68428974237 e6 G + e7fffcbd443 e F + f3842239082 - A + +To save memory, if a node can hold all the leaves in its portion of keyspace, +then the node will have all those leaves in it and will not have any metadata +pointers - even if some of those leaves would like to be in the same slot. + +A node can contain a heterogeneous mix of leaves and metadata pointers. +Metadata pointers must be in the slots that match their subdivisions of key +space. The leaves can be in any slot not occupied by a metadata pointer. It +is guaranteed that none of the leaves in a node will match a slot occupied by a +metadata pointer. If the metadata pointer is there, any leaf whose key matches +the metadata key prefix must be in the subtree that the metadata pointer points +to. + +In the above example list of index keys, node A will contain: + + SLOT CONTENT INDEX KEY (PREFIX) + ==== =============== ================== + 1 PTR TO NODE B 1* + any LEAF 9431809de993ba + any LEAF b4542910809cd + e PTR TO NODE F e* + any LEAF f3842239082 + +and node B: + + 3 PTR TO NODE C 13* + any LEAF 1458952489 + + +SHORTCUTS +--------- + +Shortcuts are metadata records that jump over a piece of keyspace. A shortcut +is a replacement for a series of single-occupancy nodes ascending through the +levels. Shortcuts exist to save memory and to speed up traversal. + +It is possible for the root of the tree to be a shortcut - say, for example, +the tree contains at least 17 nodes all with key prefix '1111'. The insertion +algorithm will insert a shortcut to skip over the '1111' keyspace in a single +bound and get to the fourth level where these actually become different. + + +SPLITTING AND COLLAPSING NODES +------------------------------ + +Each node has a maximum capacity of 16 leaves and metadata pointers. If the +insertion algorithm finds that it is trying to insert a 17th object into a +node, that node will be split such that at least two leaves that have a common +key segment at that level end up in a separate node rooted on that slot for +that common key segment. + +If the leaves in a full node and the leaf that is being inserted are +sufficiently similar, then a shortcut will be inserted into the tree. + +When the number of objects in the subtree rooted at a node falls to 16 or +fewer, then the subtree will be collapsed down to a single node - and this will +ripple towards the root if possible. + + +NON-RECURSIVE ITERATION +----------------------- + +Each node and shortcut contains a back pointer to its parent and the number of +slot in that parent that points to it. None-recursive iteration uses these to +proceed rootwards through the tree, going to the parent node, slot N + 1 to +make sure progress is made without the need for a stack. + +The backpointers, however, make simultaneous alteration and iteration tricky. + + +SIMULTANEOUS ALTERATION AND ITERATION +------------------------------------- + +There are a number of cases to consider: + + (1) Simple insert/replace. This involves simply replacing a NULL or old + matching leaf pointer with the pointer to the new leaf after a barrier. + The metadata blocks don't change otherwise. An old leaf won't be freed + until after the RCU grace period. + + (2) Simple delete. This involves just clearing an old matching leaf. The + metadata blocks don't change otherwise. The old leaf won't be freed until + after the RCU grace period. + + (3) Insertion replacing part of a subtree that we haven't yet entered. This + may involve replacement of part of that subtree - but that won't affect + the iteration as we won't have reached the pointer to it yet and the + ancestry blocks are not replaced (the layout of those does not change). + + (4) Insertion replacing nodes that we're actively processing. This isn't a + problem as we've passed the anchoring pointer and won't switch onto the + new layout until we follow the back pointers - at which point we've + already examined the leaves in the replaced node (we iterate over all the + leaves in a node before following any of its metadata pointers). + + We might, however, re-see some leaves that have been split out into a new + branch that's in a slot further along than we were at. + + (5) Insertion replacing nodes that we're processing a dependent branch of. + This won't affect us until we follow the back pointers. Similar to (4). + + (6) Deletion collapsing a branch under us. This doesn't affect us because the + back pointers will get us back to the parent of the new node before we + could see the new node. The entire collapsed subtree is thrown away + unchanged - and will still be rooted on the same slot, so we shouldn't + process it a second time as we'll go back to slot + 1. + +Note: + + (*) Under some circumstances, we need to simultaneously change the parent + pointer and the parent slot pointer on a node (say, for example, we + inserted another node before it and moved it up a level). We cannot do + this without locking against a read - so we have to replace that node too. + + However, when we're changing a shortcut into a node this isn't a problem + as shortcuts only have one slot and so the parent slot number isn't used + when traversing backwards over one. This means that it's okay to change + the slot number first - provided suitable barriers are used to make sure + the parent slot number is read after the back pointer. + +Obsolete blocks and leaves are freed up after an RCU grace period has passed, +so as long as anyone doing walking or iteration holds the RCU read lock, the +old superstructure should not go away on them. diff --git a/include/linux/assoc_array.h b/include/linux/assoc_array.h new file mode 100644 index 000000000000..9a193b84238a --- /dev/null +++ b/include/linux/assoc_array.h @@ -0,0 +1,92 @@ +/* Generic associative array implementation. + * + * See Documentation/assoc_array.txt for information. + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_ASSOC_ARRAY_H +#define _LINUX_ASSOC_ARRAY_H + +#ifdef CONFIG_ASSOCIATIVE_ARRAY + +#include + +#define ASSOC_ARRAY_KEY_CHUNK_SIZE BITS_PER_LONG /* Key data retrieved in chunks of this size */ + +/* + * Generic associative array. + */ +struct assoc_array { + struct assoc_array_ptr *root; /* The node at the root of the tree */ + unsigned long nr_leaves_on_tree; +}; + +/* + * Operations on objects and index keys for use by array manipulation routines. + */ +struct assoc_array_ops { + /* Method to get a chunk of an index key from caller-supplied data */ + unsigned long (*get_key_chunk)(const void *index_key, int level); + + /* Method to get a piece of an object's index key */ + unsigned long (*get_object_key_chunk)(const void *object, int level); + + /* Is this the object we're looking for? */ + bool (*compare_object)(const void *object, const void *index_key); + + /* How different are two objects, to a bit position in their keys? (or + * -1 if they're the same) + */ + int (*diff_objects)(const void *a, const void *b); + + /* Method to free an object. */ + void (*free_object)(void *object); +}; + +/* + * Access and manipulation functions. + */ +struct assoc_array_edit; + +static inline void assoc_array_init(struct assoc_array *array) +{ + array->root = NULL; + array->nr_leaves_on_tree = 0; +} + +extern int assoc_array_iterate(const struct assoc_array *array, + int (*iterator)(const void *object, + void *iterator_data), + void *iterator_data); +extern void *assoc_array_find(const struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key); +extern void assoc_array_destroy(struct assoc_array *array, + const struct assoc_array_ops *ops); +extern struct assoc_array_edit *assoc_array_insert(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key, + void *object); +extern void assoc_array_insert_set_object(struct assoc_array_edit *edit, + void *object); +extern struct assoc_array_edit *assoc_array_delete(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key); +extern struct assoc_array_edit *assoc_array_clear(struct assoc_array *array, + const struct assoc_array_ops *ops); +extern void assoc_array_apply_edit(struct assoc_array_edit *edit); +extern void assoc_array_cancel_edit(struct assoc_array_edit *edit); +extern int assoc_array_gc(struct assoc_array *array, + const struct assoc_array_ops *ops, + bool (*iterator)(void *object, void *iterator_data), + void *iterator_data); + +#endif /* CONFIG_ASSOCIATIVE_ARRAY */ +#endif /* _LINUX_ASSOC_ARRAY_H */ diff --git a/include/linux/assoc_array_priv.h b/include/linux/assoc_array_priv.h new file mode 100644 index 000000000000..711275e6681c --- /dev/null +++ b/include/linux/assoc_array_priv.h @@ -0,0 +1,182 @@ +/* Private definitions for the generic associative array implementation. + * + * See Documentation/assoc_array.txt for information. + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_ASSOC_ARRAY_PRIV_H +#define _LINUX_ASSOC_ARRAY_PRIV_H + +#ifdef CONFIG_ASSOCIATIVE_ARRAY + +#include + +#define ASSOC_ARRAY_FAN_OUT 16 /* Number of slots per node */ +#define ASSOC_ARRAY_FAN_MASK (ASSOC_ARRAY_FAN_OUT - 1) +#define ASSOC_ARRAY_LEVEL_STEP (ilog2(ASSOC_ARRAY_FAN_OUT)) +#define ASSOC_ARRAY_LEVEL_STEP_MASK (ASSOC_ARRAY_LEVEL_STEP - 1) +#define ASSOC_ARRAY_KEY_CHUNK_MASK (ASSOC_ARRAY_KEY_CHUNK_SIZE - 1) +#define ASSOC_ARRAY_KEY_CHUNK_SHIFT (ilog2(BITS_PER_LONG)) + +/* + * Undefined type representing a pointer with type information in the bottom + * two bits. + */ +struct assoc_array_ptr; + +/* + * An N-way node in the tree. + * + * Each slot contains one of four things: + * + * (1) Nothing (NULL). + * + * (2) A leaf object (pointer types 0). + * + * (3) A next-level node (pointer type 1, subtype 0). + * + * (4) A shortcut (pointer type 1, subtype 1). + * + * The tree is optimised for search-by-ID, but permits reasonable iteration + * also. + * + * The tree is navigated by constructing an index key consisting of an array of + * segments, where each segment is ilog2(ASSOC_ARRAY_FAN_OUT) bits in size. + * + * The segments correspond to levels of the tree (the first segment is used at + * level 0, the second at level 1, etc.). + */ +struct assoc_array_node { + struct assoc_array_ptr *back_pointer; + u8 parent_slot; + struct assoc_array_ptr *slots[ASSOC_ARRAY_FAN_OUT]; + unsigned long nr_leaves_on_branch; +}; + +/* + * A shortcut through the index space out to where a collection of nodes/leaves + * with the same IDs live. + */ +struct assoc_array_shortcut { + struct assoc_array_ptr *back_pointer; + int parent_slot; + int skip_to_level; + struct assoc_array_ptr *next_node; + unsigned long index_key[]; +}; + +/* + * Preallocation cache. + */ +struct assoc_array_edit { + struct rcu_head rcu; + struct assoc_array *array; + const struct assoc_array_ops *ops; + const struct assoc_array_ops *ops_for_excised_subtree; + struct assoc_array_ptr *leaf; + struct assoc_array_ptr **leaf_p; + struct assoc_array_ptr *dead_leaf; + struct assoc_array_ptr *new_meta[3]; + struct assoc_array_ptr *excised_meta[1]; + struct assoc_array_ptr *excised_subtree; + struct assoc_array_ptr **set_backpointers[ASSOC_ARRAY_FAN_OUT]; + struct assoc_array_ptr *set_backpointers_to; + struct assoc_array_node *adjust_count_on; + long adjust_count_by; + struct { + struct assoc_array_ptr **ptr; + struct assoc_array_ptr *to; + } set[2]; + struct { + u8 *p; + u8 to; + } set_parent_slot[1]; + u8 segment_cache[ASSOC_ARRAY_FAN_OUT + 1]; +}; + +/* + * Internal tree member pointers are marked in the bottom one or two bits to + * indicate what type they are so that we don't have to look behind every + * pointer to see what it points to. + * + * We provide functions to test type annotations and to create and translate + * the annotated pointers. + */ +#define ASSOC_ARRAY_PTR_TYPE_MASK 0x1UL +#define ASSOC_ARRAY_PTR_LEAF_TYPE 0x0UL /* Points to leaf (or nowhere) */ +#define ASSOC_ARRAY_PTR_META_TYPE 0x1UL /* Points to node or shortcut */ +#define ASSOC_ARRAY_PTR_SUBTYPE_MASK 0x2UL +#define ASSOC_ARRAY_PTR_NODE_SUBTYPE 0x0UL +#define ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE 0x2UL + +static inline bool assoc_array_ptr_is_meta(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & ASSOC_ARRAY_PTR_TYPE_MASK; +} +static inline bool assoc_array_ptr_is_leaf(const struct assoc_array_ptr *x) +{ + return !assoc_array_ptr_is_meta(x); +} +static inline bool assoc_array_ptr_is_shortcut(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & ASSOC_ARRAY_PTR_SUBTYPE_MASK; +} +static inline bool assoc_array_ptr_is_node(const struct assoc_array_ptr *x) +{ + return !assoc_array_ptr_is_shortcut(x); +} + +static inline void *assoc_array_ptr_to_leaf(const struct assoc_array_ptr *x) +{ + return (void *)((unsigned long)x & ~ASSOC_ARRAY_PTR_TYPE_MASK); +} + +static inline +unsigned long __assoc_array_ptr_to_meta(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & + ~(ASSOC_ARRAY_PTR_SUBTYPE_MASK | ASSOC_ARRAY_PTR_TYPE_MASK); +} +static inline +struct assoc_array_node *assoc_array_ptr_to_node(const struct assoc_array_ptr *x) +{ + return (struct assoc_array_node *)__assoc_array_ptr_to_meta(x); +} +static inline +struct assoc_array_shortcut *assoc_array_ptr_to_shortcut(const struct assoc_array_ptr *x) +{ + return (struct assoc_array_shortcut *)__assoc_array_ptr_to_meta(x); +} + +static inline +struct assoc_array_ptr *__assoc_array_x_to_ptr(const void *p, unsigned long t) +{ + return (struct assoc_array_ptr *)((unsigned long)p | t); +} +static inline +struct assoc_array_ptr *assoc_array_leaf_to_ptr(const void *p) +{ + return __assoc_array_x_to_ptr(p, ASSOC_ARRAY_PTR_LEAF_TYPE); +} +static inline +struct assoc_array_ptr *assoc_array_node_to_ptr(const struct assoc_array_node *p) +{ + return __assoc_array_x_to_ptr( + p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_NODE_SUBTYPE); +} +static inline +struct assoc_array_ptr *assoc_array_shortcut_to_ptr(const struct assoc_array_shortcut *p) +{ + return __assoc_array_x_to_ptr( + p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE); +} + +#endif /* CONFIG_ASSOCIATIVE_ARRAY */ +#endif /* _LINUX_ASSOC_ARRAY_PRIV_H */ diff --git a/lib/Kconfig b/lib/Kconfig index b3c8be0da17f..3cb879b1f282 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -322,6 +322,20 @@ config TEXTSEARCH_FSM config BTREE boolean +config ASSOCIATIVE_ARRAY + bool + help + Generic associative array. Can be searched and iterated over whilst + it is being modified. It is also reasonably quick to search and + modify. The algorithms are non-recursive, and the trees are highly + capacious. + + See: + + Documentation/assoc_array.txt + + for more information. + config HAS_IOMEM boolean depends on !NO_IOMEM diff --git a/lib/Makefile b/lib/Makefile index f3bb2cb98adf..1e806477e472 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -51,6 +51,7 @@ CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_BTREE) += btree.o +obj-$(CONFIG_ASSOCIATIVE_ARRAY) += assoc_array.o obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o obj-$(CONFIG_DEBUG_LIST) += list_debug.o obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o diff --git a/lib/assoc_array.c b/lib/assoc_array.c new file mode 100644 index 000000000000..a0952818f938 --- /dev/null +++ b/lib/assoc_array.c @@ -0,0 +1,1745 @@ +/* Generic associative array implementation. + * + * See Documentation/assoc_array.txt for information. + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +//#define DEBUG +#include +#include + +/* + * Iterate over an associative array. The caller must hold the RCU read lock + * or better. + */ +static int assoc_array_subtree_iterate(const struct assoc_array_ptr *root, + const struct assoc_array_ptr *stop, + int (*iterator)(const void *leaf, + void *iterator_data), + void *iterator_data) +{ + const struct assoc_array_shortcut *shortcut; + const struct assoc_array_node *node; + const struct assoc_array_ptr *cursor, *ptr, *parent; + unsigned long has_meta; + int slot, ret; + + cursor = root; + +begin_node: + if (assoc_array_ptr_is_shortcut(cursor)) { + /* Descend through a shortcut */ + shortcut = assoc_array_ptr_to_shortcut(cursor); + smp_read_barrier_depends(); + cursor = ACCESS_ONCE(shortcut->next_node); + } + + node = assoc_array_ptr_to_node(cursor); + smp_read_barrier_depends(); + slot = 0; + + /* We perform two passes of each node. + * + * The first pass does all the leaves in this node. This means we + * don't miss any leaves if the node is split up by insertion whilst + * we're iterating over the branches rooted here (we may, however, see + * some leaves twice). + */ + has_meta = 0; + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = ACCESS_ONCE(node->slots[slot]); + has_meta |= (unsigned long)ptr; + if (ptr && assoc_array_ptr_is_leaf(ptr)) { + /* We need a barrier between the read of the pointer + * and dereferencing the pointer - but only if we are + * actually going to dereference it. + */ + smp_read_barrier_depends(); + + /* Invoke the callback */ + ret = iterator(assoc_array_ptr_to_leaf(ptr), + iterator_data); + if (ret) + return ret; + } + } + + /* The second pass attends to all the metadata pointers. If we follow + * one of these we may find that we don't come back here, but rather go + * back to a replacement node with the leaves in a different layout. + * + * We are guaranteed to make progress, however, as the slot number for + * a particular portion of the key space cannot change - and we + * continue at the back pointer + 1. + */ + if (!(has_meta & ASSOC_ARRAY_PTR_META_TYPE)) + goto finished_node; + slot = 0; + +continue_node: + node = assoc_array_ptr_to_node(cursor); + smp_read_barrier_depends(); + + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = ACCESS_ONCE(node->slots[slot]); + if (assoc_array_ptr_is_meta(ptr)) { + cursor = ptr; + goto begin_node; + } + } + +finished_node: + /* Move up to the parent (may need to skip back over a shortcut) */ + parent = ACCESS_ONCE(node->back_pointer); + slot = node->parent_slot; + if (parent == stop) + return 0; + + if (assoc_array_ptr_is_shortcut(parent)) { + shortcut = assoc_array_ptr_to_shortcut(parent); + smp_read_barrier_depends(); + cursor = parent; + parent = ACCESS_ONCE(shortcut->back_pointer); + slot = shortcut->parent_slot; + if (parent == stop) + return 0; + } + + /* Ascend to next slot in parent node */ + cursor = parent; + slot++; + goto continue_node; +} + +/** + * assoc_array_iterate - Pass all objects in the array to a callback + * @array: The array to iterate over. + * @iterator: The callback function. + * @iterator_data: Private data for the callback function. + * + * Iterate over all the objects in an associative array. Each one will be + * presented to the iterator function. + * + * If the array is being modified concurrently with the iteration then it is + * possible that some objects in the array will be passed to the iterator + * callback more than once - though every object should be passed at least + * once. If this is undesirable then the caller must lock against modification + * for the duration of this function. + * + * The function will return 0 if no objects were in the array or else it will + * return the result of the last iterator function called. Iteration stops + * immediately if any call to the iteration function results in a non-zero + * return. + * + * The caller should hold the RCU read lock or better if concurrent + * modification is possible. + */ +int assoc_array_iterate(const struct assoc_array *array, + int (*iterator)(const void *object, + void *iterator_data), + void *iterator_data) +{ + struct assoc_array_ptr *root = ACCESS_ONCE(array->root); + + if (!root) + return 0; + return assoc_array_subtree_iterate(root, NULL, iterator, iterator_data); +} + +enum assoc_array_walk_status { + assoc_array_walk_tree_empty, + assoc_array_walk_found_terminal_node, + assoc_array_walk_found_wrong_shortcut, +} status; + +struct assoc_array_walk_result { + struct { + struct assoc_array_node *node; /* Node in which leaf might be found */ + int level; + int slot; + } terminal_node; + struct { + struct assoc_array_shortcut *shortcut; + int level; + int sc_level; + unsigned long sc_segments; + unsigned long dissimilarity; + } wrong_shortcut; +}; + +/* + * Navigate through the internal tree looking for the closest node to the key. + */ +static enum assoc_array_walk_status +assoc_array_walk(const struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key, + struct assoc_array_walk_result *result) +{ + struct assoc_array_shortcut *shortcut; + struct assoc_array_node *node; + struct assoc_array_ptr *cursor, *ptr; + unsigned long sc_segments, dissimilarity; + unsigned long segments; + int level, sc_level, next_sc_level; + int slot; + + pr_devel("-->%s()\n", __func__); + + cursor = ACCESS_ONCE(array->root); + if (!cursor) + return assoc_array_walk_tree_empty; + + level = 0; + + /* Use segments from the key for the new leaf to navigate through the + * internal tree, skipping through nodes and shortcuts that are on + * route to the destination. Eventually we'll come to a slot that is + * either empty or contains a leaf at which point we've found a node in + * which the leaf we're looking for might be found or into which it + * should be inserted. + */ +jumped: + segments = ops->get_key_chunk(index_key, level); + pr_devel("segments[%d]: %lx\n", level, segments); + + if (assoc_array_ptr_is_shortcut(cursor)) + goto follow_shortcut; + +consider_node: + node = assoc_array_ptr_to_node(cursor); + smp_read_barrier_depends(); + + slot = segments >> (level & ASSOC_ARRAY_KEY_CHUNK_MASK); + slot &= ASSOC_ARRAY_FAN_MASK; + ptr = ACCESS_ONCE(node->slots[slot]); + + pr_devel("consider slot %x [ix=%d type=%lu]\n", + slot, level, (unsigned long)ptr & 3); + + if (!assoc_array_ptr_is_meta(ptr)) { + /* The node doesn't have a node/shortcut pointer in the slot + * corresponding to the index key that we have to follow. + */ + result->terminal_node.node = node; + result->terminal_node.level = level; + result->terminal_node.slot = slot; + pr_devel("<--%s() = terminal_node\n", __func__); + return assoc_array_walk_found_terminal_node; + } + + if (assoc_array_ptr_is_node(ptr)) { + /* There is a pointer to a node in the slot corresponding to + * this index key segment, so we need to follow it. + */ + cursor = ptr; + level += ASSOC_ARRAY_LEVEL_STEP; + if ((level & ASSOC_ARRAY_KEY_CHUNK_MASK) != 0) + goto consider_node; + goto jumped; + } + + /* There is a shortcut in the slot corresponding to the index key + * segment. We follow the shortcut if its partial index key matches + * this leaf's. Otherwise we need to split the shortcut. + */ + cursor = ptr; +follow_shortcut: + shortcut = assoc_array_ptr_to_shortcut(cursor); + smp_read_barrier_depends(); + pr_devel("shortcut to %d\n", shortcut->skip_to_level); + sc_level = level + ASSOC_ARRAY_LEVEL_STEP; + BUG_ON(sc_level > shortcut->skip_to_level); + + do { + /* Check the leaf against the shortcut's index key a word at a + * time, trimming the final word (the shortcut stores the index + * key completely from the root to the shortcut's target). + */ + if ((sc_level & ASSOC_ARRAY_KEY_CHUNK_MASK) == 0) + segments = ops->get_key_chunk(index_key, sc_level); + + sc_segments = shortcut->index_key[sc_level >> ASSOC_ARRAY_KEY_CHUNK_SHIFT]; + dissimilarity = segments ^ sc_segments; + + if (round_up(sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE) > shortcut->skip_to_level) { + /* Trim segments that are beyond the shortcut */ + int shift = shortcut->skip_to_level & ASSOC_ARRAY_KEY_CHUNK_MASK; + dissimilarity &= ~(ULONG_MAX << shift); + next_sc_level = shortcut->skip_to_level; + } else { + next_sc_level = sc_level + ASSOC_ARRAY_KEY_CHUNK_SIZE; + next_sc_level = round_down(next_sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); + } + + if (dissimilarity != 0) { + /* This shortcut points elsewhere */ + result->wrong_shortcut.shortcut = shortcut; + result->wrong_shortcut.level = level; + result->wrong_shortcut.sc_level = sc_level; + result->wrong_shortcut.sc_segments = sc_segments; + result->wrong_shortcut.dissimilarity = dissimilarity; + return assoc_array_walk_found_wrong_shortcut; + } + + sc_level = next_sc_level; + } while (sc_level < shortcut->skip_to_level); + + /* The shortcut matches the leaf's index to this point. */ + cursor = ACCESS_ONCE(shortcut->next_node); + if (((level ^ sc_level) & ~ASSOC_ARRAY_KEY_CHUNK_MASK) != 0) { + level = sc_level; + goto jumped; + } else { + level = sc_level; + goto consider_node; + } +} + +/** + * assoc_array_find - Find an object by index key + * @array: The associative array to search. + * @ops: The operations to use. + * @index_key: The key to the object. + * + * Find an object in an associative array by walking through the internal tree + * to the node that should contain the object and then searching the leaves + * there. NULL is returned if the requested object was not found in the array. + * + * The caller must hold the RCU read lock or better. + */ +void *assoc_array_find(const struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key) +{ + struct assoc_array_walk_result result; + const struct assoc_array_node *node; + const struct assoc_array_ptr *ptr; + const void *leaf; + int slot; + + if (assoc_array_walk(array, ops, index_key, &result) != + assoc_array_walk_found_terminal_node) + return NULL; + + node = result.terminal_node.node; + smp_read_barrier_depends(); + + /* If the target key is available to us, it's has to be pointed to by + * the terminal node. + */ + for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = ACCESS_ONCE(node->slots[slot]); + if (ptr && assoc_array_ptr_is_leaf(ptr)) { + /* We need a barrier between the read of the pointer + * and dereferencing the pointer - but only if we are + * actually going to dereference it. + */ + leaf = assoc_array_ptr_to_leaf(ptr); + smp_read_barrier_depends(); + if (ops->compare_object(leaf, index_key)) + return (void *)leaf; + } + } + + return NULL; +} + +/* + * Destructively iterate over an associative array. The caller must prevent + * other simultaneous accesses. + */ +static void assoc_array_destroy_subtree(struct assoc_array_ptr *root, + const struct assoc_array_ops *ops) +{ + struct assoc_array_shortcut *shortcut; + struct assoc_array_node *node; + struct assoc_array_ptr *cursor, *parent = NULL; + int slot = -1; + + pr_devel("-->%s()\n", __func__); + + cursor = root; + if (!cursor) { + pr_devel("empty\n"); + return; + } + +move_to_meta: + if (assoc_array_ptr_is_shortcut(cursor)) { + /* Descend through a shortcut */ + pr_devel("[%d] shortcut\n", slot); + BUG_ON(!assoc_array_ptr_is_shortcut(cursor)); + shortcut = assoc_array_ptr_to_shortcut(cursor); + BUG_ON(shortcut->back_pointer != parent); + BUG_ON(slot != -1 && shortcut->parent_slot != slot); + parent = cursor; + cursor = shortcut->next_node; + slot = -1; + BUG_ON(!assoc_array_ptr_is_node(cursor)); + } + + pr_devel("[%d] node\n", slot); + node = assoc_array_ptr_to_node(cursor); + BUG_ON(node->back_pointer != parent); + BUG_ON(slot != -1 && node->parent_slot != slot); + slot = 0; + +continue_node: + pr_devel("Node %p [back=%p]\n", node, node->back_pointer); + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + struct assoc_array_ptr *ptr = node->slots[slot]; + if (!ptr) + continue; + if (assoc_array_ptr_is_meta(ptr)) { + parent = cursor; + cursor = ptr; + goto move_to_meta; + } + + if (ops) { + pr_devel("[%d] free leaf\n", slot); + ops->free_object(assoc_array_ptr_to_leaf(ptr)); + } + } + + parent = node->back_pointer; + slot = node->parent_slot; + pr_devel("free node\n"); + kfree(node); + if (!parent) + return; /* Done */ + + /* Move back up to the parent (may need to free a shortcut on + * the way up) */ + if (assoc_array_ptr_is_shortcut(parent)) { + shortcut = assoc_array_ptr_to_shortcut(parent); + BUG_ON(shortcut->next_node != cursor); + cursor = parent; + parent = shortcut->back_pointer; + slot = shortcut->parent_slot; + pr_devel("free shortcut\n"); + kfree(shortcut); + if (!parent) + return; + + BUG_ON(!assoc_array_ptr_is_node(parent)); + } + + /* Ascend to next slot in parent node */ + pr_devel("ascend to %p[%d]\n", parent, slot); + cursor = parent; + node = assoc_array_ptr_to_node(cursor); + slot++; + goto continue_node; +} + +/** + * assoc_array_destroy - Destroy an associative array + * @array: The array to destroy. + * @ops: The operations to use. + * + * Discard all metadata and free all objects in an associative array. The + * array will be empty and ready to use again upon completion. This function + * cannot fail. + * + * The caller must prevent all other accesses whilst this takes place as no + * attempt is made to adjust pointers gracefully to permit RCU readlock-holding + * accesses to continue. On the other hand, no memory allocation is required. + */ +void assoc_array_destroy(struct assoc_array *array, + const struct assoc_array_ops *ops) +{ + assoc_array_destroy_subtree(array->root, ops); + array->root = NULL; +} + +/* + * Handle insertion into an empty tree. + */ +static bool assoc_array_insert_in_empty_tree(struct assoc_array_edit *edit) +{ + struct assoc_array_node *new_n0; + + pr_devel("-->%s()\n", __func__); + + new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n0) + return false; + + edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); + edit->leaf_p = &new_n0->slots[0]; + edit->adjust_count_on = new_n0; + edit->set[0].ptr = &edit->array->root; + edit->set[0].to = assoc_array_node_to_ptr(new_n0); + + pr_devel("<--%s() = ok [no root]\n", __func__); + return true; +} + +/* + * Handle insertion into a terminal node. + */ +static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit, + const struct assoc_array_ops *ops, + const void *index_key, + struct assoc_array_walk_result *result) +{ + struct assoc_array_shortcut *shortcut, *new_s0; + struct assoc_array_node *node, *new_n0, *new_n1, *side; + struct assoc_array_ptr *ptr; + unsigned long dissimilarity, base_seg, blank; + size_t keylen; + bool have_meta; + int level, diff; + int slot, next_slot, free_slot, i, j; + + node = result->terminal_node.node; + level = result->terminal_node.level; + edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = result->terminal_node.slot; + + pr_devel("-->%s()\n", __func__); + + /* We arrived at a node which doesn't have an onward node or shortcut + * pointer that we have to follow. This means that (a) the leaf we + * want must go here (either by insertion or replacement) or (b) we + * need to split this node and insert in one of the fragments. + */ + free_slot = -1; + + /* Firstly, we have to check the leaves in this node to see if there's + * a matching one we should replace in place. + */ + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + ptr = node->slots[i]; + if (!ptr) { + free_slot = i; + continue; + } + if (ops->compare_object(assoc_array_ptr_to_leaf(ptr), index_key)) { + pr_devel("replace in slot %d\n", i); + edit->leaf_p = &node->slots[i]; + edit->dead_leaf = node->slots[i]; + pr_devel("<--%s() = ok [replace]\n", __func__); + return true; + } + } + + /* If there is a free slot in this node then we can just insert the + * leaf here. + */ + if (free_slot >= 0) { + pr_devel("insert in free slot %d\n", free_slot); + edit->leaf_p = &node->slots[free_slot]; + edit->adjust_count_on = node; + pr_devel("<--%s() = ok [insert]\n", __func__); + return true; + } + + /* The node has no spare slots - so we're either going to have to split + * it or insert another node before it. + * + * Whatever, we're going to need at least two new nodes - so allocate + * those now. We may also need a new shortcut, but we deal with that + * when we need it. + */ + new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n0) + return false; + edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); + new_n1 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n1) + return false; + edit->new_meta[1] = assoc_array_node_to_ptr(new_n1); + + /* We need to find out how similar the leaves are. */ + pr_devel("no spare slots\n"); + have_meta = false; + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + ptr = node->slots[i]; + if (assoc_array_ptr_is_meta(ptr)) { + edit->segment_cache[i] = 0xff; + have_meta = true; + continue; + } + base_seg = ops->get_object_key_chunk( + assoc_array_ptr_to_leaf(ptr), level); + base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; + edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK; + } + + if (have_meta) { + pr_devel("have meta\n"); + goto split_node; + } + + /* The node contains only leaves */ + dissimilarity = 0; + base_seg = edit->segment_cache[0]; + for (i = 1; i < ASSOC_ARRAY_FAN_OUT; i++) + dissimilarity |= edit->segment_cache[i] ^ base_seg; + + pr_devel("only leaves; dissimilarity=%lx\n", dissimilarity); + + if ((dissimilarity & ASSOC_ARRAY_FAN_MASK) == 0) { + /* The old leaves all cluster in the same slot. We will need + * to insert a shortcut if the new node wants to cluster with them. + */ + if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0) + goto all_leaves_cluster_together; + + /* Otherwise we can just insert a new node ahead of the old + * one. + */ + goto present_leaves_cluster_but_not_new_leaf; + } + +split_node: + pr_devel("split node\n"); + + /* We need to split the current node; we know that the node doesn't + * simply contain a full set of leaves that cluster together (it + * contains meta pointers and/or non-clustering leaves). + * + * We need to expel at least two leaves out of a set consisting of the + * leaves in the node and the new leaf. + * + * We need a new node (n0) to replace the current one and a new node to + * take the expelled nodes (n1). + */ + edit->set[0].to = assoc_array_node_to_ptr(new_n0); + new_n0->back_pointer = node->back_pointer; + new_n0->parent_slot = node->parent_slot; + new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); + new_n1->parent_slot = -1; /* Need to calculate this */ + +do_split_node: + pr_devel("do_split_node\n"); + + new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; + new_n1->nr_leaves_on_branch = 0; + + /* Begin by finding two matching leaves. There have to be at least two + * that match - even if there are meta pointers - because any leaf that + * would match a slot with a meta pointer in it must be somewhere + * behind that meta pointer and cannot be here. Further, given N + * remaining leaf slots, we now have N+1 leaves to go in them. + */ + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + slot = edit->segment_cache[i]; + if (slot != 0xff) + for (j = i + 1; j < ASSOC_ARRAY_FAN_OUT + 1; j++) + if (edit->segment_cache[j] == slot) + goto found_slot_for_multiple_occupancy; + } +found_slot_for_multiple_occupancy: + pr_devel("same slot: %x %x [%02x]\n", i, j, slot); + BUG_ON(i >= ASSOC_ARRAY_FAN_OUT); + BUG_ON(j >= ASSOC_ARRAY_FAN_OUT + 1); + BUG_ON(slot >= ASSOC_ARRAY_FAN_OUT); + + new_n1->parent_slot = slot; + + /* Metadata pointers cannot change slot */ + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) + if (assoc_array_ptr_is_meta(node->slots[i])) + new_n0->slots[i] = node->slots[i]; + else + new_n0->slots[i] = NULL; + BUG_ON(new_n0->slots[slot] != NULL); + new_n0->slots[slot] = assoc_array_node_to_ptr(new_n1); + + /* Filter the leaf pointers between the new nodes */ + free_slot = -1; + next_slot = 0; + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + if (assoc_array_ptr_is_meta(node->slots[i])) + continue; + if (edit->segment_cache[i] == slot) { + new_n1->slots[next_slot++] = node->slots[i]; + new_n1->nr_leaves_on_branch++; + } else { + do { + free_slot++; + } while (new_n0->slots[free_slot] != NULL); + new_n0->slots[free_slot] = node->slots[i]; + } + } + + pr_devel("filtered: f=%x n=%x\n", free_slot, next_slot); + + if (edit->segment_cache[ASSOC_ARRAY_FAN_OUT] != slot) { + do { + free_slot++; + } while (new_n0->slots[free_slot] != NULL); + edit->leaf_p = &new_n0->slots[free_slot]; + edit->adjust_count_on = new_n0; + } else { + edit->leaf_p = &new_n1->slots[next_slot++]; + edit->adjust_count_on = new_n1; + } + + BUG_ON(next_slot <= 1); + + edit->set_backpointers_to = assoc_array_node_to_ptr(new_n0); + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + if (edit->segment_cache[i] == 0xff) { + ptr = node->slots[i]; + BUG_ON(assoc_array_ptr_is_leaf(ptr)); + if (assoc_array_ptr_is_node(ptr)) { + side = assoc_array_ptr_to_node(ptr); + edit->set_backpointers[i] = &side->back_pointer; + } else { + shortcut = assoc_array_ptr_to_shortcut(ptr); + edit->set_backpointers[i] = &shortcut->back_pointer; + } + } + } + + ptr = node->back_pointer; + if (!ptr) + edit->set[0].ptr = &edit->array->root; + else if (assoc_array_ptr_is_node(ptr)) + edit->set[0].ptr = &assoc_array_ptr_to_node(ptr)->slots[node->parent_slot]; + else + edit->set[0].ptr = &assoc_array_ptr_to_shortcut(ptr)->next_node; + edit->excised_meta[0] = assoc_array_node_to_ptr(node); + pr_devel("<--%s() = ok [split node]\n", __func__); + return true; + +present_leaves_cluster_but_not_new_leaf: + /* All the old leaves cluster in the same slot, but the new leaf wants + * to go into a different slot, so we create a new node to hold the new + * leaf and a pointer to a new node holding all the old leaves. + */ + pr_devel("present leaves cluster but not new leaf\n"); + + new_n0->back_pointer = node->back_pointer; + new_n0->parent_slot = node->parent_slot; + new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; + new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); + new_n1->parent_slot = edit->segment_cache[0]; + new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch; + edit->adjust_count_on = new_n0; + + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) + new_n1->slots[i] = node->slots[i]; + + new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0); + edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]]; + + edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot]; + edit->set[0].to = assoc_array_node_to_ptr(new_n0); + edit->excised_meta[0] = assoc_array_node_to_ptr(node); + pr_devel("<--%s() = ok [insert node before]\n", __func__); + return true; + +all_leaves_cluster_together: + /* All the leaves, new and old, want to cluster together in this node + * in the same slot, so we have to replace this node with a shortcut to + * skip over the identical parts of the key and then place a pair of + * nodes, one inside the other, at the end of the shortcut and + * distribute the keys between them. + * + * Firstly we need to work out where the leaves start diverging as a + * bit position into their keys so that we know how big the shortcut + * needs to be. + * + * We only need to make a single pass of N of the N+1 leaves because if + * any keys differ between themselves at bit X then at least one of + * them must also differ with the base key at bit X or before. + */ + pr_devel("all leaves cluster together\n"); + diff = INT_MAX; + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + int x = ops->diff_objects(assoc_array_ptr_to_leaf(edit->leaf), + assoc_array_ptr_to_leaf(node->slots[i])); + if (x < diff) { + BUG_ON(x < 0); + diff = x; + } + } + BUG_ON(diff == INT_MAX); + BUG_ON(diff < level + ASSOC_ARRAY_LEVEL_STEP); + + keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE); + keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; + + new_s0 = kzalloc(sizeof(struct assoc_array_shortcut) + + keylen * sizeof(unsigned long), GFP_KERNEL); + if (!new_s0) + return false; + edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s0); + + edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0); + new_s0->back_pointer = node->back_pointer; + new_s0->parent_slot = node->parent_slot; + new_s0->next_node = assoc_array_node_to_ptr(new_n0); + new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0); + new_n0->parent_slot = 0; + new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); + new_n1->parent_slot = -1; /* Need to calculate this */ + + new_s0->skip_to_level = level = diff & ~ASSOC_ARRAY_LEVEL_STEP_MASK; + pr_devel("skip_to_level = %d [diff %d]\n", level, diff); + BUG_ON(level <= 0); + + for (i = 0; i < keylen; i++) + new_s0->index_key[i] = + ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE); + + blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK); + pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank); + new_s0->index_key[keylen - 1] &= ~blank; + + /* This now reduces to a node splitting exercise for which we'll need + * to regenerate the disparity table. + */ + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + ptr = node->slots[i]; + base_seg = ops->get_object_key_chunk(assoc_array_ptr_to_leaf(ptr), + level); + base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; + edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK; + } + + base_seg = ops->get_key_chunk(index_key, level); + base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; + edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = base_seg & ASSOC_ARRAY_FAN_MASK; + goto do_split_node; +} + +/* + * Handle insertion into the middle of a shortcut. + */ +static bool assoc_array_insert_mid_shortcut(struct assoc_array_edit *edit, + const struct assoc_array_ops *ops, + struct assoc_array_walk_result *result) +{ + struct assoc_array_shortcut *shortcut, *new_s0, *new_s1; + struct assoc_array_node *node, *new_n0, *side; + unsigned long sc_segments, dissimilarity, blank; + size_t keylen; + int level, sc_level, diff; + int sc_slot; + + shortcut = result->wrong_shortcut.shortcut; + level = result->wrong_shortcut.level; + sc_level = result->wrong_shortcut.sc_level; + sc_segments = result->wrong_shortcut.sc_segments; + dissimilarity = result->wrong_shortcut.dissimilarity; + + pr_devel("-->%s(ix=%d dis=%lx scix=%d)\n", + __func__, level, dissimilarity, sc_level); + + /* We need to split a shortcut and insert a node between the two + * pieces. Zero-length pieces will be dispensed with entirely. + * + * First of all, we need to find out in which level the first + * difference was. + */ + diff = __ffs(dissimilarity); + diff &= ~ASSOC_ARRAY_LEVEL_STEP_MASK; + diff += sc_level & ~ASSOC_ARRAY_KEY_CHUNK_MASK; + pr_devel("diff=%d\n", diff); + + if (!shortcut->back_pointer) { + edit->set[0].ptr = &edit->array->root; + } else if (assoc_array_ptr_is_node(shortcut->back_pointer)) { + node = assoc_array_ptr_to_node(shortcut->back_pointer); + edit->set[0].ptr = &node->slots[shortcut->parent_slot]; + } else { + BUG(); + } + + edit->excised_meta[0] = assoc_array_shortcut_to_ptr(shortcut); + + /* Create a new node now since we're going to need it anyway */ + new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n0) + return false; + edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); + edit->adjust_count_on = new_n0; + + /* Insert a new shortcut before the new node if this segment isn't of + * zero length - otherwise we just connect the new node directly to the + * parent. + */ + level += ASSOC_ARRAY_LEVEL_STEP; + if (diff > level) { + pr_devel("pre-shortcut %d...%d\n", level, diff); + keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE); + keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; + + new_s0 = kzalloc(sizeof(struct assoc_array_shortcut) + + keylen * sizeof(unsigned long), GFP_KERNEL); + if (!new_s0) + return false; + edit->new_meta[1] = assoc_array_shortcut_to_ptr(new_s0); + edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0); + new_s0->back_pointer = shortcut->back_pointer; + new_s0->parent_slot = shortcut->parent_slot; + new_s0->next_node = assoc_array_node_to_ptr(new_n0); + new_s0->skip_to_level = diff; + + new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0); + new_n0->parent_slot = 0; + + memcpy(new_s0->index_key, shortcut->index_key, + keylen * sizeof(unsigned long)); + + blank = ULONG_MAX << (diff & ASSOC_ARRAY_KEY_CHUNK_MASK); + pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, diff, blank); + new_s0->index_key[keylen - 1] &= ~blank; + } else { + pr_devel("no pre-shortcut\n"); + edit->set[0].to = assoc_array_node_to_ptr(new_n0); + new_n0->back_pointer = shortcut->back_pointer; + new_n0->parent_slot = shortcut->parent_slot; + } + + side = assoc_array_ptr_to_node(shortcut->next_node); + new_n0->nr_leaves_on_branch = side->nr_leaves_on_branch; + + /* We need to know which slot in the new node is going to take a + * metadata pointer. + */ + sc_slot = sc_segments >> (diff & ASSOC_ARRAY_KEY_CHUNK_MASK); + sc_slot &= ASSOC_ARRAY_FAN_MASK; + + pr_devel("new slot %lx >> %d -> %d\n", + sc_segments, diff & ASSOC_ARRAY_KEY_CHUNK_MASK, sc_slot); + + /* Determine whether we need to follow the new node with a replacement + * for the current shortcut. We could in theory reuse the current + * shortcut if its parent slot number doesn't change - but that's a + * 1-in-16 chance so not worth expending the code upon. + */ + level = diff + ASSOC_ARRAY_LEVEL_STEP; + if (level < shortcut->skip_to_level) { + pr_devel("post-shortcut %d...%d\n", level, shortcut->skip_to_level); + keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); + keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; + + new_s1 = kzalloc(sizeof(struct assoc_array_shortcut) + + keylen * sizeof(unsigned long), GFP_KERNEL); + if (!new_s1) + return false; + edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s1); + + new_s1->back_pointer = assoc_array_node_to_ptr(new_n0); + new_s1->parent_slot = sc_slot; + new_s1->next_node = shortcut->next_node; + new_s1->skip_to_level = shortcut->skip_to_level; + + new_n0->slots[sc_slot] = assoc_array_shortcut_to_ptr(new_s1); + + memcpy(new_s1->index_key, shortcut->index_key, + keylen * sizeof(unsigned long)); + + edit->set[1].ptr = &side->back_pointer; + edit->set[1].to = assoc_array_shortcut_to_ptr(new_s1); + } else { + pr_devel("no post-shortcut\n"); + + /* We don't have to replace the pointed-to node as long as we + * use memory barriers to make sure the parent slot number is + * changed before the back pointer (the parent slot number is + * irrelevant to the old parent shortcut). + */ + new_n0->slots[sc_slot] = shortcut->next_node; + edit->set_parent_slot[0].p = &side->parent_slot; + edit->set_parent_slot[0].to = sc_slot; + edit->set[1].ptr = &side->back_pointer; + edit->set[1].to = assoc_array_node_to_ptr(new_n0); + } + + /* Install the new leaf in a spare slot in the new node. */ + if (sc_slot == 0) + edit->leaf_p = &new_n0->slots[1]; + else + edit->leaf_p = &new_n0->slots[0]; + + pr_devel("<--%s() = ok [split shortcut]\n", __func__); + return edit; +} + +/** + * assoc_array_insert - Script insertion of an object into an associative array + * @array: The array to insert into. + * @ops: The operations to use. + * @index_key: The key to insert at. + * @object: The object to insert. + * + * Precalculate and preallocate a script for the insertion or replacement of an + * object in an associative array. This results in an edit script that can + * either be applied or cancelled. + * + * The function returns a pointer to an edit script or -ENOMEM. + * + * The caller should lock against other modifications and must continue to hold + * the lock until assoc_array_apply_edit() has been called. + * + * Accesses to the tree may take place concurrently with this function, + * provided they hold the RCU read lock. + */ +struct assoc_array_edit *assoc_array_insert(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key, + void *object) +{ + struct assoc_array_walk_result result; + struct assoc_array_edit *edit; + + pr_devel("-->%s()\n", __func__); + + /* The leaf pointer we're given must not have the bottom bit set as we + * use those for type-marking the pointer. NULL pointers are also not + * allowed as they indicate an empty slot but we have to allow them + * here as they can be updated later. + */ + BUG_ON(assoc_array_ptr_is_meta(object)); + + edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL); + if (!edit) + return ERR_PTR(-ENOMEM); + edit->array = array; + edit->ops = ops; + edit->leaf = assoc_array_leaf_to_ptr(object); + edit->adjust_count_by = 1; + + switch (assoc_array_walk(array, ops, index_key, &result)) { + case assoc_array_walk_tree_empty: + /* Allocate a root node if there isn't one yet */ + if (!assoc_array_insert_in_empty_tree(edit)) + goto enomem; + return edit; + + case assoc_array_walk_found_terminal_node: + /* We found a node that doesn't have a node/shortcut pointer in + * the slot corresponding to the index key that we have to + * follow. + */ + if (!assoc_array_insert_into_terminal_node(edit, ops, index_key, + &result)) + goto enomem; + return edit; + + case assoc_array_walk_found_wrong_shortcut: + /* We found a shortcut that didn't match our key in a slot we + * needed to follow. + */ + if (!assoc_array_insert_mid_shortcut(edit, ops, &result)) + goto enomem; + return edit; + } + +enomem: + /* Clean up after an out of memory error */ + pr_devel("enomem\n"); + assoc_array_cancel_edit(edit); + return ERR_PTR(-ENOMEM); +} + +/** + * assoc_array_insert_set_object - Set the new object pointer in an edit script + * @edit: The edit script to modify. + * @object: The object pointer to set. + * + * Change the object to be inserted in an edit script. The object pointed to + * by the old object is not freed. This must be done prior to applying the + * script. + */ +void assoc_array_insert_set_object(struct assoc_array_edit *edit, void *object) +{ + BUG_ON(!object); + edit->leaf = assoc_array_leaf_to_ptr(object); +} + +struct assoc_array_delete_collapse_context { + struct assoc_array_node *node; + const void *skip_leaf; + int slot; +}; + +/* + * Subtree collapse to node iterator. + */ +static int assoc_array_delete_collapse_iterator(const void *leaf, + void *iterator_data) +{ + struct assoc_array_delete_collapse_context *collapse = iterator_data; + + if (leaf == collapse->skip_leaf) + return 0; + + BUG_ON(collapse->slot >= ASSOC_ARRAY_FAN_OUT); + + collapse->node->slots[collapse->slot++] = assoc_array_leaf_to_ptr(leaf); + return 0; +} + +/** + * assoc_array_delete - Script deletion of an object from an associative array + * @array: The array to search. + * @ops: The operations to use. + * @index_key: The key to the object. + * + * Precalculate and preallocate a script for the deletion of an object from an + * associative array. This results in an edit script that can either be + * applied or cancelled. + * + * The function returns a pointer to an edit script if the object was found, + * NULL if the object was not found or -ENOMEM. + * + * The caller should lock against other modifications and must continue to hold + * the lock until assoc_array_apply_edit() has been called. + * + * Accesses to the tree may take place concurrently with this function, + * provided they hold the RCU read lock. + */ +struct assoc_array_edit *assoc_array_delete(struct assoc_array *array, + const struct assoc_array_ops *ops, + const void *index_key) +{ + struct assoc_array_delete_collapse_context collapse; + struct assoc_array_walk_result result; + struct assoc_array_node *node, *new_n0; + struct assoc_array_edit *edit; + struct assoc_array_ptr *ptr; + bool has_meta; + int slot, i; + + pr_devel("-->%s()\n", __func__); + + edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL); + if (!edit) + return ERR_PTR(-ENOMEM); + edit->array = array; + edit->ops = ops; + edit->adjust_count_by = -1; + + switch (assoc_array_walk(array, ops, index_key, &result)) { + case assoc_array_walk_found_terminal_node: + /* We found a node that should contain the leaf we've been + * asked to remove - *if* it's in the tree. + */ + pr_devel("terminal_node\n"); + node = result.terminal_node.node; + + for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = node->slots[slot]; + if (ptr && + assoc_array_ptr_is_leaf(ptr) && + ops->compare_object(assoc_array_ptr_to_leaf(ptr), + index_key)) + goto found_leaf; + } + case assoc_array_walk_tree_empty: + case assoc_array_walk_found_wrong_shortcut: + default: + assoc_array_cancel_edit(edit); + pr_devel("not found\n"); + return NULL; + } + +found_leaf: + BUG_ON(array->nr_leaves_on_tree <= 0); + + /* In the simplest form of deletion we just clear the slot and release + * the leaf after a suitable interval. + */ + edit->dead_leaf = node->slots[slot]; + edit->set[0].ptr = &node->slots[slot]; + edit->set[0].to = NULL; + edit->adjust_count_on = node; + + /* If that concludes erasure of the last leaf, then delete the entire + * internal array. + */ + if (array->nr_leaves_on_tree == 1) { + edit->set[1].ptr = &array->root; + edit->set[1].to = NULL; + edit->adjust_count_on = NULL; + edit->excised_subtree = array->root; + pr_devel("all gone\n"); + return edit; + } + + /* However, we'd also like to clear up some metadata blocks if we + * possibly can. + * + * We go for a simple algorithm of: if this node has FAN_OUT or fewer + * leaves in it, then attempt to collapse it - and attempt to + * recursively collapse up the tree. + * + * We could also try and collapse in partially filled subtrees to take + * up space in this node. + */ + if (node->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) { + struct assoc_array_node *parent, *grandparent; + struct assoc_array_ptr *ptr; + + /* First of all, we need to know if this node has metadata so + * that we don't try collapsing if all the leaves are already + * here. + */ + has_meta = false; + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + ptr = node->slots[i]; + if (assoc_array_ptr_is_meta(ptr)) { + has_meta = true; + break; + } + } + + pr_devel("leaves: %ld [m=%d]\n", + node->nr_leaves_on_branch - 1, has_meta); + + /* Look further up the tree to see if we can collapse this node + * into a more proximal node too. + */ + parent = node; + collapse_up: + pr_devel("collapse subtree: %ld\n", parent->nr_leaves_on_branch); + + ptr = parent->back_pointer; + if (!ptr) + goto do_collapse; + if (assoc_array_ptr_is_shortcut(ptr)) { + struct assoc_array_shortcut *s = assoc_array_ptr_to_shortcut(ptr); + ptr = s->back_pointer; + if (!ptr) + goto do_collapse; + } + + grandparent = assoc_array_ptr_to_node(ptr); + if (grandparent->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) { + parent = grandparent; + goto collapse_up; + } + + do_collapse: + /* There's no point collapsing if the original node has no meta + * pointers to discard and if we didn't merge into one of that + * node's ancestry. + */ + if (has_meta || parent != node) { + node = parent; + + /* Create a new node to collapse into */ + new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n0) + goto enomem; + edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); + + new_n0->back_pointer = node->back_pointer; + new_n0->parent_slot = node->parent_slot; + new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; + edit->adjust_count_on = new_n0; + + collapse.node = new_n0; + collapse.skip_leaf = assoc_array_ptr_to_leaf(edit->dead_leaf); + collapse.slot = 0; + assoc_array_subtree_iterate(assoc_array_node_to_ptr(node), + node->back_pointer, + assoc_array_delete_collapse_iterator, + &collapse); + pr_devel("collapsed %d,%lu\n", collapse.slot, new_n0->nr_leaves_on_branch); + BUG_ON(collapse.slot != new_n0->nr_leaves_on_branch - 1); + + if (!node->back_pointer) { + edit->set[1].ptr = &array->root; + } else if (assoc_array_ptr_is_leaf(node->back_pointer)) { + BUG(); + } else if (assoc_array_ptr_is_node(node->back_pointer)) { + struct assoc_array_node *p = + assoc_array_ptr_to_node(node->back_pointer); + edit->set[1].ptr = &p->slots[node->parent_slot]; + } else if (assoc_array_ptr_is_shortcut(node->back_pointer)) { + struct assoc_array_shortcut *s = + assoc_array_ptr_to_shortcut(node->back_pointer); + edit->set[1].ptr = &s->next_node; + } + edit->set[1].to = assoc_array_node_to_ptr(new_n0); + edit->excised_subtree = assoc_array_node_to_ptr(node); + } + } + + return edit; + +enomem: + /* Clean up after an out of memory error */ + pr_devel("enomem\n"); + assoc_array_cancel_edit(edit); + return ERR_PTR(-ENOMEM); +} + +/** + * assoc_array_clear - Script deletion of all objects from an associative array + * @array: The array to clear. + * @ops: The operations to use. + * + * Precalculate and preallocate a script for the deletion of all the objects + * from an associative array. This results in an edit script that can either + * be applied or cancelled. + * + * The function returns a pointer to an edit script if there are objects to be + * deleted, NULL if there are no objects in the array or -ENOMEM. + * + * The caller should lock against other modifications and must continue to hold + * the lock until assoc_array_apply_edit() has been called. + * + * Accesses to the tree may take place concurrently with this function, + * provided they hold the RCU read lock. + */ +struct assoc_array_edit *assoc_array_clear(struct assoc_array *array, + const struct assoc_array_ops *ops) +{ + struct assoc_array_edit *edit; + + pr_devel("-->%s()\n", __func__); + + if (!array->root) + return NULL; + + edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL); + if (!edit) + return ERR_PTR(-ENOMEM); + edit->array = array; + edit->ops = ops; + edit->set[1].ptr = &array->root; + edit->set[1].to = NULL; + edit->excised_subtree = array->root; + edit->ops_for_excised_subtree = ops; + pr_devel("all gone\n"); + return edit; +} + +/* + * Handle the deferred destruction after an applied edit. + */ +static void assoc_array_rcu_cleanup(struct rcu_head *head) +{ + struct assoc_array_edit *edit = + container_of(head, struct assoc_array_edit, rcu); + int i; + + pr_devel("-->%s()\n", __func__); + + if (edit->dead_leaf) + edit->ops->free_object(assoc_array_ptr_to_leaf(edit->dead_leaf)); + for (i = 0; i < ARRAY_SIZE(edit->excised_meta); i++) + if (edit->excised_meta[i]) + kfree(assoc_array_ptr_to_node(edit->excised_meta[i])); + + if (edit->excised_subtree) { + BUG_ON(assoc_array_ptr_is_leaf(edit->excised_subtree)); + if (assoc_array_ptr_is_node(edit->excised_subtree)) { + struct assoc_array_node *n = + assoc_array_ptr_to_node(edit->excised_subtree); + n->back_pointer = NULL; + } else { + struct assoc_array_shortcut *s = + assoc_array_ptr_to_shortcut(edit->excised_subtree); + s->back_pointer = NULL; + } + assoc_array_destroy_subtree(edit->excised_subtree, + edit->ops_for_excised_subtree); + } + + kfree(edit); +} + +/** + * assoc_array_apply_edit - Apply an edit script to an associative array + * @edit: The script to apply. + * + * Apply an edit script to an associative array to effect an insertion, + * deletion or clearance. As the edit script includes preallocated memory, + * this is guaranteed not to fail. + * + * The edit script, dead objects and dead metadata will be scheduled for + * destruction after an RCU grace period to permit those doing read-only + * accesses on the array to continue to do so under the RCU read lock whilst + * the edit is taking place. + */ +void assoc_array_apply_edit(struct assoc_array_edit *edit) +{ + struct assoc_array_shortcut *shortcut; + struct assoc_array_node *node; + struct assoc_array_ptr *ptr; + int i; + + pr_devel("-->%s()\n", __func__); + + smp_wmb(); + if (edit->leaf_p) + *edit->leaf_p = edit->leaf; + + smp_wmb(); + for (i = 0; i < ARRAY_SIZE(edit->set_parent_slot); i++) + if (edit->set_parent_slot[i].p) + *edit->set_parent_slot[i].p = edit->set_parent_slot[i].to; + + smp_wmb(); + for (i = 0; i < ARRAY_SIZE(edit->set_backpointers); i++) + if (edit->set_backpointers[i]) + *edit->set_backpointers[i] = edit->set_backpointers_to; + + smp_wmb(); + for (i = 0; i < ARRAY_SIZE(edit->set); i++) + if (edit->set[i].ptr) + *edit->set[i].ptr = edit->set[i].to; + + if (edit->array->root == NULL) { + edit->array->nr_leaves_on_tree = 0; + } else if (edit->adjust_count_on) { + node = edit->adjust_count_on; + for (;;) { + node->nr_leaves_on_branch += edit->adjust_count_by; + + ptr = node->back_pointer; + if (!ptr) + break; + if (assoc_array_ptr_is_shortcut(ptr)) { + shortcut = assoc_array_ptr_to_shortcut(ptr); + ptr = shortcut->back_pointer; + if (!ptr) + break; + } + BUG_ON(!assoc_array_ptr_is_node(ptr)); + node = assoc_array_ptr_to_node(ptr); + } + + edit->array->nr_leaves_on_tree += edit->adjust_count_by; + } + + call_rcu(&edit->rcu, assoc_array_rcu_cleanup); +} + +/** + * assoc_array_cancel_edit - Discard an edit script. + * @edit: The script to discard. + * + * Free an edit script and all the preallocated data it holds without making + * any changes to the associative array it was intended for. + * + * NOTE! In the case of an insertion script, this does _not_ release the leaf + * that was to be inserted. That is left to the caller. + */ +void assoc_array_cancel_edit(struct assoc_array_edit *edit) +{ + struct assoc_array_ptr *ptr; + int i; + + pr_devel("-->%s()\n", __func__); + + /* Clean up after an out of memory error */ + for (i = 0; i < ARRAY_SIZE(edit->new_meta); i++) { + ptr = edit->new_meta[i]; + if (ptr) { + if (assoc_array_ptr_is_node(ptr)) + kfree(assoc_array_ptr_to_node(ptr)); + else + kfree(assoc_array_ptr_to_shortcut(ptr)); + } + } + kfree(edit); +} + +/** + * assoc_array_gc - Garbage collect an associative array. + * @array: The array to clean. + * @ops: The operations to use. + * @iterator: A callback function to pass judgement on each object. + * @iterator_data: Private data for the callback function. + * + * Collect garbage from an associative array and pack down the internal tree to + * save memory. + * + * The iterator function is asked to pass judgement upon each object in the + * array. If it returns false, the object is discard and if it returns true, + * the object is kept. If it returns true, it must increment the object's + * usage count (or whatever it needs to do to retain it) before returning. + * + * This function returns 0 if successful or -ENOMEM if out of memory. In the + * latter case, the array is not changed. + * + * The caller should lock against other modifications and must continue to hold + * the lock until assoc_array_apply_edit() has been called. + * + * Accesses to the tree may take place concurrently with this function, + * provided they hold the RCU read lock. + */ +int assoc_array_gc(struct assoc_array *array, + const struct assoc_array_ops *ops, + bool (*iterator)(void *object, void *iterator_data), + void *iterator_data) +{ + struct assoc_array_shortcut *shortcut, *new_s; + struct assoc_array_node *node, *new_n; + struct assoc_array_edit *edit; + struct assoc_array_ptr *cursor, *ptr; + struct assoc_array_ptr *new_root, *new_parent, **new_ptr_pp; + unsigned long nr_leaves_on_tree; + int keylen, slot, nr_free, next_slot, i; + + pr_devel("-->%s()\n", __func__); + + if (!array->root) + return 0; + + edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL); + if (!edit) + return -ENOMEM; + edit->array = array; + edit->ops = ops; + edit->ops_for_excised_subtree = ops; + edit->set[0].ptr = &array->root; + edit->excised_subtree = array->root; + + new_root = new_parent = NULL; + new_ptr_pp = &new_root; + cursor = array->root; + +descend: + /* If this point is a shortcut, then we need to duplicate it and + * advance the target cursor. + */ + if (assoc_array_ptr_is_shortcut(cursor)) { + shortcut = assoc_array_ptr_to_shortcut(cursor); + keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); + keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; + new_s = kmalloc(sizeof(struct assoc_array_shortcut) + + keylen * sizeof(unsigned long), GFP_KERNEL); + if (!new_s) + goto enomem; + pr_devel("dup shortcut %p -> %p\n", shortcut, new_s); + memcpy(new_s, shortcut, (sizeof(struct assoc_array_shortcut) + + keylen * sizeof(unsigned long))); + new_s->back_pointer = new_parent; + new_s->parent_slot = shortcut->parent_slot; + *new_ptr_pp = new_parent = assoc_array_shortcut_to_ptr(new_s); + new_ptr_pp = &new_s->next_node; + cursor = shortcut->next_node; + } + + /* Duplicate the node at this position */ + node = assoc_array_ptr_to_node(cursor); + new_n = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL); + if (!new_n) + goto enomem; + pr_devel("dup node %p -> %p\n", node, new_n); + new_n->back_pointer = new_parent; + new_n->parent_slot = node->parent_slot; + *new_ptr_pp = new_parent = assoc_array_node_to_ptr(new_n); + new_ptr_pp = NULL; + slot = 0; + +continue_node: + /* Filter across any leaves and gc any subtrees */ + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = node->slots[slot]; + if (!ptr) + continue; + + if (assoc_array_ptr_is_leaf(ptr)) { + if (iterator(assoc_array_ptr_to_leaf(ptr), + iterator_data)) + /* The iterator will have done any reference + * counting on the object for us. + */ + new_n->slots[slot] = ptr; + continue; + } + + new_ptr_pp = &new_n->slots[slot]; + cursor = ptr; + goto descend; + } + + pr_devel("-- compress node %p --\n", new_n); + + /* Count up the number of empty slots in this node and work out the + * subtree leaf count. + */ + new_n->nr_leaves_on_branch = 0; + nr_free = 0; + for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = new_n->slots[slot]; + if (!ptr) + nr_free++; + else if (assoc_array_ptr_is_leaf(ptr)) + new_n->nr_leaves_on_branch++; + } + pr_devel("free=%d, leaves=%lu\n", nr_free, new_n->nr_leaves_on_branch); + + /* See what we can fold in */ + next_slot = 0; + for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + struct assoc_array_shortcut *s; + struct assoc_array_node *child; + + ptr = new_n->slots[slot]; + if (!ptr || assoc_array_ptr_is_leaf(ptr)) + continue; + + s = NULL; + if (assoc_array_ptr_is_shortcut(ptr)) { + s = assoc_array_ptr_to_shortcut(ptr); + ptr = s->next_node; + } + + child = assoc_array_ptr_to_node(ptr); + new_n->nr_leaves_on_branch += child->nr_leaves_on_branch; + + if (child->nr_leaves_on_branch <= nr_free + 1) { + /* Fold the child node into this one */ + pr_devel("[%d] fold node %lu/%d [nx %d]\n", + slot, child->nr_leaves_on_branch, nr_free + 1, + next_slot); + + /* We would already have reaped an intervening shortcut + * on the way back up the tree. + */ + BUG_ON(s); + + new_n->slots[slot] = NULL; + nr_free++; + if (slot < next_slot) + next_slot = slot; + for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { + struct assoc_array_ptr *p = child->slots[i]; + if (!p) + continue; + BUG_ON(assoc_array_ptr_is_meta(p)); + while (new_n->slots[next_slot]) + next_slot++; + BUG_ON(next_slot >= ASSOC_ARRAY_FAN_OUT); + new_n->slots[next_slot++] = p; + nr_free--; + } + kfree(child); + } else { + pr_devel("[%d] retain node %lu/%d [nx %d]\n", + slot, child->nr_leaves_on_branch, nr_free + 1, + next_slot); + } + } + + pr_devel("after: %lu\n", new_n->nr_leaves_on_branch); + + nr_leaves_on_tree = new_n->nr_leaves_on_branch; + + /* Excise this node if it is singly occupied by a shortcut */ + if (nr_free == ASSOC_ARRAY_FAN_OUT - 1) { + for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) + if ((ptr = new_n->slots[slot])) + break; + + if (assoc_array_ptr_is_meta(ptr) && + assoc_array_ptr_is_shortcut(ptr)) { + pr_devel("excise node %p with 1 shortcut\n", new_n); + new_s = assoc_array_ptr_to_shortcut(ptr); + new_parent = new_n->back_pointer; + slot = new_n->parent_slot; + kfree(new_n); + if (!new_parent) { + new_s->back_pointer = NULL; + new_s->parent_slot = 0; + new_root = ptr; + goto gc_complete; + } + + if (assoc_array_ptr_is_shortcut(new_parent)) { + /* We can discard any preceding shortcut also */ + struct assoc_array_shortcut *s = + assoc_array_ptr_to_shortcut(new_parent); + + pr_devel("excise preceding shortcut\n"); + + new_parent = new_s->back_pointer = s->back_pointer; + slot = new_s->parent_slot = s->parent_slot; + kfree(s); + if (!new_parent) { + new_s->back_pointer = NULL; + new_s->parent_slot = 0; + new_root = ptr; + goto gc_complete; + } + } + + new_s->back_pointer = new_parent; + new_s->parent_slot = slot; + new_n = assoc_array_ptr_to_node(new_parent); + new_n->slots[slot] = ptr; + goto ascend_old_tree; + } + } + + /* Excise any shortcuts we might encounter that point to nodes that + * only contain leaves. + */ + ptr = new_n->back_pointer; + if (!ptr) + goto gc_complete; + + if (assoc_array_ptr_is_shortcut(ptr)) { + new_s = assoc_array_ptr_to_shortcut(ptr); + new_parent = new_s->back_pointer; + slot = new_s->parent_slot; + + if (new_n->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT) { + struct assoc_array_node *n; + + pr_devel("excise shortcut\n"); + new_n->back_pointer = new_parent; + new_n->parent_slot = slot; + kfree(new_s); + if (!new_parent) { + new_root = assoc_array_node_to_ptr(new_n); + goto gc_complete; + } + + n = assoc_array_ptr_to_node(new_parent); + n->slots[slot] = assoc_array_node_to_ptr(new_n); + } + } else { + new_parent = ptr; + } + new_n = assoc_array_ptr_to_node(new_parent); + +ascend_old_tree: + ptr = node->back_pointer; + if (assoc_array_ptr_is_shortcut(ptr)) { + shortcut = assoc_array_ptr_to_shortcut(ptr); + slot = shortcut->parent_slot; + cursor = shortcut->back_pointer; + } else { + slot = node->parent_slot; + cursor = ptr; + } + BUG_ON(!ptr); + node = assoc_array_ptr_to_node(cursor); + slot++; + goto continue_node; + +gc_complete: + edit->set[0].to = new_root; + assoc_array_apply_edit(edit); + edit->array->nr_leaves_on_tree = nr_leaves_on_tree; + return 0; + +enomem: + pr_devel("enomem\n"); + assoc_array_destroy_subtree(new_root, edit->ops); + kfree(edit); + return -ENOMEM; +} -- cgit From b2a4df200d570b2c33a57e1ebfa5896e4bc81b69 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:18 +0100 Subject: KEYS: Expand the capacity of a keyring Expand the capacity of a keyring to be able to hold a lot more keys by using the previously added associative array implementation. Currently the maximum capacity is: (PAGE_SIZE - sizeof(header)) / sizeof(struct key *) which, on a 64-bit system, is a little more 500. However, since this is being used for the NFS uid mapper, we need more than that. The new implementation gives us effectively unlimited capacity. With some alterations, the keyutils testsuite runs successfully to completion after this patch is applied. The alterations are because (a) keyrings that are simply added to no longer appear ordered and (b) some of the errors have changed a bit. Signed-off-by: David Howells --- include/keys/keyring-type.h | 17 +- include/linux/key.h | 13 +- lib/assoc_array.c | 1 + security/keys/Kconfig | 1 + security/keys/gc.c | 33 +- security/keys/internal.h | 17 +- security/keys/key.c | 35 +- security/keys/keyring.c | 1436 ++++++++++++++++++++++--------------------- security/keys/request_key.c | 12 +- 9 files changed, 803 insertions(+), 762 deletions(-) (limited to 'include') diff --git a/include/keys/keyring-type.h b/include/keys/keyring-type.h index cf49159b0e3a..fca5c62340a4 100644 --- a/include/keys/keyring-type.h +++ b/include/keys/keyring-type.h @@ -1,6 +1,6 @@ /* Keyring key type * - * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2008, 2013 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -13,19 +13,6 @@ #define _KEYS_KEYRING_TYPE_H #include -#include - -/* - * the keyring payload contains a list of the keys to which the keyring is - * subscribed - */ -struct keyring_list { - struct rcu_head rcu; /* RCU deletion hook */ - unsigned short maxkeys; /* max keys this list can hold */ - unsigned short nkeys; /* number of keys currently held */ - unsigned short delkey; /* key to be unlinked by RCU */ - struct key __rcu *keys[0]; -}; - +#include #endif /* _KEYS_KEYRING_TYPE_H */ diff --git a/include/linux/key.h b/include/linux/key.h index ef596c7af585..2417f789d29b 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef __KERNEL__ #include @@ -196,11 +197,13 @@ struct key { * whatever */ union { - unsigned long value; - void __rcu *rcudata; - void *data; - struct keyring_list __rcu *subscriptions; - } payload; + union { + unsigned long value; + void __rcu *rcudata; + void *data; + } payload; + struct assoc_array keys; + }; }; extern struct key *key_alloc(struct key_type *type, diff --git a/lib/assoc_array.c b/lib/assoc_array.c index a0952818f938..17edeaf19180 100644 --- a/lib/assoc_array.c +++ b/lib/assoc_array.c @@ -12,6 +12,7 @@ */ //#define DEBUG #include +#include #include /* diff --git a/security/keys/Kconfig b/security/keys/Kconfig index a90d6d300dbd..15e0dfe8c80f 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -4,6 +4,7 @@ config KEYS bool "Enable access key retention support" + select ASSOCIATIVE_ARRAY help This option provides support for retaining authentication tokens and access keys in the kernel. diff --git a/security/keys/gc.c b/security/keys/gc.c index d67c97bb1025..cce621c33dce 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -130,6 +130,13 @@ void key_gc_keytype(struct key_type *ktype) kleave(""); } +static int key_gc_keyring_func(const void *object, void *iterator_data) +{ + const struct key *key = object; + time_t *limit = iterator_data; + return key_is_dead(key, *limit); +} + /* * Garbage collect pointers from a keyring. * @@ -138,10 +145,9 @@ void key_gc_keytype(struct key_type *ktype) */ static void key_gc_keyring(struct key *keyring, time_t limit) { - struct keyring_list *klist; - int loop; + int result; - kenter("%x", key_serial(keyring)); + kenter("%x{%s}", keyring->serial, keyring->description ?: ""); if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED))) @@ -149,27 +155,17 @@ static void key_gc_keyring(struct key *keyring, time_t limit) /* scan the keyring looking for dead keys */ rcu_read_lock(); - klist = rcu_dereference(keyring->payload.subscriptions); - if (!klist) - goto unlock_dont_gc; - - loop = klist->nkeys; - smp_rmb(); - for (loop--; loop >= 0; loop--) { - struct key *key = rcu_dereference(klist->keys[loop]); - if (key_is_dead(key, limit)) - goto do_gc; - } - -unlock_dont_gc: + result = assoc_array_iterate(&keyring->keys, + key_gc_keyring_func, &limit); rcu_read_unlock(); + if (result == true) + goto do_gc; + dont_gc: kleave(" [no gc]"); return; do_gc: - rcu_read_unlock(); - keyring_gc(keyring, limit); kleave(" [gc]"); } @@ -392,7 +388,6 @@ found_unreferenced_key: */ found_keyring: spin_unlock(&key_serial_lock); - kdebug("scan keyring %d", key->serial); key_gc_keyring(key, limit); goto maybe_resched; diff --git a/security/keys/internal.h b/security/keys/internal.h index 73950bf8f875..581c6f688352 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -90,20 +90,23 @@ extern void key_type_put(struct key_type *ktype); extern int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, - unsigned long *_prealloc); + struct assoc_array_edit **_edit); extern int __key_link_check_live_key(struct key *keyring, struct key *key); -extern void __key_link(struct key *keyring, struct key *key, - unsigned long *_prealloc); +extern void __key_link(struct key *key, struct assoc_array_edit **_edit); extern void __key_link_end(struct key *keyring, const struct keyring_index_key *index_key, - unsigned long prealloc); + struct assoc_array_edit *edit); -extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, - const struct keyring_index_key *index_key); +extern key_ref_t find_key_to_update(key_ref_t keyring_ref, + const struct keyring_index_key *index_key); extern struct key *keyring_search_instkey(struct key *keyring, key_serial_t target_id); +extern int iterate_over_keyring(const struct key *keyring, + int (*func)(const struct key *key, void *data), + void *data); + typedef int (*key_match_func_t)(const struct key *, const void *); struct keyring_search_context { @@ -119,6 +122,8 @@ struct keyring_search_context { #define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ + int (*iterator)(const void *object, void *iterator_data); + /* Internal stuff */ int skipped_ret; bool possessed; diff --git a/security/keys/key.c b/security/keys/key.c index 7d716b82a61e..a819b5c7d4ec 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -409,7 +409,7 @@ static int __key_instantiate_and_link(struct key *key, struct key_preparsed_payload *prep, struct key *keyring, struct key *authkey, - unsigned long *_prealloc) + struct assoc_array_edit **_edit) { int ret, awaken; @@ -436,7 +436,7 @@ static int __key_instantiate_and_link(struct key *key, /* and link it into the destination keyring */ if (keyring) - __key_link(keyring, key, _prealloc); + __key_link(key, _edit); /* disable the authorisation key */ if (authkey) @@ -476,7 +476,7 @@ int key_instantiate_and_link(struct key *key, struct key *authkey) { struct key_preparsed_payload prep; - unsigned long prealloc; + struct assoc_array_edit *edit; int ret; memset(&prep, 0, sizeof(prep)); @@ -490,16 +490,15 @@ int key_instantiate_and_link(struct key *key, } if (keyring) { - ret = __key_link_begin(keyring, &key->index_key, &prealloc); + ret = __key_link_begin(keyring, &key->index_key, &edit); if (ret < 0) goto error_free_preparse; } - ret = __key_instantiate_and_link(key, &prep, keyring, authkey, - &prealloc); + ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); if (keyring) - __key_link_end(keyring, &key->index_key, prealloc); + __key_link_end(keyring, &key->index_key, edit); error_free_preparse: if (key->type->preparse) @@ -537,7 +536,7 @@ int key_reject_and_link(struct key *key, struct key *keyring, struct key *authkey) { - unsigned long prealloc; + struct assoc_array_edit *edit; struct timespec now; int ret, awaken, link_ret = 0; @@ -548,7 +547,7 @@ int key_reject_and_link(struct key *key, ret = -EBUSY; if (keyring) - link_ret = __key_link_begin(keyring, &key->index_key, &prealloc); + link_ret = __key_link_begin(keyring, &key->index_key, &edit); mutex_lock(&key_construction_mutex); @@ -570,7 +569,7 @@ int key_reject_and_link(struct key *key, /* and link it into the destination keyring */ if (keyring && link_ret == 0) - __key_link(keyring, key, &prealloc); + __key_link(key, &edit); /* disable the authorisation key */ if (authkey) @@ -580,7 +579,7 @@ int key_reject_and_link(struct key *key, mutex_unlock(&key_construction_mutex); if (keyring) - __key_link_end(keyring, &key->index_key, prealloc); + __key_link_end(keyring, &key->index_key, edit); /* wake up anyone waiting for a key to be constructed */ if (awaken) @@ -783,8 +782,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, .description = description, }; struct key_preparsed_payload prep; + struct assoc_array_edit *edit; const struct cred *cred = current_cred(); - unsigned long prealloc; struct key *keyring, *key = NULL; key_ref_t key_ref; int ret; @@ -828,7 +827,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } index_key.desc_len = strlen(index_key.description); - ret = __key_link_begin(keyring, &index_key, &prealloc); + ret = __key_link_begin(keyring, &index_key, &edit); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_free_prep; @@ -847,8 +846,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, * update that instead if possible */ if (index_key.type->update) { - key_ref = __keyring_search_one(keyring_ref, &index_key); - if (!IS_ERR(key_ref)) + key_ref = find_key_to_update(keyring_ref, &index_key); + if (key_ref) goto found_matching_key; } @@ -874,7 +873,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } /* instantiate it and link it into the target keyring */ - ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); + ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &edit); if (ret < 0) { key_put(key); key_ref = ERR_PTR(ret); @@ -884,7 +883,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_link_end: - __key_link_end(keyring, &index_key, prealloc); + __key_link_end(keyring, &index_key, edit); error_free_prep: if (index_key.type->preparse) index_key.type->free_preparse(&prep); @@ -897,7 +896,7 @@ error: /* we found a matching key, so we're going to try to update it * - we can drop the locks first as we have the key pinned */ - __key_link_end(keyring, &index_key, prealloc); + __key_link_end(keyring, &index_key, edit); key_ref = __key_update(key_ref, &prep); goto error_free_prep; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index eeef1a073db4..f7cdea22214f 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1,6 +1,6 @@ /* Keyring handling * - * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004-2005, 2008, 2013 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -17,25 +17,11 @@ #include #include #include +#include +#include #include #include "internal.h" -#define rcu_dereference_locked_keyring(keyring) \ - (rcu_dereference_protected( \ - (keyring)->payload.subscriptions, \ - rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) - -#define rcu_deref_link_locked(klist, index, keyring) \ - (rcu_dereference_protected( \ - (klist)->keys[index], \ - rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) - -#define MAX_KEYRING_LINKS \ - min_t(size_t, USHRT_MAX - 1, \ - ((PAGE_SIZE - sizeof(struct keyring_list)) / sizeof(struct key *))) - -#define KEY_LINK_FIXQUOTA 1UL - /* * When plumbing the depths of the key tree, this sets a hard limit * set on how deep we're willing to go. @@ -47,6 +33,28 @@ */ #define KEYRING_NAME_HASH_SIZE (1 << 5) +/* + * We mark pointers we pass to the associative array with bit 1 set if + * they're keyrings and clear otherwise. + */ +#define KEYRING_PTR_SUBTYPE 0x2UL + +static inline bool keyring_ptr_is_keyring(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & KEYRING_PTR_SUBTYPE; +} +static inline struct key *keyring_ptr_to_key(const struct assoc_array_ptr *x) +{ + void *object = assoc_array_ptr_to_leaf(x); + return (struct key *)((unsigned long)object & ~KEYRING_PTR_SUBTYPE); +} +static inline void *keyring_key_to_ptr(struct key *key) +{ + if (key->type == &key_type_keyring) + return (void *)((unsigned long)key | KEYRING_PTR_SUBTYPE); + return key; +} + static struct list_head keyring_name_hash[KEYRING_NAME_HASH_SIZE]; static DEFINE_RWLOCK(keyring_name_lock); @@ -67,7 +75,6 @@ static inline unsigned keyring_hash(const char *desc) */ static int keyring_instantiate(struct key *keyring, struct key_preparsed_payload *prep); -static int keyring_match(const struct key *keyring, const void *criterion); static void keyring_revoke(struct key *keyring); static void keyring_destroy(struct key *keyring); static void keyring_describe(const struct key *keyring, struct seq_file *m); @@ -76,9 +83,9 @@ static long keyring_read(const struct key *keyring, struct key_type key_type_keyring = { .name = "keyring", - .def_datalen = sizeof(struct keyring_list), + .def_datalen = 0, .instantiate = keyring_instantiate, - .match = keyring_match, + .match = user_match, .revoke = keyring_revoke, .destroy = keyring_destroy, .describe = keyring_describe, @@ -127,6 +134,7 @@ static int keyring_instantiate(struct key *keyring, ret = -EINVAL; if (prep->datalen == 0) { + assoc_array_init(&keyring->keys); /* make the keyring available by name if it has one */ keyring_publish_name(keyring); ret = 0; @@ -136,14 +144,225 @@ static int keyring_instantiate(struct key *keyring, } /* - * Match keyrings on their name + * Multiply 64-bits by 32-bits to 96-bits and fold back to 64-bit. Ideally we'd + * fold the carry back too, but that requires inline asm. + */ +static u64 mult_64x32_and_fold(u64 x, u32 y) +{ + u64 hi = (u64)(u32)(x >> 32) * y; + u64 lo = (u64)(u32)(x) * y; + return lo + ((u64)(u32)hi << 32) + (u32)(hi >> 32); +} + +/* + * Hash a key type and description. + */ +static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key) +{ + const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP; + const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK; + const char *description = index_key->description; + unsigned long hash, type; + u32 piece; + u64 acc; + int n, desc_len = index_key->desc_len; + + type = (unsigned long)index_key->type; + + acc = mult_64x32_and_fold(type, desc_len + 13); + acc = mult_64x32_and_fold(acc, 9207); + for (;;) { + n = desc_len; + if (n <= 0) + break; + if (n > 4) + n = 4; + piece = 0; + memcpy(&piece, description, n); + description += n; + desc_len -= n; + acc = mult_64x32_and_fold(acc, piece); + acc = mult_64x32_and_fold(acc, 9207); + } + + /* Fold the hash down to 32 bits if need be. */ + hash = acc; + if (ASSOC_ARRAY_KEY_CHUNK_SIZE == 32) + hash ^= acc >> 32; + + /* Squidge all the keyrings into a separate part of the tree to + * ordinary keys by making sure the lowest level segment in the hash is + * zero for keyrings and non-zero otherwise. + */ + if (index_key->type != &key_type_keyring && (hash & level_mask) == 0) + return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; + if (index_key->type == &key_type_keyring && (hash & level_mask) != 0) + return (hash + (hash << level_shift)) & ~level_mask; + return hash; +} + +/* + * Build the next index key chunk. + * + * On 32-bit systems the index key is laid out as: + * + * 0 4 5 9... + * hash desclen typeptr desc[] + * + * On 64-bit systems: + * + * 0 8 9 17... + * hash desclen typeptr desc[] + * + * We return it one word-sized chunk at a time. */ -static int keyring_match(const struct key *keyring, const void *description) +static unsigned long keyring_get_key_chunk(const void *data, int level) +{ + const struct keyring_index_key *index_key = data; + unsigned long chunk = 0; + long offset = 0; + int desc_len = index_key->desc_len, n = sizeof(chunk); + + level /= ASSOC_ARRAY_KEY_CHUNK_SIZE; + switch (level) { + case 0: + return hash_key_type_and_desc(index_key); + case 1: + return ((unsigned long)index_key->type << 8) | desc_len; + case 2: + if (desc_len == 0) + return (u8)((unsigned long)index_key->type >> + (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); + n--; + offset = 1; + default: + offset += sizeof(chunk) - 1; + offset += (level - 3) * sizeof(chunk); + if (offset >= desc_len) + return 0; + desc_len -= offset; + if (desc_len > n) + desc_len = n; + offset += desc_len; + do { + chunk <<= 8; + chunk |= ((u8*)index_key->description)[--offset]; + } while (--desc_len > 0); + + if (level == 2) { + chunk <<= 8; + chunk |= (u8)((unsigned long)index_key->type >> + (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); + } + return chunk; + } +} + +static unsigned long keyring_get_object_key_chunk(const void *object, int level) +{ + const struct key *key = keyring_ptr_to_key(object); + return keyring_get_key_chunk(&key->index_key, level); +} + +static bool keyring_compare_object(const void *object, const void *data) { - return keyring->description && - strcmp(keyring->description, description) == 0; + const struct keyring_index_key *index_key = data; + const struct key *key = keyring_ptr_to_key(object); + + return key->index_key.type == index_key->type && + key->index_key.desc_len == index_key->desc_len && + memcmp(key->index_key.description, index_key->description, + index_key->desc_len) == 0; } +/* + * Compare the index keys of a pair of objects and determine the bit position + * at which they differ - if they differ. + */ +static int keyring_diff_objects(const void *_a, const void *_b) +{ + const struct key *key_a = keyring_ptr_to_key(_a); + const struct key *key_b = keyring_ptr_to_key(_b); + const struct keyring_index_key *a = &key_a->index_key; + const struct keyring_index_key *b = &key_b->index_key; + unsigned long seg_a, seg_b; + int level, i; + + level = 0; + seg_a = hash_key_type_and_desc(a); + seg_b = hash_key_type_and_desc(b); + if ((seg_a ^ seg_b) != 0) + goto differ; + + /* The number of bits contributed by the hash is controlled by a + * constant in the assoc_array headers. Everything else thereafter we + * can deal with as being machine word-size dependent. + */ + level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8; + seg_a = a->desc_len; + seg_b = b->desc_len; + if ((seg_a ^ seg_b) != 0) + goto differ; + + /* The next bit may not work on big endian */ + level++; + seg_a = (unsigned long)a->type; + seg_b = (unsigned long)b->type; + if ((seg_a ^ seg_b) != 0) + goto differ; + + level += sizeof(unsigned long); + if (a->desc_len == 0) + goto same; + + i = 0; + if (((unsigned long)a->description | (unsigned long)b->description) & + (sizeof(unsigned long) - 1)) { + do { + seg_a = *(unsigned long *)(a->description + i); + seg_b = *(unsigned long *)(b->description + i); + if ((seg_a ^ seg_b) != 0) + goto differ_plus_i; + i += sizeof(unsigned long); + } while (i < (a->desc_len & (sizeof(unsigned long) - 1))); + } + + for (; i < a->desc_len; i++) { + seg_a = *(unsigned char *)(a->description + i); + seg_b = *(unsigned char *)(b->description + i); + if ((seg_a ^ seg_b) != 0) + goto differ_plus_i; + } + +same: + return -1; + +differ_plus_i: + level += i; +differ: + i = level * 8 + __ffs(seg_a ^ seg_b); + return i; +} + +/* + * Free an object after stripping the keyring flag off of the pointer. + */ +static void keyring_free_object(void *object) +{ + key_put(keyring_ptr_to_key(object)); +} + +/* + * Operations for keyring management by the index-tree routines. + */ +static const struct assoc_array_ops keyring_assoc_array_ops = { + .get_key_chunk = keyring_get_key_chunk, + .get_object_key_chunk = keyring_get_object_key_chunk, + .compare_object = keyring_compare_object, + .diff_objects = keyring_diff_objects, + .free_object = keyring_free_object, +}; + /* * Clean up a keyring when it is destroyed. Unpublish its name if it had one * and dispose of its data. @@ -155,9 +374,6 @@ static int keyring_match(const struct key *keyring, const void *description) */ static void keyring_destroy(struct key *keyring) { - struct keyring_list *klist; - int loop; - if (keyring->description) { write_lock(&keyring_name_lock); @@ -168,12 +384,7 @@ static void keyring_destroy(struct key *keyring) write_unlock(&keyring_name_lock); } - klist = rcu_access_pointer(keyring->payload.subscriptions); - if (klist) { - for (loop = klist->nkeys - 1; loop >= 0; loop--) - key_put(rcu_access_pointer(klist->keys[loop])); - kfree(klist); - } + assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops); } /* @@ -181,76 +392,88 @@ static void keyring_destroy(struct key *keyring) */ static void keyring_describe(const struct key *keyring, struct seq_file *m) { - struct keyring_list *klist; - if (keyring->description) seq_puts(m, keyring->description); else seq_puts(m, "[anon]"); if (key_is_instantiated(keyring)) { - rcu_read_lock(); - klist = rcu_dereference(keyring->payload.subscriptions); - if (klist) - seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); + if (keyring->keys.nr_leaves_on_tree != 0) + seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree); else seq_puts(m, ": empty"); - rcu_read_unlock(); } } +struct keyring_read_iterator_context { + size_t qty; + size_t count; + key_serial_t __user *buffer; +}; + +static int keyring_read_iterator(const void *object, void *data) +{ + struct keyring_read_iterator_context *ctx = data; + const struct key *key = keyring_ptr_to_key(object); + int ret; + + kenter("{%s,%d},,{%zu/%zu}", + key->type->name, key->serial, ctx->count, ctx->qty); + + if (ctx->count >= ctx->qty) + return 1; + + ret = put_user(key->serial, ctx->buffer); + if (ret < 0) + return ret; + ctx->buffer++; + ctx->count += sizeof(key->serial); + return 0; +} + /* * Read a list of key IDs from the keyring's contents in binary form * - * The keyring's semaphore is read-locked by the caller. + * The keyring's semaphore is read-locked by the caller. This prevents someone + * from modifying it under us - which could cause us to read key IDs multiple + * times. */ static long keyring_read(const struct key *keyring, char __user *buffer, size_t buflen) { - struct keyring_list *klist; - struct key *key; - size_t qty, tmp; - int loop, ret; + struct keyring_read_iterator_context ctx; + unsigned long nr_keys; + int ret; - ret = 0; - klist = rcu_dereference_locked_keyring(keyring); - if (klist) { - /* calculate how much data we could return */ - qty = klist->nkeys * sizeof(key_serial_t); - - if (buffer && buflen > 0) { - if (buflen > qty) - buflen = qty; - - /* copy the IDs of the subscribed keys into the - * buffer */ - ret = -EFAULT; - - for (loop = 0; loop < klist->nkeys; loop++) { - key = rcu_deref_link_locked(klist, loop, - keyring); - - tmp = sizeof(key_serial_t); - if (tmp > buflen) - tmp = buflen; - - if (copy_to_user(buffer, - &key->serial, - tmp) != 0) - goto error; - - buflen -= tmp; - if (buflen == 0) - break; - buffer += tmp; - } - } + kenter("{%d},,%zu", key_serial(keyring), buflen); + + if (buflen & (sizeof(key_serial_t) - 1)) + return -EINVAL; + + nr_keys = keyring->keys.nr_leaves_on_tree; + if (nr_keys == 0) + return 0; - ret = qty; + /* Calculate how much data we could return */ + ctx.qty = nr_keys * sizeof(key_serial_t); + + if (!buffer || !buflen) + return ctx.qty; + + if (buflen > ctx.qty) + ctx.qty = buflen; + + /* Copy the IDs of the subscribed keys into the buffer */ + ctx.buffer = (key_serial_t __user *)buffer; + ctx.count = 0; + ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); + if (ret < 0) { + kleave(" = %d [iterate]", ret); + return ret; } -error: - return ret; + kleave(" = %zu [ok]", ctx.count); + return ctx.count; } /* @@ -277,219 +500,360 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, } EXPORT_SYMBOL(keyring_alloc); -/** - * keyring_search_aux - Search a keyring tree for a key matching some criteria - * @keyring_ref: A pointer to the keyring with possession indicator. - * @ctx: The keyring search context. - * - * Search the supplied keyring tree for a key that matches the criteria given. - * The root keyring and any linked keyrings must grant Search permission to the - * caller to be searchable and keys can only be found if they too grant Search - * to the caller. The possession flag on the root keyring pointer controls use - * of the possessor bits in permissions checking of the entire tree. In - * addition, the LSM gets to forbid keyring searches and key matches. - * - * The search is performed as a breadth-then-depth search up to the prescribed - * limit (KEYRING_SEARCH_MAX_DEPTH). - * - * Keys are matched to the type provided and are then filtered by the match - * function, which is given the description to use in any way it sees fit. The - * match function may use any attributes of a key that it wishes to to - * determine the match. Normally the match function from the key type would be - * used. - * - * RCU is used to prevent the keyring key lists from disappearing without the - * need to take lots of locks. - * - * Returns a pointer to the found key and increments the key usage count if - * successful; -EAGAIN if no matching keys were found, or if expired or revoked - * keys were found; -ENOKEY if only negative keys were found; -ENOTDIR if the - * specified keyring wasn't a keyring. - * - * In the case of a successful return, the possession attribute from - * @keyring_ref is propagated to the returned key reference. +/* + * Iteration function to consider each key found. */ -key_ref_t keyring_search_aux(key_ref_t keyring_ref, - struct keyring_search_context *ctx) +static int keyring_search_iterator(const void *object, void *iterator_data) { - struct { - /* Need a separate keylist pointer for RCU purposes */ - struct key *keyring; - struct keyring_list *keylist; - int kix; - } stack[KEYRING_SEARCH_MAX_DEPTH]; - - struct keyring_list *keylist; - unsigned long kflags; - struct key *keyring, *key; - key_ref_t key_ref; - long err; - int sp, nkeys, kix; + struct keyring_search_context *ctx = iterator_data; + const struct key *key = keyring_ptr_to_key(object); + unsigned long kflags = key->flags; - keyring = key_ref_to_ptr(keyring_ref); - ctx->possessed = is_key_possessed(keyring_ref); - key_check(keyring); + kenter("{%d}", key->serial); - /* top keyring must have search permission to begin the search */ - err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH); - if (err < 0) { - key_ref = ERR_PTR(err); - goto error; + /* ignore keys not of this type */ + if (key->type != ctx->index_key.type) { + kleave(" = 0 [!type]"); + return 0; } - key_ref = ERR_PTR(-ENOTDIR); - if (keyring->type != &key_type_keyring) - goto error; + /* skip invalidated, revoked and expired keys */ + if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { + if (kflags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED))) { + ctx->result = ERR_PTR(-EKEYREVOKED); + kleave(" = %d [invrev]", ctx->skipped_ret); + goto skipped; + } - rcu_read_lock(); + if (key->expiry && ctx->now.tv_sec >= key->expiry) { + ctx->result = ERR_PTR(-EKEYEXPIRED); + kleave(" = %d [expire]", ctx->skipped_ret); + goto skipped; + } + } - ctx->now = current_kernel_time(); - err = -EAGAIN; - sp = 0; - - /* firstly we should check to see if this top-level keyring is what we - * are looking for */ - key_ref = ERR_PTR(-EAGAIN); - kflags = keyring->flags; - if (keyring->type == ctx->index_key.type && - ctx->match(keyring, ctx->match_data)) { - key = keyring; - if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK) - goto found; + /* keys that don't match */ + if (!ctx->match(key, ctx->match_data)) { + kleave(" = 0 [!match]"); + return 0; + } - /* check it isn't negative and hasn't expired or been - * revoked */ - if (kflags & (1 << KEY_FLAG_REVOKED)) - goto error_2; - if (key->expiry && ctx->now.tv_sec >= key->expiry) - goto error_2; - key_ref = ERR_PTR(key->type_data.reject_error); - if (kflags & (1 << KEY_FLAG_NEGATIVE)) - goto error_2; - goto found; + /* key must have search permissions */ + if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) && + key_task_permission(make_key_ref(key, ctx->possessed), + ctx->cred, KEY_SEARCH) < 0) { + ctx->result = ERR_PTR(-EACCES); + kleave(" = %d [!perm]", ctx->skipped_ret); + goto skipped; } - /* otherwise, the top keyring must not be revoked, expired, or - * negatively instantiated if we are to search it */ - key_ref = ERR_PTR(-EAGAIN); - if (kflags & ((1 << KEY_FLAG_INVALIDATED) | - (1 << KEY_FLAG_REVOKED) | - (1 << KEY_FLAG_NEGATIVE)) || - (keyring->expiry && ctx->now.tv_sec >= keyring->expiry)) - goto error_2; - - /* start processing a new keyring */ -descend: - kflags = keyring->flags; - if (kflags & ((1 << KEY_FLAG_INVALIDATED) | - (1 << KEY_FLAG_REVOKED))) - goto not_this_keyring; + if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { + /* we set a different error code if we pass a negative key */ + if (kflags & (1 << KEY_FLAG_NEGATIVE)) { + ctx->result = ERR_PTR(key->type_data.reject_error); + kleave(" = %d [neg]", ctx->skipped_ret); + goto skipped; + } + } - keylist = rcu_dereference(keyring->payload.subscriptions); - if (!keylist) - goto not_this_keyring; + /* Found */ + ctx->result = make_key_ref(key, ctx->possessed); + kleave(" = 1 [found]"); + return 1; - /* iterate through the keys in this keyring first */ - nkeys = keylist->nkeys; - smp_rmb(); - for (kix = 0; kix < nkeys; kix++) { - key = rcu_dereference(keylist->keys[kix]); - kflags = key->flags; +skipped: + return ctx->skipped_ret; +} - /* ignore keys not of this type */ - if (key->type != ctx->index_key.type) - continue; +/* + * Search inside a keyring for a key. We can search by walking to it + * directly based on its index-key or we can iterate over the entire + * tree looking for it, based on the match function. + */ +static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) +{ + if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == + KEYRING_SEARCH_LOOKUP_DIRECT) { + const void *object; + + object = assoc_array_find(&keyring->keys, + &keyring_assoc_array_ops, + &ctx->index_key); + return object ? ctx->iterator(object, ctx) : 0; + } + return assoc_array_iterate(&keyring->keys, ctx->iterator, ctx); +} - /* skip invalidated, revoked and expired keys */ - if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) { - if (kflags & ((1 << KEY_FLAG_INVALIDATED) | - (1 << KEY_FLAG_REVOKED))) - continue; +/* + * Search a tree of keyrings that point to other keyrings up to the maximum + * depth. + */ +static bool search_nested_keyrings(struct key *keyring, + struct keyring_search_context *ctx) +{ + struct { + struct key *keyring; + struct assoc_array_node *node; + int slot; + } stack[KEYRING_SEARCH_MAX_DEPTH]; - if (key->expiry && ctx->now.tv_sec >= key->expiry) - continue; - } + struct assoc_array_shortcut *shortcut; + struct assoc_array_node *node; + struct assoc_array_ptr *ptr; + struct key *key; + int sp = 0, slot; - /* keys that don't match */ - if (!ctx->match(key, ctx->match_data)) - continue; + kenter("{%d},{%s,%s}", + keyring->serial, + ctx->index_key.type->name, + ctx->index_key.description); - /* key must have search permissions */ - if (key_task_permission(make_key_ref(key, ctx->possessed), - ctx->cred, KEY_SEARCH) < 0) - continue; + if (ctx->index_key.description) + ctx->index_key.desc_len = strlen(ctx->index_key.description); - if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK) + /* Check to see if this top-level keyring is what we are looking for + * and whether it is valid or not. + */ + if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE || + keyring_compare_object(keyring, &ctx->index_key)) { + ctx->skipped_ret = 2; + ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; + switch (ctx->iterator(keyring_key_to_ptr(keyring), ctx)) { + case 1: goto found; - - /* we set a different error code if we pass a negative key */ - if (kflags & (1 << KEY_FLAG_NEGATIVE)) { - err = key->type_data.reject_error; - continue; + case 2: + return false; + default: + break; } + } + ctx->skipped_ret = 0; + if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK) + ctx->flags &= ~KEYRING_SEARCH_DO_STATE_CHECK; + + /* Start processing a new keyring */ +descend_to_keyring: + kdebug("descend to %d", keyring->serial); + if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED))) + goto not_this_keyring; + + /* Search through the keys in this keyring before its searching its + * subtrees. + */ + if (search_keyring(keyring, ctx)) goto found; - } - /* search through the keyrings nested in this one */ - kix = 0; -ascend: - nkeys = keylist->nkeys; - smp_rmb(); - for (; kix < nkeys; kix++) { - key = rcu_dereference(keylist->keys[kix]); - if (key->type != &key_type_keyring) - continue; + /* Then manually iterate through the keyrings nested in this one. + * + * Start from the root node of the index tree. Because of the way the + * hash function has been set up, keyrings cluster on the leftmost + * branch of the root node (root slot 0) or in the root node itself. + * Non-keyrings avoid the leftmost branch of the root entirely (root + * slots 1-15). + */ + ptr = ACCESS_ONCE(keyring->keys.root); + if (!ptr) + goto not_this_keyring; - /* recursively search nested keyrings - * - only search keyrings for which we have search permission + if (assoc_array_ptr_is_shortcut(ptr)) { + /* If the root is a shortcut, either the keyring only contains + * keyring pointers (everything clusters behind root slot 0) or + * doesn't contain any keyring pointers. */ - if (sp >= KEYRING_SEARCH_MAX_DEPTH) + shortcut = assoc_array_ptr_to_shortcut(ptr); + smp_read_barrier_depends(); + if ((shortcut->index_key[0] & ASSOC_ARRAY_FAN_MASK) != 0) + goto not_this_keyring; + + ptr = ACCESS_ONCE(shortcut->next_node); + node = assoc_array_ptr_to_node(ptr); + goto begin_node; + } + + node = assoc_array_ptr_to_node(ptr); + smp_read_barrier_depends(); + + ptr = node->slots[0]; + if (!assoc_array_ptr_is_meta(ptr)) + goto begin_node; + +descend_to_node: + /* Descend to a more distal node in this keyring's content tree and go + * through that. + */ + kdebug("descend"); + if (assoc_array_ptr_is_shortcut(ptr)) { + shortcut = assoc_array_ptr_to_shortcut(ptr); + smp_read_barrier_depends(); + ptr = ACCESS_ONCE(shortcut->next_node); + BUG_ON(!assoc_array_ptr_is_node(ptr)); + node = assoc_array_ptr_to_node(ptr); + } + +begin_node: + kdebug("begin_node"); + smp_read_barrier_depends(); + slot = 0; +ascend_to_node: + /* Go through the slots in a node */ + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + ptr = ACCESS_ONCE(node->slots[slot]); + + if (assoc_array_ptr_is_meta(ptr) && node->back_pointer) + goto descend_to_node; + + if (!keyring_ptr_is_keyring(ptr)) continue; - if (key_task_permission(make_key_ref(key, ctx->possessed), + key = keyring_ptr_to_key(ptr); + + if (sp >= KEYRING_SEARCH_MAX_DEPTH) { + if (ctx->flags & KEYRING_SEARCH_DETECT_TOO_DEEP) { + ctx->result = ERR_PTR(-ELOOP); + return false; + } + goto not_this_keyring; + } + + /* Search a nested keyring */ + if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) && + key_task_permission(make_key_ref(key, ctx->possessed), ctx->cred, KEY_SEARCH) < 0) continue; /* stack the current position */ stack[sp].keyring = keyring; - stack[sp].keylist = keylist; - stack[sp].kix = kix; + stack[sp].node = node; + stack[sp].slot = slot; sp++; /* begin again with the new keyring */ keyring = key; - goto descend; + goto descend_to_keyring; + } + + /* We've dealt with all the slots in the current node, so now we need + * to ascend to the parent and continue processing there. + */ + ptr = ACCESS_ONCE(node->back_pointer); + slot = node->parent_slot; + + if (ptr && assoc_array_ptr_is_shortcut(ptr)) { + shortcut = assoc_array_ptr_to_shortcut(ptr); + smp_read_barrier_depends(); + ptr = ACCESS_ONCE(shortcut->back_pointer); + slot = shortcut->parent_slot; + } + if (!ptr) + goto not_this_keyring; + node = assoc_array_ptr_to_node(ptr); + smp_read_barrier_depends(); + slot++; + + /* If we've ascended to the root (zero backpointer), we must have just + * finished processing the leftmost branch rather than the root slots - + * so there can't be any more keyrings for us to find. + */ + if (node->back_pointer) { + kdebug("ascend %d", slot); + goto ascend_to_node; } - /* the keyring we're looking at was disqualified or didn't contain a - * matching key */ + /* The keyring we're looking at was disqualified or didn't contain a + * matching key. + */ not_this_keyring: - if (sp > 0) { - /* resume the processing of a keyring higher up in the tree */ - sp--; - keyring = stack[sp].keyring; - keylist = stack[sp].keylist; - kix = stack[sp].kix + 1; - goto ascend; + kdebug("not_this_keyring %d", sp); + if (sp <= 0) { + kleave(" = false"); + return false; } - key_ref = ERR_PTR(err); - goto error_2; + /* Resume the processing of a keyring higher up in the tree */ + sp--; + keyring = stack[sp].keyring; + node = stack[sp].node; + slot = stack[sp].slot + 1; + kdebug("ascend to %d [%d]", keyring->serial, slot); + goto ascend_to_node; - /* we found a viable match */ + /* We found a viable match */ found: - __key_get(key); - key->last_used_at = ctx->now.tv_sec; - keyring->last_used_at = ctx->now.tv_sec; - while (sp > 0) - stack[--sp].keyring->last_used_at = ctx->now.tv_sec; + key = key_ref_to_ptr(ctx->result); key_check(key); - key_ref = make_key_ref(key, ctx->possessed); -error_2: + if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { + key->last_used_at = ctx->now.tv_sec; + keyring->last_used_at = ctx->now.tv_sec; + while (sp > 0) + stack[--sp].keyring->last_used_at = ctx->now.tv_sec; + } + kleave(" = true"); + return true; +} + +/** + * keyring_search_aux - Search a keyring tree for a key matching some criteria + * @keyring_ref: A pointer to the keyring with possession indicator. + * @ctx: The keyring search context. + * + * Search the supplied keyring tree for a key that matches the criteria given. + * The root keyring and any linked keyrings must grant Search permission to the + * caller to be searchable and keys can only be found if they too grant Search + * to the caller. The possession flag on the root keyring pointer controls use + * of the possessor bits in permissions checking of the entire tree. In + * addition, the LSM gets to forbid keyring searches and key matches. + * + * The search is performed as a breadth-then-depth search up to the prescribed + * limit (KEYRING_SEARCH_MAX_DEPTH). + * + * Keys are matched to the type provided and are then filtered by the match + * function, which is given the description to use in any way it sees fit. The + * match function may use any attributes of a key that it wishes to to + * determine the match. Normally the match function from the key type would be + * used. + * + * RCU can be used to prevent the keyring key lists from disappearing without + * the need to take lots of locks. + * + * Returns a pointer to the found key and increments the key usage count if + * successful; -EAGAIN if no matching keys were found, or if expired or revoked + * keys were found; -ENOKEY if only negative keys were found; -ENOTDIR if the + * specified keyring wasn't a keyring. + * + * In the case of a successful return, the possession attribute from + * @keyring_ref is propagated to the returned key reference. + */ +key_ref_t keyring_search_aux(key_ref_t keyring_ref, + struct keyring_search_context *ctx) +{ + struct key *keyring; + long err; + + ctx->iterator = keyring_search_iterator; + ctx->possessed = is_key_possessed(keyring_ref); + ctx->result = ERR_PTR(-EAGAIN); + + keyring = key_ref_to_ptr(keyring_ref); + key_check(keyring); + + if (keyring->type != &key_type_keyring) + return ERR_PTR(-ENOTDIR); + + if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM)) { + err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH); + if (err < 0) + return ERR_PTR(err); + } + + rcu_read_lock(); + ctx->now = current_kernel_time(); + if (search_nested_keyrings(keyring, ctx)) + __key_get(key_ref_to_ptr(ctx->result)); rcu_read_unlock(); -error: - return key_ref; + return ctx->result; } /** @@ -499,7 +863,7 @@ error: * @description: The name of the keyring we want to find. * * As keyring_search_aux() above, but using the current task's credentials and - * type's default matching function. + * type's default matching function and preferred search method. */ key_ref_t keyring_search(key_ref_t keyring, struct key_type *type, @@ -523,58 +887,49 @@ key_ref_t keyring_search(key_ref_t keyring, EXPORT_SYMBOL(keyring_search); /* - * Search the given keyring only (no recursion). + * Search the given keyring for a key that might be updated. * * The caller must guarantee that the keyring is a keyring and that the - * permission is granted to search the keyring as no check is made here. - * - * RCU is used to make it unnecessary to lock the keyring key list here. + * permission is granted to modify the keyring as no check is made here. The + * caller must also hold a lock on the keyring semaphore. * * Returns a pointer to the found key with usage count incremented if - * successful and returns -ENOKEY if not found. Revoked and invalidated keys - * are skipped over. + * successful and returns NULL if not found. Revoked and invalidated keys are + * skipped over. * * If successful, the possession indicator is propagated from the keyring ref * to the returned key reference. */ -key_ref_t __keyring_search_one(key_ref_t keyring_ref, - const struct keyring_index_key *index_key) +key_ref_t find_key_to_update(key_ref_t keyring_ref, + const struct keyring_index_key *index_key) { - struct keyring_list *klist; struct key *keyring, *key; - bool possessed; - int nkeys, loop; + const void *object; keyring = key_ref_to_ptr(keyring_ref); - possessed = is_key_possessed(keyring_ref); - rcu_read_lock(); + kenter("{%d},{%s,%s}", + keyring->serial, index_key->type->name, index_key->description); - klist = rcu_dereference(keyring->payload.subscriptions); - if (klist) { - nkeys = klist->nkeys; - smp_rmb(); - for (loop = 0; loop < nkeys ; loop++) { - key = rcu_dereference(klist->keys[loop]); - if (key->type == index_key->type && - (!key->type->match || - key->type->match(key, index_key->description)) && - !(key->flags & ((1 << KEY_FLAG_INVALIDATED) | - (1 << KEY_FLAG_REVOKED))) - ) - goto found; - } - } + object = assoc_array_find(&keyring->keys, &keyring_assoc_array_ops, + index_key); - rcu_read_unlock(); - return ERR_PTR(-ENOKEY); + if (object) + goto found; + + kleave(" = NULL"); + return NULL; found: + key = keyring_ptr_to_key(object); + if (key->flags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED))) { + kleave(" = NULL [x]"); + return NULL; + } __key_get(key); - keyring->last_used_at = key->last_used_at = - current_kernel_time().tv_sec; - rcu_read_unlock(); - return make_key_ref(key, possessed); + kleave(" = {%d}", key->serial); + return make_key_ref(key, is_key_possessed(keyring_ref)); } /* @@ -637,6 +992,19 @@ out: return keyring; } +static int keyring_detect_cycle_iterator(const void *object, + void *iterator_data) +{ + struct keyring_search_context *ctx = iterator_data; + const struct key *key = keyring_ptr_to_key(object); + + kenter("{%d}", key->serial); + + BUG_ON(key != ctx->match_data); + ctx->result = ERR_PTR(-EDEADLK); + return 1; +} + /* * See if a cycle will will be created by inserting acyclic tree B in acyclic * tree A at the topmost level (ie: as a direct child of A). @@ -646,117 +1014,39 @@ out: */ static int keyring_detect_cycle(struct key *A, struct key *B) { - struct { - struct keyring_list *keylist; - int kix; - } stack[KEYRING_SEARCH_MAX_DEPTH]; - - struct keyring_list *keylist; - struct key *subtree, *key; - int sp, nkeys, kix, ret; + struct keyring_search_context ctx = { + .index_key = A->index_key, + .match_data = A, + .iterator = keyring_detect_cycle_iterator, + .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | + KEYRING_SEARCH_NO_STATE_CHECK | + KEYRING_SEARCH_NO_UPDATE_TIME | + KEYRING_SEARCH_NO_CHECK_PERM | + KEYRING_SEARCH_DETECT_TOO_DEEP), + }; rcu_read_lock(); - - ret = -EDEADLK; - if (A == B) - goto cycle_detected; - - subtree = B; - sp = 0; - - /* start processing a new keyring */ -descend: - if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) - goto not_this_keyring; - - keylist = rcu_dereference(subtree->payload.subscriptions); - if (!keylist) - goto not_this_keyring; - kix = 0; - -ascend: - /* iterate through the remaining keys in this keyring */ - nkeys = keylist->nkeys; - smp_rmb(); - for (; kix < nkeys; kix++) { - key = rcu_dereference(keylist->keys[kix]); - - if (key == A) - goto cycle_detected; - - /* recursively check nested keyrings */ - if (key->type == &key_type_keyring) { - if (sp >= KEYRING_SEARCH_MAX_DEPTH) - goto too_deep; - - /* stack the current position */ - stack[sp].keylist = keylist; - stack[sp].kix = kix; - sp++; - - /* begin again with the new keyring */ - subtree = key; - goto descend; - } - } - - /* the keyring we're looking at was disqualified or didn't contain a - * matching key */ -not_this_keyring: - if (sp > 0) { - /* resume the checking of a keyring higher up in the tree */ - sp--; - keylist = stack[sp].keylist; - kix = stack[sp].kix + 1; - goto ascend; - } - - ret = 0; /* no cycles detected */ - -error: + search_nested_keyrings(B, &ctx); rcu_read_unlock(); - return ret; - -too_deep: - ret = -ELOOP; - goto error; - -cycle_detected: - ret = -EDEADLK; - goto error; -} - -/* - * Dispose of a keyring list after the RCU grace period, freeing the unlinked - * key - */ -static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) -{ - struct keyring_list *klist = - container_of(rcu, struct keyring_list, rcu); - - if (klist->delkey != USHRT_MAX) - key_put(rcu_access_pointer(klist->keys[klist->delkey])); - kfree(klist); + return PTR_ERR(ctx.result) == -EAGAIN ? 0 : PTR_ERR(ctx.result); } /* * Preallocate memory so that a key can be linked into to a keyring. */ -int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, - unsigned long *_prealloc) +int __key_link_begin(struct key *keyring, + const struct keyring_index_key *index_key, + struct assoc_array_edit **_edit) __acquires(&keyring->sem) __acquires(&keyring_serialise_link_sem) { - struct keyring_list *klist, *nklist; - unsigned long prealloc; - unsigned max; - time_t lowest_lru; - size_t size; - int loop, lru, ret; + struct assoc_array_edit *edit; + int ret; kenter("%d,%s,%s,", - key_serial(keyring), index_key->type->name, index_key->description); + keyring->serial, index_key->type->name, index_key->description); + + BUG_ON(index_key->desc_len == 0); if (keyring->type != &key_type_keyring) return -ENOTDIR; @@ -772,88 +1062,25 @@ int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_ if (index_key->type == &key_type_keyring) down_write(&keyring_serialise_link_sem); - klist = rcu_dereference_locked_keyring(keyring); - - /* see if there's a matching key we can displace */ - lru = -1; - if (klist && klist->nkeys > 0) { - lowest_lru = TIME_T_MAX; - for (loop = klist->nkeys - 1; loop >= 0; loop--) { - struct key *key = rcu_deref_link_locked(klist, loop, - keyring); - if (key->type == index_key->type && - strcmp(key->description, index_key->description) == 0) { - /* Found a match - we'll replace the link with - * one to the new key. We record the slot - * position. - */ - klist->delkey = loop; - prealloc = 0; - goto done; - } - if (key->last_used_at < lowest_lru) { - lowest_lru = key->last_used_at; - lru = loop; - } - } - } - - /* If the keyring is full then do an LRU discard */ - if (klist && - klist->nkeys == klist->maxkeys && - klist->maxkeys >= MAX_KEYRING_LINKS) { - kdebug("LRU discard %d\n", lru); - klist->delkey = lru; - prealloc = 0; - goto done; - } - /* check that we aren't going to overrun the user's quota */ ret = key_payload_reserve(keyring, keyring->datalen + KEYQUOTA_LINK_BYTES); if (ret < 0) goto error_sem; - if (klist && klist->nkeys < klist->maxkeys) { - /* there's sufficient slack space to append directly */ - klist->delkey = klist->nkeys; - prealloc = KEY_LINK_FIXQUOTA; - } else { - /* grow the key list */ - max = 4; - if (klist) { - max += klist->maxkeys; - if (max > MAX_KEYRING_LINKS) - max = MAX_KEYRING_LINKS; - BUG_ON(max <= klist->maxkeys); - } - - size = sizeof(*klist) + sizeof(struct key *) * max; - - ret = -ENOMEM; - nklist = kmalloc(size, GFP_KERNEL); - if (!nklist) - goto error_quota; - - nklist->maxkeys = max; - if (klist) { - memcpy(nklist->keys, klist->keys, - sizeof(struct key *) * klist->nkeys); - nklist->delkey = klist->nkeys; - nklist->nkeys = klist->nkeys + 1; - klist->delkey = USHRT_MAX; - } else { - nklist->nkeys = 1; - nklist->delkey = 0; - } - - /* add the key into the new space */ - RCU_INIT_POINTER(nklist->keys[nklist->delkey], NULL); - prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA; + /* Create an edit script that will insert/replace the key in the + * keyring tree. + */ + edit = assoc_array_insert(&keyring->keys, + &keyring_assoc_array_ops, + index_key, + NULL); + if (IS_ERR(edit)) { + ret = PTR_ERR(edit); + goto error_quota; } -done: - *_prealloc = prealloc; + *_edit = edit; kleave(" = 0"); return 0; @@ -893,60 +1120,12 @@ int __key_link_check_live_key(struct key *keyring, struct key *key) * holds at most one link to any given key of a particular type+description * combination. */ -void __key_link(struct key *keyring, struct key *key, - unsigned long *_prealloc) +void __key_link(struct key *key, struct assoc_array_edit **_edit) { - struct keyring_list *klist, *nklist; - struct key *discard; - - nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA); - *_prealloc = 0; - - kenter("%d,%d,%p", keyring->serial, key->serial, nklist); - - klist = rcu_dereference_locked_keyring(keyring); - __key_get(key); - keyring->last_used_at = key->last_used_at = - current_kernel_time().tv_sec; - - /* there's a matching key we can displace or an empty slot in a newly - * allocated list we can fill */ - if (nklist) { - kdebug("reissue %hu/%hu/%hu", - nklist->delkey, nklist->nkeys, nklist->maxkeys); - - RCU_INIT_POINTER(nklist->keys[nklist->delkey], key); - - rcu_assign_pointer(keyring->payload.subscriptions, nklist); - - /* dispose of the old keyring list and, if there was one, the - * displaced key */ - if (klist) { - kdebug("dispose %hu/%hu/%hu", - klist->delkey, klist->nkeys, klist->maxkeys); - call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); - } - } else if (klist->delkey < klist->nkeys) { - kdebug("replace %hu/%hu/%hu", - klist->delkey, klist->nkeys, klist->maxkeys); - - discard = rcu_dereference_protected( - klist->keys[klist->delkey], - rwsem_is_locked(&keyring->sem)); - rcu_assign_pointer(klist->keys[klist->delkey], key); - /* The garbage collector will take care of RCU - * synchronisation */ - key_put(discard); - } else { - /* there's sufficient slack space to append directly */ - kdebug("append %hu/%hu/%hu", - klist->delkey, klist->nkeys, klist->maxkeys); - - RCU_INIT_POINTER(klist->keys[klist->delkey], key); - smp_wmb(); - klist->nkeys++; - } + assoc_array_insert_set_object(*_edit, keyring_key_to_ptr(key)); + assoc_array_apply_edit(*_edit); + *_edit = NULL; } /* @@ -956,23 +1135,20 @@ void __key_link(struct key *keyring, struct key *key, */ void __key_link_end(struct key *keyring, const struct keyring_index_key *index_key, - unsigned long prealloc) + struct assoc_array_edit *edit) __releases(&keyring->sem) __releases(&keyring_serialise_link_sem) { BUG_ON(index_key->type == NULL); - BUG_ON(index_key->type->name == NULL); - kenter("%d,%s,%lx", keyring->serial, index_key->type->name, prealloc); + kenter("%d,%s,", keyring->serial, index_key->type->name); if (index_key->type == &key_type_keyring) up_write(&keyring_serialise_link_sem); - if (prealloc) { - if (prealloc & KEY_LINK_FIXQUOTA) - key_payload_reserve(keyring, - keyring->datalen - - KEYQUOTA_LINK_BYTES); - kfree((struct keyring_list *)(prealloc & ~KEY_LINK_FIXQUOTA)); + if (edit) { + key_payload_reserve(keyring, + keyring->datalen - KEYQUOTA_LINK_BYTES); + assoc_array_cancel_edit(edit); } up_write(&keyring->sem); } @@ -999,20 +1175,24 @@ void __key_link_end(struct key *keyring, */ int key_link(struct key *keyring, struct key *key) { - unsigned long prealloc; + struct assoc_array_edit *edit; int ret; + kenter("{%d,%d}", keyring->serial, atomic_read(&keyring->usage)); + key_check(keyring); key_check(key); - ret = __key_link_begin(keyring, &key->index_key, &prealloc); + ret = __key_link_begin(keyring, &key->index_key, &edit); if (ret == 0) { + kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); ret = __key_link_check_live_key(keyring, key); if (ret == 0) - __key_link(keyring, key, &prealloc); - __key_link_end(keyring, &key->index_key, prealloc); + __key_link(key, &edit); + __key_link_end(keyring, &key->index_key, edit); } + kleave(" = %d {%d,%d}", ret, keyring->serial, atomic_read(&keyring->usage)); return ret; } EXPORT_SYMBOL(key_link); @@ -1036,90 +1216,36 @@ EXPORT_SYMBOL(key_link); */ int key_unlink(struct key *keyring, struct key *key) { - struct keyring_list *klist, *nklist; - int loop, ret; + struct assoc_array_edit *edit; + int ret; key_check(keyring); key_check(key); - ret = -ENOTDIR; if (keyring->type != &key_type_keyring) - goto error; + return -ENOTDIR; down_write(&keyring->sem); - klist = rcu_dereference_locked_keyring(keyring); - if (klist) { - /* search the keyring for the key */ - for (loop = 0; loop < klist->nkeys; loop++) - if (rcu_access_pointer(klist->keys[loop]) == key) - goto key_is_present; + edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, + &key->index_key); + if (IS_ERR(edit)) { + ret = PTR_ERR(edit); + goto error; } - - up_write(&keyring->sem); ret = -ENOENT; - goto error; - -key_is_present: - /* we need to copy the key list for RCU purposes */ - nklist = kmalloc(sizeof(*klist) + - sizeof(struct key *) * klist->maxkeys, - GFP_KERNEL); - if (!nklist) - goto nomem; - nklist->maxkeys = klist->maxkeys; - nklist->nkeys = klist->nkeys - 1; - - if (loop > 0) - memcpy(&nklist->keys[0], - &klist->keys[0], - loop * sizeof(struct key *)); - - if (loop < nklist->nkeys) - memcpy(&nklist->keys[loop], - &klist->keys[loop + 1], - (nklist->nkeys - loop) * sizeof(struct key *)); - - /* adjust the user's quota */ - key_payload_reserve(keyring, - keyring->datalen - KEYQUOTA_LINK_BYTES); - - rcu_assign_pointer(keyring->payload.subscriptions, nklist); - - up_write(&keyring->sem); - - /* schedule for later cleanup */ - klist->delkey = loop; - call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); + if (edit == NULL) + goto error; + assoc_array_apply_edit(edit); ret = 0; error: - return ret; -nomem: - ret = -ENOMEM; up_write(&keyring->sem); - goto error; + return ret; } EXPORT_SYMBOL(key_unlink); -/* - * Dispose of a keyring list after the RCU grace period, releasing the keys it - * links to. - */ -static void keyring_clear_rcu_disposal(struct rcu_head *rcu) -{ - struct keyring_list *klist; - int loop; - - klist = container_of(rcu, struct keyring_list, rcu); - - for (loop = klist->nkeys - 1; loop >= 0; loop--) - key_put(rcu_access_pointer(klist->keys[loop])); - - kfree(klist); -} - /** * keyring_clear - Clear a keyring * @keyring: The keyring to clear. @@ -1130,33 +1256,25 @@ static void keyring_clear_rcu_disposal(struct rcu_head *rcu) */ int keyring_clear(struct key *keyring) { - struct keyring_list *klist; + struct assoc_array_edit *edit; int ret; - ret = -ENOTDIR; - if (keyring->type == &key_type_keyring) { - /* detach the pointer block with the locks held */ - down_write(&keyring->sem); - - klist = rcu_dereference_locked_keyring(keyring); - if (klist) { - /* adjust the quota */ - key_payload_reserve(keyring, - sizeof(struct keyring_list)); - - rcu_assign_pointer(keyring->payload.subscriptions, - NULL); - } - - up_write(&keyring->sem); + if (keyring->type != &key_type_keyring) + return -ENOTDIR; - /* free the keys after the locks have been dropped */ - if (klist) - call_rcu(&klist->rcu, keyring_clear_rcu_disposal); + down_write(&keyring->sem); + edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops); + if (IS_ERR(edit)) { + ret = PTR_ERR(edit); + } else { + if (edit) + assoc_array_apply_edit(edit); + key_payload_reserve(keyring, 0); ret = 0; } + up_write(&keyring->sem); return ret; } EXPORT_SYMBOL(keyring_clear); @@ -1168,17 +1286,25 @@ EXPORT_SYMBOL(keyring_clear); */ static void keyring_revoke(struct key *keyring) { - struct keyring_list *klist; + struct assoc_array_edit *edit; - klist = rcu_dereference_locked_keyring(keyring); + edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops); + if (!IS_ERR(edit)) { + if (edit) + assoc_array_apply_edit(edit); + key_payload_reserve(keyring, 0); + } +} - /* adjust the quota */ - key_payload_reserve(keyring, 0); +static bool gc_iterator(void *object, void *iterator_data) +{ + struct key *key = keyring_ptr_to_key(object); + time_t *limit = iterator_data; - if (klist) { - rcu_assign_pointer(keyring->payload.subscriptions, NULL); - call_rcu(&klist->rcu, keyring_clear_rcu_disposal); - } + if (key_is_dead(key, *limit)) + return false; + key_get(key); + return true; } /* @@ -1191,88 +1317,12 @@ static void keyring_revoke(struct key *keyring) */ void keyring_gc(struct key *keyring, time_t limit) { - struct keyring_list *klist, *new; - struct key *key; - int loop, keep, max; - kenter("{%x,%s}", key_serial(keyring), keyring->description); down_write(&keyring->sem); - - klist = rcu_dereference_locked_keyring(keyring); - if (!klist) - goto no_klist; - - /* work out how many subscriptions we're keeping */ - keep = 0; - for (loop = klist->nkeys - 1; loop >= 0; loop--) - if (!key_is_dead(rcu_deref_link_locked(klist, loop, keyring), - limit)) - keep++; - - if (keep == klist->nkeys) - goto just_return; - - /* allocate a new keyring payload */ - max = roundup(keep, 4); - new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *), - GFP_KERNEL); - if (!new) - goto nomem; - new->maxkeys = max; - new->nkeys = 0; - new->delkey = 0; - - /* install the live keys - * - must take care as expired keys may be updated back to life - */ - keep = 0; - for (loop = klist->nkeys - 1; loop >= 0; loop--) { - key = rcu_deref_link_locked(klist, loop, keyring); - if (!key_is_dead(key, limit)) { - if (keep >= max) - goto discard_new; - RCU_INIT_POINTER(new->keys[keep++], key_get(key)); - } - } - new->nkeys = keep; - - /* adjust the quota */ - key_payload_reserve(keyring, - sizeof(struct keyring_list) + - KEYQUOTA_LINK_BYTES * keep); - - if (keep == 0) { - rcu_assign_pointer(keyring->payload.subscriptions, NULL); - kfree(new); - } else { - rcu_assign_pointer(keyring->payload.subscriptions, new); - } - - up_write(&keyring->sem); - - call_rcu(&klist->rcu, keyring_clear_rcu_disposal); - kleave(" [yes]"); - return; - -discard_new: - new->nkeys = keep; - keyring_clear_rcu_disposal(&new->rcu); + assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops, + gc_iterator, &limit); up_write(&keyring->sem); - kleave(" [discard]"); - return; -just_return: - up_write(&keyring->sem); - kleave(" [no dead]"); - return; - -no_klist: - up_write(&keyring->sem); - kleave(" [no_klist]"); - return; - -nomem: - up_write(&keyring->sem); - kleave(" [oom]"); + kleave(""); } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index ab75df4745af..df94827103d0 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -351,7 +351,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx, struct key_user *user, struct key **_key) { - unsigned long prealloc; + struct assoc_array_edit *edit; struct key *key; key_perm_t perm; key_ref_t key_ref; @@ -380,7 +380,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); if (dest_keyring) { - ret = __key_link_begin(dest_keyring, &ctx->index_key, &prealloc); + ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit); if (ret < 0) goto link_prealloc_failed; } @@ -395,11 +395,11 @@ static int construct_alloc_key(struct keyring_search_context *ctx, goto key_already_present; if (dest_keyring) - __key_link(dest_keyring, key, &prealloc); + __key_link(key, &edit); mutex_unlock(&key_construction_mutex); if (dest_keyring) - __key_link_end(dest_keyring, &ctx->index_key, prealloc); + __key_link_end(dest_keyring, &ctx->index_key, edit); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); @@ -414,8 +414,8 @@ key_already_present: if (dest_keyring) { ret = __key_link_check_live_key(dest_keyring, key); if (ret == 0) - __key_link(dest_keyring, key, &prealloc); - __key_link_end(dest_keyring, &ctx->index_key, prealloc); + __key_link(key, &edit); + __key_link_end(dest_keyring, &ctx->index_key, edit); if (ret < 0) goto link_check_failed; } -- cgit From ab3c3587f8cda9083209a61dbe3a4407d3cada10 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:18 +0100 Subject: KEYS: Implement a big key type that can save to tmpfs Implement a big key type that can save its contents to tmpfs and thus swapspace when memory is tight. This is useful for Kerberos ticket caches. Signed-off-by: David Howells Tested-by: Simo Sorce --- include/keys/big_key-type.h | 25 ++++++ include/linux/key.h | 1 + security/keys/Kconfig | 11 +++ security/keys/Makefile | 1 + security/keys/big_key.c | 204 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 include/keys/big_key-type.h create mode 100644 security/keys/big_key.c (limited to 'include') diff --git a/include/keys/big_key-type.h b/include/keys/big_key-type.h new file mode 100644 index 000000000000..d69bc8af3292 --- /dev/null +++ b/include/keys/big_key-type.h @@ -0,0 +1,25 @@ +/* Big capacity key type. + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _KEYS_BIG_KEY_TYPE_H +#define _KEYS_BIG_KEY_TYPE_H + +#include + +extern struct key_type key_type_big_key; + +extern int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep); +extern void big_key_revoke(struct key *key); +extern void big_key_destroy(struct key *key); +extern void big_key_describe(const struct key *big_key, struct seq_file *m); +extern long big_key_read(const struct key *key, char __user *buffer, size_t buflen); + +#endif /* _KEYS_BIG_KEY_TYPE_H */ diff --git a/include/linux/key.h b/include/linux/key.h index 2417f789d29b..010dbb618aca 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -201,6 +201,7 @@ struct key { unsigned long value; void __rcu *rcudata; void *data; + void *data2[2]; } payload; struct assoc_array keys; }; diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 15e0dfe8c80f..b56362275ec8 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -20,6 +20,17 @@ config KEYS If you are unsure as to whether this is required, answer N. +config BIG_KEYS + tristate "Large payload keys" + depends on KEYS + depends on TMPFS + help + This option provides support for holding large keys within the kernel + (for example Kerberos ticket caches). The data may be stored out to + swapspace by tmpfs. + + If you are unsure as to whether this is required, answer N. + config TRUSTED_KEYS tristate "TRUSTED KEYS" depends on KEYS && TCG_TPM diff --git a/security/keys/Makefile b/security/keys/Makefile index 504aaa008388..c487c77a00be 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -22,5 +22,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o # # Key types # +obj-$(CONFIG_BIG_KEYS) += big_key.o obj-$(CONFIG_TRUSTED_KEYS) += trusted.o obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ diff --git a/security/keys/big_key.c b/security/keys/big_key.c new file mode 100644 index 000000000000..5f9defc4a807 --- /dev/null +++ b/security/keys/big_key.c @@ -0,0 +1,204 @@ +/* Large capacity key type + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +/* + * If the data is under this limit, there's no point creating a shm file to + * hold it as the permanently resident metadata for the shmem fs will be at + * least as large as the data. + */ +#define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry)) + +/* + * big_key defined keys take an arbitrary string as the description and an + * arbitrary blob of data as the payload + */ +struct key_type key_type_big_key = { + .name = "big_key", + .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, + .instantiate = big_key_instantiate, + .match = user_match, + .revoke = big_key_revoke, + .destroy = big_key_destroy, + .describe = big_key_describe, + .read = big_key_read, +}; + +/* + * Instantiate a big key + */ +int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) +{ + struct path *path = (struct path *)&key->payload.data2; + struct file *file; + ssize_t written; + size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; + if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) + goto error; + + /* Set an arbitrary quota */ + ret = key_payload_reserve(key, 16); + if (ret < 0) + goto error; + + key->type_data.x[1] = datalen; + + if (datalen > BIG_KEY_FILE_THRESHOLD) { + /* Create a shmem file to store the data in. This will permit the data + * to be swapped out if needed. + * + * TODO: Encrypt the stored data with a temporary key. + */ + file = shmem_file_setup("", datalen, 0); + if (IS_ERR(file)) + goto err_quota; + + written = kernel_write(file, prep->data, prep->datalen, 0); + if (written != datalen) { + if (written >= 0) + ret = -ENOMEM; + goto err_fput; + } + + /* Pin the mount and dentry to the key so that we can open it again + * later + */ + *path = file->f_path; + path_get(path); + fput(file); + } else { + /* Just store the data in a buffer */ + void *data = kmalloc(datalen, GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err_quota; + } + + key->payload.data = memcpy(data, prep->data, prep->datalen); + } + return 0; + +err_fput: + fput(file); +err_quota: + key_payload_reserve(key, 0); +error: + return ret; +} + +/* + * dispose of the links from a revoked keyring + * - called with the key sem write-locked + */ +void big_key_revoke(struct key *key) +{ + struct path *path = (struct path *)&key->payload.data2; + + /* clear the quota */ + key_payload_reserve(key, 0); + if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) + vfs_truncate(path, 0); +} + +/* + * dispose of the data dangling from the corpse of a big_key key + */ +void big_key_destroy(struct key *key) +{ + if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) { + struct path *path = (struct path *)&key->payload.data2; + path_put(path); + path->mnt = NULL; + path->dentry = NULL; + } else { + kfree(key->payload.data); + key->payload.data = NULL; + } +} + +/* + * describe the big_key key + */ +void big_key_describe(const struct key *key, struct seq_file *m) +{ + unsigned long datalen = key->type_data.x[1]; + + seq_puts(m, key->description); + + if (key_is_instantiated(key)) + seq_printf(m, ": %lu [%s]", + datalen, + datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); +} + +/* + * read the key data + * - the key's semaphore is read-locked + */ +long big_key_read(const struct key *key, char __user *buffer, size_t buflen) +{ + unsigned long datalen = key->type_data.x[1]; + long ret; + + if (!buffer || buflen < datalen) + return datalen; + + if (datalen > BIG_KEY_FILE_THRESHOLD) { + struct path *path = (struct path *)&key->payload.data2; + struct file *file; + loff_t pos; + + file = dentry_open(path, O_RDONLY, current_cred()); + if (IS_ERR(file)) + return PTR_ERR(file); + + pos = 0; + ret = vfs_read(file, buffer, datalen, &pos); + fput(file); + if (ret >= 0 && ret != datalen) + ret = -EIO; + } else { + ret = datalen; + if (copy_to_user(buffer, key->payload.data, datalen) != 0) + ret = -EFAULT; + } + + return ret; +} + +/* + * Module stuff + */ +static int __init big_key_init(void) +{ + return register_key_type(&key_type_big_key); +} + +static void __exit big_key_cleanup(void) +{ + unregister_key_type(&key_type_big_key); +} + +module_init(big_key_init); +module_exit(big_key_cleanup); -- cgit From f36f8c75ae2e7d4da34f4c908cebdb4aa42c977e Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:19 +0100 Subject: KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches Add support for per-user_namespace registers of persistent per-UID kerberos caches held within the kernel. This allows the kerberos cache to be retained beyond the life of all a user's processes so that the user's cron jobs can work. The kerberos cache is envisioned as a keyring/key tree looking something like: struct user_namespace \___ .krb_cache keyring - The register \___ _krb.0 keyring - Root's Kerberos cache \___ _krb.5000 keyring - User 5000's Kerberos cache \___ _krb.5001 keyring - User 5001's Kerberos cache \___ tkt785 big_key - A ccache blob \___ tkt12345 big_key - Another ccache blob Or possibly: struct user_namespace \___ .krb_cache keyring - The register \___ _krb.0 keyring - Root's Kerberos cache \___ _krb.5000 keyring - User 5000's Kerberos cache \___ _krb.5001 keyring - User 5001's Kerberos cache \___ tkt785 keyring - A ccache \___ krbtgt/REDHAT.COM@REDHAT.COM big_key \___ http/REDHAT.COM@REDHAT.COM user \___ afs/REDHAT.COM@REDHAT.COM user \___ nfs/REDHAT.COM@REDHAT.COM user \___ krbtgt/KERNEL.ORG@KERNEL.ORG big_key \___ http/KERNEL.ORG@KERNEL.ORG big_key What goes into a particular Kerberos cache is entirely up to userspace. Kernel support is limited to giving you the Kerberos cache keyring that you want. The user asks for their Kerberos cache by: krb_cache = keyctl_get_krbcache(uid, dest_keyring); The uid is -1 or the user's own UID for the user's own cache or the uid of some other user's cache (requires CAP_SETUID). This permits rpc.gssd or whatever to mess with the cache. The cache returned is a keyring named "_krb." that the possessor can read, search, clear, invalidate, unlink from and add links to. Active LSMs get a chance to rule on whether the caller is permitted to make a link. Each uid's cache keyring is created when it first accessed and is given a timeout that is extended each time this function is called so that the keyring goes away after a while. The timeout is configurable by sysctl but defaults to three days. Each user_namespace struct gets a lazily-created keyring that serves as the register. The cache keyrings are added to it. This means that standard key search and garbage collection facilities are available. The user_namespace struct's register goes away when it does and anything left in it is then automatically gc'd. Signed-off-by: David Howells Tested-by: Simo Sorce cc: Serge E. Hallyn cc: Eric W. Biederman --- include/linux/user_namespace.h | 6 ++ include/uapi/linux/keyctl.h | 1 + kernel/user.c | 4 + kernel/user_namespace.c | 6 ++ security/keys/Kconfig | 17 +++++ security/keys/Makefile | 1 + security/keys/compat.c | 3 + security/keys/internal.h | 9 +++ security/keys/keyctl.c | 3 + security/keys/persistent.c | 169 +++++++++++++++++++++++++++++++++++++++++ security/keys/sysctl.c | 11 +++ 11 files changed, 230 insertions(+) create mode 100644 security/keys/persistent.c (limited to 'include') diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 4db29859464f..4836ba3c1cd8 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -27,6 +27,12 @@ struct user_namespace { kuid_t owner; kgid_t group; unsigned int proc_inum; + + /* Register of per-UID persistent keyrings for this namespace */ +#ifdef CONFIG_PERSISTENT_KEYRINGS + struct key *persistent_keyring_register; + struct rw_semaphore persistent_keyring_register_sem; +#endif }; extern struct user_namespace init_user_ns; diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index c9b7f4faf97a..840cb990abe2 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -56,5 +56,6 @@ #define KEYCTL_REJECT 19 /* reject a partially constructed key */ #define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */ #define KEYCTL_INVALIDATE 21 /* invalidate a key */ +#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ #endif /* _LINUX_KEYCTL_H */ diff --git a/kernel/user.c b/kernel/user.c index 5bbb91988e69..a3a0dbfda329 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -51,6 +51,10 @@ struct user_namespace init_user_ns = { .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, .proc_inum = PROC_USER_INIT_INO, +#ifdef CONFIG_KEYS_KERBEROS_CACHE + .krb_cache_register_sem = + __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem), +#endif }; EXPORT_SYMBOL_GPL(init_user_ns); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 13fb1134ba58..240fb62cf394 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -101,6 +101,9 @@ int create_user_ns(struct cred *new) set_cred_user_ns(new, ns); +#ifdef CONFIG_PERSISTENT_KEYRINGS + init_rwsem(&ns->persistent_keyring_register_sem); +#endif return 0; } @@ -130,6 +133,9 @@ void free_user_ns(struct user_namespace *ns) do { parent = ns->parent; +#ifdef CONFIG_PERSISTENT_KEYRINGS + key_put(ns->persistent_keyring_register); +#endif proc_free_inum(ns->proc_inum); kmem_cache_free(user_ns_cachep, ns); ns = parent; diff --git a/security/keys/Kconfig b/security/keys/Kconfig index b56362275ec8..53d8748c9564 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -20,6 +20,23 @@ config KEYS If you are unsure as to whether this is required, answer N. +config PERSISTENT_KEYRINGS + bool "Enable register of persistent per-UID keyrings" + depends on KEYS + help + This option provides a register of persistent per-UID keyrings, + primarily aimed at Kerberos key storage. The keyrings are persistent + in the sense that they stay around after all processes of that UID + have exited, not that they survive the machine being rebooted. + + A particular keyring may be accessed by either the user whose keyring + it is or by a process with administrative privileges. The active + LSMs gets to rule on which admin-level processes get to access the + cache. + + Keyrings are created and added into the register upon demand and get + removed if they expire (a default timeout is set upon creation). + config BIG_KEYS tristate "Large payload keys" depends on KEYS diff --git a/security/keys/Makefile b/security/keys/Makefile index c487c77a00be..dfb3a7bededf 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -18,6 +18,7 @@ obj-y := \ obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o +obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o # # Key types diff --git a/security/keys/compat.c b/security/keys/compat.c index d65fa7fa29ba..bbd32c729dbb 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -138,6 +138,9 @@ asmlinkage long compat_sys_keyctl(u32 option, case KEYCTL_INVALIDATE: return keyctl_invalidate_key(arg2); + case KEYCTL_GET_PERSISTENT: + return keyctl_get_persistent(arg2, arg3); + default: return -EOPNOTSUPP; } diff --git a/security/keys/internal.h b/security/keys/internal.h index 581c6f688352..80b2aac4f50c 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -255,6 +255,15 @@ extern long keyctl_invalidate_key(key_serial_t); extern long keyctl_instantiate_key_common(key_serial_t, const struct iovec *, unsigned, size_t, key_serial_t); +#ifdef CONFIG_PERSISTENT_KEYRINGS +extern long keyctl_get_persistent(uid_t, key_serial_t); +extern unsigned persistent_keyring_expiry; +#else +static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring) +{ + return -EOPNOTSUPP; +} +#endif /* * Debugging key validation diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 33cfd27b4de2..cee72ce64222 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1667,6 +1667,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, case KEYCTL_INVALIDATE: return keyctl_invalidate_key((key_serial_t) arg2); + case KEYCTL_GET_PERSISTENT: + return keyctl_get_persistent((uid_t)arg2, (key_serial_t)arg3); + default: return -EOPNOTSUPP; } diff --git a/security/keys/persistent.c b/security/keys/persistent.c new file mode 100644 index 000000000000..82f4957a7acf --- /dev/null +++ b/security/keys/persistent.c @@ -0,0 +1,169 @@ +/* General persistent per-UID keyrings register + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include "internal.h" + +unsigned persistent_keyring_expiry = 3 * 24 * 3600; /* Expire after 3 days of non-use */ + +/* + * Create the persistent keyring register for the current user namespace. + * + * Called with the namespace's sem locked for writing. + */ +static int key_create_persistent_register(struct user_namespace *ns) +{ + struct key *reg = keyring_alloc(".persistent_register", + KUIDT_INIT(0), KGIDT_INIT(0), + current_cred(), + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + ns->persistent_keyring_register = reg; + return 0; +} + +/* + * Create the persistent keyring for the specified user. + * + * Called with the namespace's sem locked for writing. + */ +static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid, + struct keyring_index_key *index_key) +{ + struct key *persistent; + key_ref_t reg_ref, persistent_ref; + + if (!ns->persistent_keyring_register) { + long err = key_create_persistent_register(ns); + if (err < 0) + return ERR_PTR(err); + } else { + reg_ref = make_key_ref(ns->persistent_keyring_register, true); + persistent_ref = find_key_to_update(reg_ref, index_key); + if (persistent_ref) + return persistent_ref; + } + + persistent = keyring_alloc(index_key->description, + uid, INVALID_GID, current_cred(), + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA, + ns->persistent_keyring_register); + if (IS_ERR(persistent)) + return ERR_CAST(persistent); + + return make_key_ref(persistent, true); +} + +/* + * Get the persistent keyring for a specific UID and link it to the nominated + * keyring. + */ +static long key_get_persistent(struct user_namespace *ns, kuid_t uid, + key_ref_t dest_ref) +{ + struct keyring_index_key index_key; + struct key *persistent; + key_ref_t reg_ref, persistent_ref; + char buf[32]; + long ret; + + /* Look in the register if it exists */ + index_key.type = &key_type_keyring; + index_key.description = buf; + index_key.desc_len = sprintf(buf, "_persistent.%u", from_kuid(ns, uid)); + + if (ns->persistent_keyring_register) { + reg_ref = make_key_ref(ns->persistent_keyring_register, true); + down_read(&ns->persistent_keyring_register_sem); + persistent_ref = find_key_to_update(reg_ref, &index_key); + up_read(&ns->persistent_keyring_register_sem); + + if (persistent_ref) + goto found; + } + + /* It wasn't in the register, so we'll need to create it. We might + * also need to create the register. + */ + down_write(&ns->persistent_keyring_register_sem); + persistent_ref = key_create_persistent(ns, uid, &index_key); + up_write(&ns->persistent_keyring_register_sem); + if (!IS_ERR(persistent_ref)) + goto found; + + return PTR_ERR(persistent_ref); + +found: + ret = key_task_permission(persistent_ref, current_cred(), KEY_LINK); + if (ret == 0) { + persistent = key_ref_to_ptr(persistent_ref); + ret = key_link(key_ref_to_ptr(dest_ref), persistent); + if (ret == 0) { + key_set_timeout(persistent, persistent_keyring_expiry); + ret = persistent->serial; + } + } + + key_ref_put(persistent_ref); + return ret; +} + +/* + * Get the persistent keyring for a specific UID and link it to the nominated + * keyring. + */ +long keyctl_get_persistent(uid_t _uid, key_serial_t destid) +{ + struct user_namespace *ns = current_user_ns(); + key_ref_t dest_ref; + kuid_t uid; + long ret; + + /* -1 indicates the current user */ + if (_uid == (uid_t)-1) { + uid = current_uid(); + } else { + uid = make_kuid(ns, _uid); + if (!uid_valid(uid)) + return -EINVAL; + + /* You can only see your own persistent cache if you're not + * sufficiently privileged. + */ + if (uid_eq(uid, current_uid()) && + uid_eq(uid, current_suid()) && + uid_eq(uid, current_euid()) && + uid_eq(uid, current_fsuid()) && + !ns_capable(ns, CAP_SETUID)) + return -EPERM; + } + + /* There must be a destination keyring */ + dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_WRITE); + if (IS_ERR(dest_ref)) + return PTR_ERR(dest_ref); + if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) { + ret = -ENOTDIR; + goto out_put_dest; + } + + ret = key_get_persistent(ns, uid, dest_ref); + +out_put_dest: + key_ref_put(dest_ref); + return ret; +} diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c index ee32d181764a..8c0af08760c8 100644 --- a/security/keys/sysctl.c +++ b/security/keys/sysctl.c @@ -61,5 +61,16 @@ ctl_table key_sysctls[] = { .extra1 = (void *) &zero, .extra2 = (void *) &max, }, +#ifdef CONFIG_PERSISTENT_KEYRINGS + { + .procname = "persistent_keyring_expiry", + .data = &persistent_keyring_expiry, + .maxlen = sizeof(unsigned), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = (void *) &zero, + .extra2 = (void *) &max, + }, +#endif { } }; -- cgit From 7f6db1717235bd45d265766dad53c10d30899d41 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 15 Aug 2013 11:59:23 -0600 Subject: iommu: Add event tracing feature to iommu Add tracing feature to iommu to report various iommu events. Classes iommu_group, iommu_device, and iommu_map_unmap are defined. iommu_group class events can be enabled to trigger when devices get added to and removed from an iommu group. Trace information includes iommu group id and device name. iommu:add_device_to_group iommu:remove_device_from_group iommu_device class events can be enabled to trigger when devices are attached to and detached from a domain. Trace information includes device name. iommu:attach_device_to_domain iommu:detach_device_from_domain iommu_map_unmap class events can be enabled to trigger when iommu map and unmap iommu ops. Trace information includes iova, physical address (map event only), and size. iommu:map iommu:unmap Signed-off-by: Shuah Khan Signed-off-by: Joerg Roedel --- drivers/iommu/Makefile | 1 + drivers/iommu/iommu-traces.c | 24 ++++++++ drivers/iommu/iommu.c | 1 + include/trace/events/iommu.h | 129 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 drivers/iommu/iommu-traces.c create mode 100644 include/trace/events/iommu.h (limited to 'include') diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 14c1f474cf11..5d58bf16e9e3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_IOMMU_API) += iommu.o +obj-$(CONFIG_IOMMU_API) += iommu-traces.o obj-$(CONFIG_OF_IOMMU) += of_iommu.o obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c new file mode 100644 index 000000000000..a2af60f31810 --- /dev/null +++ b/drivers/iommu/iommu-traces.c @@ -0,0 +1,24 @@ +/* + * iommu trace points + * + * Copyright (C) 2013 Shuah Khan + * + */ + +#include +#include + +#define CREATE_TRACE_POINTS +#include + +/* iommu_group_event */ +EXPORT_TRACEPOINT_SYMBOL_GPL(add_device_to_group); +EXPORT_TRACEPOINT_SYMBOL_GPL(remove_device_from_group); + +/* iommu_device_event */ +EXPORT_TRACEPOINT_SYMBOL_GPL(attach_device_to_domain); +EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain); + +/* iommu_map_unmap */ +EXPORT_TRACEPOINT_SYMBOL_GPL(map); +EXPORT_TRACEPOINT_SYMBOL_GPL(unmap); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index fbe9ca734f8f..58f6a16b2e1a 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -29,6 +29,7 @@ #include #include #include +#include static struct kset *iommu_group_kset; static struct ida iommu_group_ida; diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h new file mode 100644 index 000000000000..86bcc5a9fedc --- /dev/null +++ b/include/trace/events/iommu.h @@ -0,0 +1,129 @@ +/* + * iommu trace points + * + * Copyright (C) 2013 Shuah Khan + * + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM iommu + +#if !defined(_TRACE_IOMMU_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_IOMMU_H + +#include +#include + +struct device; + +DECLARE_EVENT_CLASS(iommu_group_event, + + TP_PROTO(int group_id, struct device *dev), + + TP_ARGS(group_id, dev), + + TP_STRUCT__entry( + __field(int, gid) + __string(device, dev_name(dev)) + ), + + TP_fast_assign( + __entry->gid = group_id; + __assign_str(device, dev_name(dev)); + ), + + TP_printk("IOMMU: groupID=%d device=%s", + __entry->gid, __get_str(device) + ) +); + +DEFINE_EVENT(iommu_group_event, add_device_to_group, + + TP_PROTO(int group_id, struct device *dev), + + TP_ARGS(group_id, dev) + +); + +DEFINE_EVENT(iommu_group_event, remove_device_from_group, + + TP_PROTO(int group_id, struct device *dev), + + TP_ARGS(group_id, dev) +); + +DECLARE_EVENT_CLASS(iommu_device_event, + + TP_PROTO(struct device *dev), + + TP_ARGS(dev), + + TP_STRUCT__entry( + __string(device, dev_name(dev)) + ), + + TP_fast_assign( + __assign_str(device, dev_name(dev)); + ), + + TP_printk("IOMMU: device=%s", __get_str(device) + ) +); + +DEFINE_EVENT(iommu_device_event, attach_device_to_domain, + + TP_PROTO(struct device *dev), + + TP_ARGS(dev) +); + +DEFINE_EVENT(iommu_device_event, detach_device_from_domain, + + TP_PROTO(struct device *dev), + + TP_ARGS(dev) +); + +DECLARE_EVENT_CLASS(iommu_map_unmap, + + TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size), + + TP_ARGS(iova, paddr, size), + + TP_STRUCT__entry( + __field(u64, iova) + __field(u64, paddr) + __field(int, size) + ), + + TP_fast_assign( + __entry->iova = iova; + __entry->paddr = paddr; + __entry->size = size; + ), + + TP_printk("IOMMU: iova=0x%016llx paddr=0x%016llx size=0x%x", + __entry->iova, __entry->paddr, __entry->size + ) +); + +DEFINE_EVENT(iommu_map_unmap, map, + + TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size), + + TP_ARGS(iova, paddr, size) +); + +DEFINE_EVENT_PRINT(iommu_map_unmap, unmap, + + TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size), + + TP_ARGS(iova, paddr, size), + + TP_printk("IOMMU: iova=0x%016llx size=0x%x", + __entry->iova, __entry->size + ) +); +#endif /* _TRACE_IOMMU_H */ + +/* This part must be outside protection */ +#include -- cgit From 8c27bd75f04fb9cb70c69c3cfe24f4e6d8e15906 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 20 Sep 2013 22:32:55 +0200 Subject: tcp: syncookies: reduce cookie lifetime to 128 seconds We currently accept cookies that were created less than 4 minutes ago (ie, cookies with counter delta 0-3). Combined with the 8 mss table values, this yields 32 possible values (out of 2**32) that will be valid. Reducing the lifetime to < 2 minutes halves the guessing chance while still providing a large enough period. While at it, get rid of jiffies value -- they overflow too quickly on 32 bit platforms. getnstimeofday is used to create a counter that increments every 64s. perf shows getnstimeofday cost is negible compared to sha_transform; normal tcp initial sequence number generation uses getnstimeofday, too. Reported-by: Jakob Lell Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- include/net/tcp.h | 18 ++++++++++++++++++ net/ipv4/syncookies.c | 31 ++++++++++--------------------- net/ipv6/syncookies.c | 24 +++++++----------------- 3 files changed, 35 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index 0e47551e9bdb..de870ee5582d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -481,6 +481,24 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt); #ifdef CONFIG_SYN_COOKIES +#include + +/* Syncookies use a monotonic timer which increments every 64 seconds. + * This counter is used both as a hash input and partially encoded into + * the cookie value. A cookie is only validated further if the delta + * between the current counter value and the encoded one is less than this, + * i.e. a sent cookie is valid only at most for 128 seconds (or less if + * the counter advances immediately after a cookie is generated). + */ +#define MAX_SYNCOOKIE_AGE 2 + +static inline u32 tcp_cookie_time(void) +{ + struct timespec now; + getnstimeofday(&now); + return now.tv_sec >> 6; /* 64 seconds granularity */ +} + u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th, u16 *mssp); __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mss); diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 14a15c49129d..b6ea2979a2b7 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -89,8 +89,7 @@ __u32 cookie_init_timestamp(struct request_sock *req) static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport, - __be16 dport, __u32 sseq, __u32 count, - __u32 data) + __be16 dport, __u32 sseq, __u32 data) { /* * Compute the secure sequence number. @@ -102,7 +101,7 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport, * As an extra hack, we add a small "data" value that encodes the * MSS into the second hash value. */ - + u32 count = tcp_cookie_time(); return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq + (count << COOKIEBITS) + ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) @@ -114,22 +113,21 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport, * If the syncookie is bad, the data returned will be out of * range. This must be checked by the caller. * - * The count value used to generate the cookie must be within - * "maxdiff" if the current (passed-in) "count". The return value - * is (__u32)-1 if this test fails. + * The count value used to generate the cookie must be less than + * MAX_SYNCOOKIE_AGE minutes in the past. + * The return value (__u32)-1 if this test fails. */ static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr, - __be16 sport, __be16 dport, __u32 sseq, - __u32 count, __u32 maxdiff) + __be16 sport, __be16 dport, __u32 sseq) { - __u32 diff; + u32 diff, count = tcp_cookie_time(); /* Strip away the layers from the cookie */ cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */ diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS); - if (diff >= maxdiff) + if (diff >= MAX_SYNCOOKIE_AGE) return (__u32)-1; return (cookie - @@ -173,7 +171,7 @@ u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th, return secure_tcp_syn_cookie(iph->saddr, iph->daddr, th->source, th->dest, ntohl(th->seq), - jiffies / (HZ * 60), mssind); + mssind); } EXPORT_SYMBOL_GPL(__cookie_v4_init_sequence); @@ -188,13 +186,6 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) return __cookie_v4_init_sequence(iph, th, mssp); } -/* - * This (misnamed) value is the age of syncookie which is permitted. - * Its ideal value should be dependent on TCP_TIMEOUT_INIT and - * sysctl_tcp_retries1. It's a rather complicated formula (exponential - * backoff) to compute at runtime so it's currently hardcoded here. - */ -#define COUNTER_TRIES 4 /* * Check if a ack sequence number is a valid syncookie. * Return the decoded mss if it is, or 0 if not. @@ -204,9 +195,7 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, { __u32 seq = ntohl(th->seq) - 1; __u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr, - th->source, th->dest, seq, - jiffies / (HZ * 60), - COUNTER_TRIES); + th->source, th->dest, seq); return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; } diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index bf63ac8a49b9..13ca0a0ea680 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -36,14 +36,6 @@ static __u16 const msstab[] = { 9000 - 60, }; -/* - * This (misnamed) value is the age of syncookie which is permitted. - * Its ideal value should be dependent on TCP_TIMEOUT_INIT and - * sysctl_tcp_retries1. It's a rather complicated formula (exponential - * backoff) to compute at runtime so it's currently hardcoded here. - */ -#define COUNTER_TRIES 4 - static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst) @@ -86,8 +78,9 @@ static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *dadd static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, const struct in6_addr *daddr, __be16 sport, __be16 dport, __u32 sseq, - __u32 count, __u32 data) + __u32 data) { + u32 count = tcp_cookie_time(); return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq + (count << COOKIEBITS) + ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) @@ -96,15 +89,14 @@ static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr, const struct in6_addr *daddr, __be16 sport, - __be16 dport, __u32 sseq, __u32 count, - __u32 maxdiff) + __be16 dport, __u32 sseq) { - __u32 diff; + __u32 diff, count = tcp_cookie_time(); cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS); - if (diff >= maxdiff) + if (diff >= MAX_SYNCOOKIE_AGE) return (__u32)-1; return (cookie - @@ -125,8 +117,7 @@ u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph, *mssp = msstab[mssind]; return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source, - th->dest, ntohl(th->seq), - jiffies / (HZ * 60), mssind); + th->dest, ntohl(th->seq), mssind); } EXPORT_SYMBOL_GPL(__cookie_v6_init_sequence); @@ -146,8 +137,7 @@ int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, { __u32 seq = ntohl(th->seq) - 1; __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, - th->source, th->dest, seq, - jiffies / (HZ * 60), COUNTER_TRIES); + th->source, th->dest, seq); return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; } -- cgit From 98fda169290b3b28c0f2db2b8f02290c13da50ef Mon Sep 17 00:00:00 2001 From: Radim Krčmář Date: Wed, 4 Sep 2013 22:32:24 +0200 Subject: kvm: remove .done from struct kvm_async_pf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit '.done' is used to mark the completion of 'async_pf_execute()', but 'cancel_work_sync()' returns true when the work was canceled, so we use it instead. Signed-off-by: Radim Krčmář Reviewed-by: Paolo Bonzini Reviewed-by: Gleb Natapov Signed-off-by: Paolo Bonzini --- include/linux/kvm_host.h | 1 - virt/kvm/async_pf.c | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 0fbbc7aa02cb..749bdb12cd15 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -190,7 +190,6 @@ struct kvm_async_pf { unsigned long addr; struct kvm_arch_async_pf arch; struct page *page; - bool done; }; void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu); diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c index 8a39dda7a325..b197950ac4d5 100644 --- a/virt/kvm/async_pf.c +++ b/virt/kvm/async_pf.c @@ -75,7 +75,6 @@ static void async_pf_execute(struct work_struct *work) spin_lock(&vcpu->async_pf.lock); list_add_tail(&apf->link, &vcpu->async_pf.done); apf->page = page; - apf->done = true; spin_unlock(&vcpu->async_pf.lock); /* @@ -99,9 +98,8 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu) struct kvm_async_pf *work = list_entry(vcpu->async_pf.queue.next, typeof(*work), queue); - cancel_work_sync(&work->work); list_del(&work->queue); - if (!work->done) { /* work was canceled */ + if (cancel_work_sync(&work->work)) { mmdrop(work->mm); kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */ kmem_cache_free(async_pf_cache, work); @@ -166,7 +164,6 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, return 0; work->page = NULL; - work->done = false; work->vcpu = vcpu; work->gva = gva; work->addr = gfn_to_hva(vcpu->kvm, gfn); -- cgit From f1a4c52ff5913378b7baf05ac71f10282b341cf7 Mon Sep 17 00:00:00 2001 From: Philip Avinash Date: Sun, 18 Aug 2013 10:49:03 +0530 Subject: ARM: davinci: gpio: use gpiolib API instead of inline functions Remove NEED_MACH_GPIO_H config select option for ARCH_DAVINCI to start using gpiolib interface for davinci platforms. This makes it easier to use the gpio driver on other platforms as it breaks dependency on mach-davinci. Latencies for gpio_get/set APIs will increase. On measurement, latency was found to have increased by 18 microsecond with gpiolib API as compared to inline APIs. Measurement was done on DA850 EVM for gpio_get_value() API by taking the printk timing across the call with interrupts disabled. inline gpio API with interrupt disabled [ 29.734337] before gpio_get [ 29.736847] after gpio_get Time difference 0.00251 gpio library with interrupt disabled [ 272.876763] before gpio_get [ 272.879291] after gpio_get Time difference 0.002528 Latency increased by (0.002528 - 0.00251) = 18 microsecond. While at it, remove GPIO_TYPE_DAVINCI enum definition as gpio-davinci.c is converted to Linux device driver model. Signed-off-by: Philip Avinash Signed-off-by: Lad, Prabhakar Acked-by: Linus Walleij [nsekhar@ti.com: minor edits to commit message] Signed-off-by: Sekhar Nori --- arch/arm/Kconfig | 1 - arch/arm/mach-davinci/include/mach/gpio-davinci.h | 90 ----------------------- arch/arm/mach-davinci/include/mach/gpio.h | 88 ---------------------- drivers/gpio/gpio-tnetv107x.c | 1 + include/linux/platform_data/gpio-davinci.h | 35 +++++++++ 5 files changed, 36 insertions(+), 179 deletions(-) delete mode 100644 arch/arm/mach-davinci/include/mach/gpio-davinci.h delete mode 100644 arch/arm/mach-davinci/include/mach/gpio.h (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3f7714d8d2d2..ad3767095422 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -847,7 +847,6 @@ config ARCH_DAVINCI select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP select HAVE_IDE - select NEED_MACH_GPIO_H select TI_PRIV_EDMA select USE_OF select ZONE_DMA diff --git a/arch/arm/mach-davinci/include/mach/gpio-davinci.h b/arch/arm/mach-davinci/include/mach/gpio-davinci.h deleted file mode 100644 index 0d63b24cefc9..000000000000 --- a/arch/arm/mach-davinci/include/mach/gpio-davinci.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * TI DaVinci GPIO Support - * - * Copyright (c) 2006 David Brownell - * Copyright (c) 2007, MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __DAVINCI_DAVINCI_GPIO_H -#define __DAVINCI_DAVINCI_GPIO_H - -#include -#include - -#include - -#include -#include - -enum davinci_gpio_type { - GPIO_TYPE_DAVINCI = 0, - GPIO_TYPE_TNETV107X, -}; - -/* - * basic gpio routines - * - * board-specific init should be done by arch/.../.../board-XXX.c (maybe - * initializing banks together) rather than boot loaders; kexec() won't - * go through boot loaders. - * - * the gpio clock will be turned on when gpios are used, and you may also - * need to pay attention to PINMUX registers to be sure those pins are - * used as gpios, not with other peripherals. - * - * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, - * and maybe for later updates, code may write GPIO(N). These may be - * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip - * may not support all the GPIOs in that range. - * - * GPIOs can also be on external chips, numbered after the ones built-in - * to the DaVinci chip. For now, they won't be usable as IRQ sources. - */ -#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */ - -/* Convert GPIO signal to GPIO pin number */ -#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) - -struct davinci_gpio_controller { - struct gpio_chip chip; - int irq_base; - spinlock_t lock; - void __iomem *regs; - void __iomem *set_data; - void __iomem *clr_data; - void __iomem *in_data; - unsigned gpio_irq; -}; - -/* The __gpio_to_controller() and __gpio_mask() functions inline to constants - * with constant parameters; or in outlined code they execute at runtime. - * - * You'd access the controller directly when reading or writing more than - * one gpio value at a time, and to support wired logic where the value - * being driven by the cpu need not match the value read back. - * - * These are NOT part of the cross-platform GPIO interface - */ -static inline struct davinci_gpio_controller * -__gpio_to_controller(unsigned gpio) -{ - struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs; - int index = gpio / 32; - - if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num) - return NULL; - - return ctlrs + index; -} - -static inline u32 __gpio_mask(unsigned gpio) -{ - return 1 << (gpio % 32); -} - -#endif /* __DAVINCI_DAVINCI_GPIO_H */ diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h deleted file mode 100644 index 960e9de47e1e..000000000000 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * TI DaVinci GPIO Support - * - * Copyright (c) 2006 David Brownell - * Copyright (c) 2007, MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __DAVINCI_GPIO_H -#define __DAVINCI_GPIO_H - -#include - -#define __ARM_GPIOLIB_COMPLEX - -/* The inline versions use the static inlines in the driver header */ -#include "gpio-davinci.h" - -/* - * The get/set/clear functions will inline when called with constant - * parameters referencing built-in GPIOs, for low-overhead bitbanging. - * - * gpio_set_value() will inline only on traditional Davinci style controllers - * with distinct set/clear registers. - * - * Otherwise, calls with variable parameters or referencing external - * GPIOs (e.g. on GPIO expander chips) use outlined functions. - */ -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (__builtin_constant_p(value) && gpio < davinci_soc_info.gpio_num) { - struct davinci_gpio_controller *ctlr; - u32 mask; - - ctlr = __gpio_to_controller(gpio); - - if (ctlr->set_data != ctlr->clr_data) { - mask = __gpio_mask(gpio); - if (value) - __raw_writel(mask, ctlr->set_data); - else - __raw_writel(mask, ctlr->clr_data); - return; - } - } - - __gpio_set_value(gpio, value); -} - -/* Returns zero or nonzero; works for gpios configured as inputs OR - * as outputs, at least for built-in GPIOs. - * - * NOTE: for built-in GPIOs, changes in reported values are synchronized - * to the GPIO clock. This is easily seen after calling gpio_set_value() - * and then immediately gpio_get_value(), where the gpio_get_value() will - * return the old value until the GPIO clock ticks and the new value gets - * latched. - */ -static inline int gpio_get_value(unsigned gpio) -{ - struct davinci_gpio_controller *ctlr; - - if (!__builtin_constant_p(gpio) || gpio >= davinci_soc_info.gpio_num) - return __gpio_get_value(gpio); - - ctlr = __gpio_to_controller(gpio); - return __gpio_mask(gpio) & __raw_readl(ctlr->in_data); -} - -static inline int gpio_cansleep(unsigned gpio) -{ - if (__builtin_constant_p(gpio) && gpio < davinci_soc_info.gpio_num) - return 0; - else - return __gpio_cansleep(gpio); -} - -static inline int irq_to_gpio(unsigned irq) -{ - /* don't support the reverse mapping */ - return -ENOSYS; -} - -#endif /* __DAVINCI_GPIO_H */ diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c index 3fa3e2867e19..58445bb69106 100644 --- a/drivers/gpio/gpio-tnetv107x.c +++ b/drivers/gpio/gpio-tnetv107x.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/include/linux/platform_data/gpio-davinci.h b/include/linux/platform_data/gpio-davinci.h index 2fcc125af1aa..6efd20264585 100644 --- a/include/linux/platform_data/gpio-davinci.h +++ b/include/linux/platform_data/gpio-davinci.h @@ -16,10 +16,45 @@ #ifndef __DAVINCI_GPIO_PLATFORM_H #define __DAVINCI_GPIO_PLATFORM_H +#include +#include + +#include + +enum davinci_gpio_type { + GPIO_TYPE_TNETV107X = 0, +}; + struct davinci_gpio_platform_data { u32 ngpio; u32 gpio_unbanked; u32 intc_irq_num; }; + +struct davinci_gpio_controller { + struct gpio_chip chip; + int irq_base; + /* Serialize access to GPIO registers */ + spinlock_t lock; + void __iomem *regs; + void __iomem *set_data; + void __iomem *clr_data; + void __iomem *in_data; + int gpio_unbanked; + unsigned gpio_irq; +}; + +/* + * basic gpio routines + */ +#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */ + +/* Convert GPIO signal to GPIO pin number */ +#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) + +static inline u32 __gpio_mask(unsigned gpio) +{ + return 1 << (gpio % 32); +} #endif -- cgit From d8eb18eecaf358e37f4941c2b8cba3c4b8122b7f Mon Sep 17 00:00:00 2001 From: Arron Wang Date: Fri, 23 Aug 2013 16:02:08 +0800 Subject: NFC: Export nfc_find_se() This will be needed by all NFC driver implementing the SE ops. Signed-off-by: Arron Wang Signed-off-by: Samuel Ortiz --- include/net/nfc/nfc.h | 1 + net/nfc/core.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index f68ee68e4e3e..e34859423105 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -243,5 +243,6 @@ void nfc_driver_failure(struct nfc_dev *dev, int err); int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type); int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); +struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx); #endif /* __NET_NFC_H */ diff --git a/net/nfc/core.c b/net/nfc/core.c index e92923cf3e03..269ffc5288d0 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -536,7 +536,7 @@ error: return rc; } -static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) +struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) { struct nfc_se *se, *n; @@ -546,6 +546,7 @@ static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) return NULL; } +EXPORT_SYMBOL(nfc_find_se); int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) { @@ -577,7 +578,7 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) goto error; } - se = find_se(dev, se_idx); + se = nfc_find_se(dev, se_idx); if (!se) { rc = -EINVAL; goto error; @@ -622,7 +623,7 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) goto error; } - se = find_se(dev, se_idx); + se = nfc_find_se(dev, se_idx); if (!se) { rc = -EINVAL; goto error; @@ -881,7 +882,7 @@ int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); - se = find_se(dev, se_idx); + se = nfc_find_se(dev, se_idx); if (se) return -EALREADY; -- cgit From b48348395ff665f49c7c684c93c5ce09fd0a0307 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 5 Apr 2013 12:27:37 -0700 Subject: NFC: Replace nfc_dev_dbg with dev_dbg Use the generic kernel function instead of a home-grown one that does the same thing. Add \n to uses not at the macro. Don't add \n where the nfc_dev_dbg macro mistakenly had them already. Signed-off-by: Joe Perches Signed-off-by: Samuel Ortiz --- drivers/nfc/nfcsim.c | 24 ++++----- drivers/nfc/nfcwilink.c | 51 ++++++------------ drivers/nfc/pn533.c | 137 ++++++++++++++++++++++-------------------------- include/net/nfc/nfc.h | 1 - 4 files changed, 91 insertions(+), 122 deletions(-) (limited to 'include') diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 9a53f13c88df..4a614794ea61 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c @@ -22,7 +22,7 @@ #define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ "%s: " fmt, __func__, ## args) -#define DEV_DBG(_dev, fmt, args...) nfc_dev_dbg(&_dev->nfc_dev->dev, \ +#define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ "%s: " fmt, __func__, ## args) #define NFCSIM_VERSION "0.1" @@ -64,7 +64,7 @@ static struct workqueue_struct *wq; static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) { - DEV_DBG(dev, "shutdown=%d", shutdown); + DEV_DBG(dev, "shutdown=%d\n", shutdown); mutex_lock(&dev->lock); @@ -84,7 +84,7 @@ static int nfcsim_target_found(struct nfcsim *dev) { struct nfc_target nfc_tgt; - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); memset(&nfc_tgt, 0, sizeof(struct nfc_target)); @@ -98,7 +98,7 @@ static int nfcsim_dev_up(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); mutex_lock(&dev->lock); @@ -113,7 +113,7 @@ static int nfcsim_dev_down(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); mutex_lock(&dev->lock); @@ -172,7 +172,7 @@ static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); nfcsim_cleanup_dev(dev, 0); @@ -210,7 +210,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, queue_delayed_work(wq, &dev->poll_work, 0); - DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X", im_protocols, + DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols, tm_protocols); rc = 0; @@ -224,7 +224,7 @@ static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, "Stop poll"); + DEV_DBG(dev, "Stop poll\n"); mutex_lock(&dev->lock); @@ -240,7 +240,7 @@ static int nfcsim_activate_target(struct nfc_dev *nfc_dev, { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); return -ENOTSUPP; } @@ -250,7 +250,7 @@ static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); } static void nfcsim_wq_recv(struct work_struct *work) @@ -397,13 +397,13 @@ static void nfcsim_wq_poll(struct work_struct *work) nfcsim_set_polling_mode(dev); if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { - DEV_DBG(dev, "Not polling"); + DEV_DBG(dev, "Not polling\n"); goto unlock; } DEV_DBG(dev, "Polling as %s", dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? - "initiator" : "target"); + "initiator\n" : "target\n"); if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) goto sched_work; diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 59f95d8fc98c..ec9dbf4fad83 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -146,8 +146,6 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "get_bts_file_name entry"); - skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd), GFP_KERNEL); if (!skb) { @@ -170,17 +168,16 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) comp_ret = wait_for_completion_timeout(&drv->completed, msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { - nfc_dev_err(&drv->pdev->dev, - "timeout on wait_for_completion_timeout"); + dev_err(&drv->pdev->dev, + "timeout on wait_for_completion_timeout\n"); return -ETIMEDOUT; } - nfc_dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d", - drv->nfcc_info.plen, - drv->nfcc_info.status); + dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d\n", + drv->nfcc_info.plen, drv->nfcc_info.status); if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) { nfc_dev_err(&drv->pdev->dev, @@ -207,8 +204,6 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "send_bts_cmd entry"); - /* verify valid cmd for the NFC channel */ if ((len <= sizeof(struct nfcwilink_hdr)) || (len > BTS_FILE_CMD_MAX_LEN) || @@ -238,8 +233,8 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) comp_ret = wait_for_completion_timeout(&drv->completed, msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { nfc_dev_err(&drv->pdev->dev, "timeout on wait_for_completion_timeout"); @@ -257,8 +252,6 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) __u8 *ptr; int len, rc; - nfc_dev_dbg(&drv->pdev->dev, "download_fw entry"); - set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags); rc = nfcwilink_get_bts_file_name(drv, file_name); @@ -280,8 +273,8 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) ptr = (__u8 *)fw->data; if ((len == 0) || (ptr == NULL)) { - nfc_dev_dbg(&drv->pdev->dev, - "request_firmware returned size %d", len); + dev_dbg(&drv->pdev->dev, + "request_firmware returned size %d\n", len); goto release_fw; } @@ -302,8 +295,8 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) action_len = __le16_to_cpu(((struct bts_file_action *)ptr)->len); - nfc_dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d", - action_type, action_len); + dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d\n", + action_type, action_len); switch (action_type) { case BTS_FILE_ACTION_TYPE_SEND_CMD: @@ -333,8 +326,6 @@ static void nfcwilink_register_complete(void *priv_data, char data) { struct nfcwilink *drv = priv_data; - nfc_dev_dbg(&drv->pdev->dev, "register_complete entry"); - /* store ST registration status */ drv->st_register_cb_status = data; @@ -356,7 +347,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) return -EFAULT; } - nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); + dev_dbg(&drv->pdev->dev, "receive entry, len %d\n", skb->len); /* strip the ST header (apart for the chnl byte, which is not received in the hdr) */ @@ -396,8 +387,6 @@ static int nfcwilink_open(struct nci_dev *ndev) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "open entry"); - if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) { rc = -EBUSY; goto exit; @@ -415,9 +404,9 @@ static int nfcwilink_open(struct nci_dev *ndev) &drv->completed, msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, - "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, + "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { /* timeout */ @@ -460,8 +449,6 @@ static int nfcwilink_close(struct nci_dev *ndev) struct nfcwilink *drv = nci_get_drvdata(ndev); int rc; - nfc_dev_dbg(&drv->pdev->dev, "close entry"); - if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags)) return 0; @@ -480,7 +467,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; long len; - nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len); + dev_dbg(&drv->pdev->dev, "send entry, len %d\n", skb->len); if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) { kfree_skb(skb); @@ -517,8 +504,6 @@ static int nfcwilink_probe(struct platform_device *pdev) int rc; __u32 protocols; - nfc_dev_dbg(&pdev->dev, "probe entry"); - drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); if (!drv) { rc = -ENOMEM; @@ -568,8 +553,6 @@ static int nfcwilink_remove(struct platform_device *pdev) struct nfcwilink *drv = dev_get_drvdata(&pdev->dev); struct nci_dev *ndev; - nfc_dev_dbg(&pdev->dev, "remove entry"); - if (!drv) return -EFAULT; diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5df730be88a3..e64bea53f0c8 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -722,9 +722,9 @@ static void pn533_recv_response(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been canceled (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been canceled (status %d)\n", + urb->status); goto sched_wq; case -ESHUTDOWN: default: @@ -735,7 +735,7 @@ static void pn533_recv_response(struct urb *urb) in_frame = dev->in_urb->transfer_buffer; - nfc_dev_dbg(&dev->interface->dev, "Received a frame."); + dev_dbg(&dev->interface->dev, "Received a frame\n"); print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, dev->ops->rx_frame_size(in_frame), false); @@ -777,9 +777,9 @@ static void pn533_recv_ack(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been stopped (status %d)\n", + urb->status); goto sched_wq; case -ESHUTDOWN: default: @@ -823,8 +823,6 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags) /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - dev->out_urb->transfer_buffer = ack; dev->out_urb->transfer_buffer_length = sizeof(ack); rc = usb_submit_urb(dev->out_urb, flags); @@ -927,7 +925,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, struct pn533_cmd *cmd; int rc = 0; - nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); + dev_dbg(&dev->interface->dev, "Sending command 0x%x\n", cmd_code); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) @@ -954,8 +952,8 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, goto unlock; } - nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__, - cmd_code); + dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x\n", + __func__, cmd_code); INIT_LIST_HEAD(&cmd->queue); list_add_tail(&cmd->queue, &dev->cmd_queue); @@ -1168,9 +1166,9 @@ static void pn533_send_complete(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been stopped (status %d)\n", + urb->status); break; case -ESHUTDOWN: default: @@ -1452,8 +1450,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, struct nfc_target nfc_tgt; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, - dev->poll_mod_curr); + dev_dbg(&dev->interface->dev, "%s - modulation=%d\n", + __func__, dev->poll_mod_curr); if (tg != 1) return -EPROTO; @@ -1484,14 +1482,14 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, return rc; if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { - nfc_dev_dbg(&dev->interface->dev, - "The Tg found doesn't have the desired protocol"); + dev_dbg(&dev->interface->dev, + "The Tg found doesn't have the desired protocol\n"); return -EAGAIN; } - nfc_dev_dbg(&dev->interface->dev, - "Target found - supported protocols: 0x%x", - nfc_tgt.supported_protocols); + dev_dbg(&dev->interface->dev, + "Target found - supported protocols: 0x%x\n", + nfc_tgt.supported_protocols); dev->tgt_available_prots = nfc_tgt.supported_protocols; @@ -1548,8 +1546,6 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) u8 nbtg, tg, *tgdata; int rc, tgdata_len; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - nbtg = resp->data[0]; tg = resp->data[1]; tgdata = &resp->data[2]; @@ -1629,7 +1625,7 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, { u8 status; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) return PTR_ERR(resp); @@ -1650,11 +1646,10 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, static void pn533_wq_tg_get_data(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, tg_work); - struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1676,7 +1671,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) size_t gb_len; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; @@ -1684,8 +1679,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) mode = resp->data[0]; cmd = &resp->data[1]; - nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", - mode, resp->len); + dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", + mode, resp->len); if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == PN533_INIT_TARGET_RESP_ACTIVE) @@ -1715,7 +1710,7 @@ static void pn533_listen_mode_timer(unsigned long data) { struct pn533 *dev = (struct pn533 *)data; - nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); + dev_dbg(&dev->interface->dev, "Listen mode timeout\n"); dev->cancel_listen = 1; @@ -1730,7 +1725,7 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, { int rc = 0; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -1754,7 +1749,7 @@ static void pn533_wq_rf(struct work_struct *work) struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 2); if (!skb) @@ -1779,7 +1774,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, struct pn533_poll_modulations *cur_mod; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -1813,7 +1808,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, goto done; if (!dev->poll_mod_count) { - nfc_dev_dbg(&dev->interface->dev, "Polling has been stopped."); + dev_dbg(&dev->interface->dev, "Polling has been stopped\n"); goto done; } @@ -1856,8 +1851,8 @@ static int pn533_send_poll_frame(struct pn533 *dev) mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, "%s mod len %d\n", - __func__, mod->len); + dev_dbg(&dev->interface->dev, "%s mod len %d\n", + __func__, mod->len); if (mod->len == 0) { /* Listen mode */ cmd_code = PN533_CMD_TG_INIT_AS_TARGET; @@ -1890,9 +1885,9 @@ static void pn533_wq_poll(struct work_struct *work) cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, - "%s cancel_listen %d modulation len %d", - __func__, dev->cancel_listen, cur_mod->len); + dev_dbg(&dev->interface->dev, + "%s cancel_listen %d modulation len %d\n", + __func__, dev->cancel_listen, cur_mod->len); if (dev->cancel_listen == 1) { dev->cancel_listen = 0; @@ -1915,9 +1910,9 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, struct pn533 *dev = nfc_get_drvdata(nfc_dev); u8 rand_mod; - nfc_dev_dbg(&dev->interface->dev, - "%s: im protocols 0x%x tm protocols 0x%x", - __func__, im_protocols, tm_protocols); + dev_dbg(&dev->interface->dev, + "%s: im protocols 0x%x tm protocols 0x%x\n", + __func__, im_protocols, tm_protocols); if (dev->tgt_active_prot) { nfc_dev_err(&dev->interface->dev, @@ -1953,13 +1948,11 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - del_timer(&dev->listen_timer); if (!dev->poll_mod_count) { - nfc_dev_dbg(&dev->interface->dev, - "Polling operation was not running"); + dev_dbg(&dev->interface->dev, + "Polling operation was not running\n"); return; } @@ -1973,11 +1966,10 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) struct pn533_cmd_activate_response *rsp; u16 gt_len; int rc; - struct sk_buff *skb; struct sk_buff *resp; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) @@ -2013,12 +2005,12 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, - protocol); + dev_dbg(&dev->interface->dev, "%s - protocol=%u\n", + __func__, protocol); if (dev->poll_mod_count) { - nfc_dev_err(&dev->interface->dev, - "Cannot activate while polling"); + dev_err(&dev->interface->dev, + "Cannot activate while polling\n"); return -EBUSY; } @@ -2060,13 +2052,11 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - struct sk_buff *skb; struct sk_buff *resp; - int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { nfc_dev_err(&dev->interface->dev, "There is no active target"); @@ -2129,7 +2119,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (!dev->tgt_available_prots) { struct nfc_target nfc_target; - nfc_dev_dbg(&dev->interface->dev, "Creating new target"); + dev_dbg(&dev->interface->dev, "Creating new target\n"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -2166,10 +2156,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb; int rc, skb_len; u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; - u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (dev->poll_mod_count) { nfc_dev_err(&dev->interface->dev, @@ -2249,7 +2238,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); pn533_poll_reset_mod_list(dev); @@ -2274,7 +2263,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (skb_queue_empty(&dev->resp_q)) return NULL; @@ -2287,8 +2276,8 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) skb_queue_walk_safe(&dev->resp_q, tmp, t) skb_len += tmp->len; - nfc_dev_dbg(&dev->interface->dev, "%s total length %d\n", - __func__, skb_len); + dev_dbg(&dev->interface->dev, "%s total length %d\n", + __func__, skb_len); skb = alloc_skb(skb_len, GFP_KERNEL); if (skb == NULL) @@ -2315,7 +2304,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, int rc = 0; u8 status, ret, mi; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -2420,7 +2409,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, struct pn533_data_exchange_arg *arg = NULL; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { nfc_dev_err(&dev->interface->dev, @@ -2487,7 +2476,7 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, { u8 status; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) return PTR_ERR(resp); @@ -2514,7 +2503,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { nfc_dev_err(&dev->interface->dev, @@ -2534,11 +2523,10 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) static void pn533_wq_mi_recv(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, mi_rx_work); - struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) @@ -2587,7 +2575,7 @@ static void pn533_wq_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -2641,10 +2629,9 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, { struct sk_buff *skb; struct sk_buff *resp; - int skb_len; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ @@ -2691,7 +2678,7 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) @@ -2717,7 +2704,7 @@ static void pn533_acr122_poweron_rdr_resp(struct urb *urb) { struct pn533_acr122_poweron_rdr_arg *arg = urb->context; - nfc_dev_dbg(&urb->dev->dev, "%s", __func__); + dev_dbg(&urb->dev->dev, "%s\n", __func__); print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, urb->transfer_buffer, urb->transfer_buffer_length, @@ -2737,7 +2724,7 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) void *cntx; struct pn533_acr122_poweron_rdr_arg arg; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); init_completion(&arg.done); cntx = dev->in_urb->context; /* backup context */ diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index e34859423105..a164c46bed7e 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -30,7 +30,6 @@ #define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg) #define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg) -#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg) struct nfc_dev; -- cgit From 073a625f0b80fb7613220a56375b0f3d2831af1b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 5 Apr 2013 12:27:38 -0700 Subject: NFC: Convert nfc_dev_info and nfc_dev_err to nfc_ Use a more standard kernel style macro logging name. Standardize the spacing of the "NFC: " prefix. Add \n to uses, remove from macro. Fix the defective uses that already had a \n. Signed-off-by: Joe Perches Signed-off-by: Samuel Ortiz --- drivers/nfc/nfcsim.c | 14 ++-- drivers/nfc/nfcwilink.c | 44 ++++++------ drivers/nfc/pn533.c | 175 +++++++++++++++++++++++------------------------- include/net/nfc/nfc.h | 4 +- 4 files changed, 115 insertions(+), 122 deletions(-) (limited to 'include') diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 4a614794ea61..93111fa8d282 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c @@ -19,7 +19,7 @@ #include #include -#define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ +#define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \ "%s: " fmt, __func__, ## args) #define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ @@ -143,7 +143,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); if (!remote_gb) { - DEV_ERR(peer, "Can't get remote general bytes"); + DEV_ERR(peer, "Can't get remote general bytes\n"); mutex_unlock(&peer->lock); return -EINVAL; @@ -155,7 +155,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); if (rc) { - DEV_ERR(dev, "Can't set remote general bytes"); + DEV_ERR(dev, "Can't set remote general bytes\n"); mutex_unlock(&dev->lock); return rc; } @@ -188,7 +188,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, mutex_lock(&dev->lock); if (dev->polling_mode != NFCSIM_POLL_NONE) { - DEV_ERR(dev, "Already in polling mode"); + DEV_ERR(dev, "Already in polling mode\n"); rc = -EBUSY; goto exit; } @@ -200,7 +200,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, dev->polling_mode |= NFCSIM_POLL_TARGET; if (dev->polling_mode == NFCSIM_POLL_NONE) { - DEV_ERR(dev, "Unsupported polling mode"); + DEV_ERR(dev, "Unsupported polling mode\n"); rc = -EINVAL; goto exit; } @@ -267,7 +267,7 @@ static void nfcsim_wq_recv(struct work_struct *work) if (dev->initiator) { if (!dev->cb) { - DEV_ERR(dev, "Null recv callback"); + DEV_ERR(dev, "Null recv callback\n"); dev_kfree_skb(dev->clone_skb); goto exit; } @@ -310,7 +310,7 @@ static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, peer->clone_skb = skb_clone(skb, GFP_KERNEL); if (!peer->clone_skb) { - DEV_ERR(dev, "skb_clone failed"); + DEV_ERR(dev, "skb_clone failed\n"); mutex_unlock(&peer->lock); err = -ENOMEM; goto exit; diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index ec9dbf4fad83..ebf6da75bd40 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -149,8 +149,8 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd), GFP_KERNEL); if (!skb) { - nfc_dev_err(&drv->pdev->dev, - "no memory for nci_vs_nfcc_info_cmd"); + nfc_err(&drv->pdev->dev, + "no memory for nci_vs_nfcc_info_cmd\n"); return -ENOMEM; } @@ -180,8 +180,7 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) drv->nfcc_info.plen, drv->nfcc_info.status); if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) { - nfc_dev_err(&drv->pdev->dev, - "invalid nci_vs_nfcc_info_rsp"); + nfc_err(&drv->pdev->dev, "invalid nci_vs_nfcc_info_rsp\n"); return -EINVAL; } @@ -192,7 +191,7 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) drv->nfcc_info.sw_ver_z, drv->nfcc_info.patch_id); - nfc_dev_info(&drv->pdev->dev, "nfcwilink FW file name: %s", file_name); + nfc_info(&drv->pdev->dev, "nfcwilink FW file name: %s\n", file_name); return 0; } @@ -209,8 +208,8 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) (len > BTS_FILE_CMD_MAX_LEN) || (hdr->chnl != NFCWILINK_CHNL) || (hdr->opcode != NFCWILINK_OPCODE)) { - nfc_dev_err(&drv->pdev->dev, - "ignoring invalid bts cmd, len %d, chnl %d, opcode %d", + nfc_err(&drv->pdev->dev, + "ignoring invalid bts cmd, len %d, chnl %d, opcode %d\n", len, hdr->chnl, hdr->opcode); return 0; } @@ -221,7 +220,7 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) skb = nfcwilink_skb_alloc(len, GFP_KERNEL); if (!skb) { - nfc_dev_err(&drv->pdev->dev, "no memory for bts cmd"); + nfc_err(&drv->pdev->dev, "no memory for bts cmd\n"); return -ENOMEM; } @@ -236,8 +235,8 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", comp_ret); if (comp_ret == 0) { - nfc_dev_err(&drv->pdev->dev, - "timeout on wait_for_completion_timeout"); + nfc_err(&drv->pdev->dev, + "timeout on wait_for_completion_timeout\n"); return -ETIMEDOUT; } @@ -260,7 +259,7 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) rc = request_firmware(&fw, file_name, &drv->pdev->dev); if (rc) { - nfc_dev_err(&drv->pdev->dev, "request_firmware failed %d", rc); + nfc_err(&drv->pdev->dev, "request_firmware failed %d\n", rc); /* if the file is not found, don't exit with failure */ if (rc == -ENOENT) @@ -280,7 +279,7 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) != BTS_FILE_HDR_MAGIC) { - nfc_dev_err(&drv->pdev->dev, "wrong bts magic number"); + nfc_err(&drv->pdev->dev, "wrong bts magic number\n"); rc = -EINVAL; goto release_fw; } @@ -361,7 +360,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) /* Forward skb to NCI core layer */ rc = nci_recv_frame(drv->ndev, skb); if (rc < 0) { - nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc); + nfc_err(&drv->pdev->dev, "nci_recv_frame failed %d\n", rc); return rc; } @@ -414,13 +413,12 @@ static int nfcwilink_open(struct nci_dev *ndev) goto clear_exit; } else if (drv->st_register_cb_status != 0) { rc = drv->st_register_cb_status; - nfc_dev_err(&drv->pdev->dev, - "st_register_cb failed %d", rc); + nfc_err(&drv->pdev->dev, + "st_register_cb failed %d\n", rc); goto clear_exit; } } else { - nfc_dev_err(&drv->pdev->dev, - "st_register failed %d", rc); + nfc_err(&drv->pdev->dev, "st_register failed %d\n", rc); goto clear_exit; } } @@ -430,8 +428,8 @@ static int nfcwilink_open(struct nci_dev *ndev) drv->st_write = nfcwilink_proto.write; if (nfcwilink_download_fw(drv)) { - nfc_dev_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d", - rc); + nfc_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d\n", + rc); /* open should succeed, even if the FW download failed */ } @@ -454,7 +452,7 @@ static int nfcwilink_close(struct nci_dev *ndev) rc = st_unregister(&nfcwilink_proto); if (rc) - nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc); + nfc_err(&drv->pdev->dev, "st_unregister failed %d\n", rc); drv->st_write = NULL; @@ -485,7 +483,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) len = drv->st_write(skb); if (len < 0) { kfree_skb(skb); - nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len); + nfc_err(&drv->pdev->dev, "st_write failed %ld\n", len); return -EFAULT; } @@ -523,7 +521,7 @@ static int nfcwilink_probe(struct platform_device *pdev) NFCWILINK_HDR_LEN, 0); if (!drv->ndev) { - nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); + nfc_err(&pdev->dev, "nci_allocate_device failed\n"); rc = -ENOMEM; goto exit; } @@ -533,7 +531,7 @@ static int nfcwilink_probe(struct platform_device *pdev) rc = nci_register_device(drv->ndev); if (rc < 0) { - nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc); + nfc_err(&pdev->dev, "nci_register_device failed %d\n", rc); goto free_dev_exit; } diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index e64bea53f0c8..a66dff6ed51c 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -728,8 +728,8 @@ static void pn533_recv_response(struct urb *urb) goto sched_wq; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, + "Urb failure (status %d)\n", urb->status); goto sched_wq; } @@ -740,14 +740,14 @@ static void pn533_recv_response(struct urb *urb) dev->ops->rx_frame_size(in_frame), false); if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { - nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); + nfc_err(&dev->interface->dev, "Received an invalid frame\n"); cmd->status = -EIO; goto sched_wq; } if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { - nfc_dev_err(&dev->interface->dev, - "It it not the response to the last command"); + nfc_err(&dev->interface->dev, + "It it not the response to the last command\n"); cmd->status = -EIO; goto sched_wq; } @@ -783,23 +783,23 @@ static void pn533_recv_ack(struct urb *urb) goto sched_wq; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, + "Urb failure (status %d)\n", urb->status); goto sched_wq; } in_frame = dev->in_urb->transfer_buffer; if (!pn533_std_rx_frame_is_ack(in_frame)) { - nfc_dev_err(&dev->interface->dev, "Received an invalid ack"); + nfc_err(&dev->interface->dev, "Received an invalid ack\n"); cmd->status = -EIO; goto sched_wq; } rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); if (rc) { - nfc_dev_err(&dev->interface->dev, - "usb_submit_urb failed with result %d", rc); + nfc_err(&dev->interface->dev, + "usb_submit_urb failed with result %d\n", rc); cmd->status = rc; goto sched_wq; } @@ -1172,8 +1172,8 @@ static void pn533_send_complete(struct urb *urb) break; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, "Urb failure (status %d)\n", + urb->status); } } @@ -1473,8 +1473,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); break; default: - nfc_dev_err(&dev->interface->dev, - "Unknown current poll modulation"); + nfc_err(&dev->interface->dev, + "Unknown current poll modulation\n"); return -EPROTO; } @@ -1695,8 +1695,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, comm_mode, gb, gb_len); if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Error when signaling target activation"); + nfc_err(&dev->interface->dev, + "Error when signaling target activation\n"); return rc; } @@ -1730,8 +1730,7 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_dev_err(&dev->interface->dev, "%s RF setting error %d", - __func__, rc); + nfc_err(&dev->interface->dev, "RF setting error %d", rc); return rc; } @@ -1762,7 +1761,7 @@ static void pn533_wq_rf(struct work_struct *work) pn533_rf_complete, NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_dev_err(&dev->interface->dev, "RF setting error %d", rc); + nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); } return; @@ -1779,8 +1778,8 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_dev_err(&dev->interface->dev, "%s Poll complete error %d", - __func__, rc); + nfc_err(&dev->interface->dev, "%s Poll complete error %d\n", + __func__, rc); if (rc == -ENOENT) { if (dev->poll_mod_count != 0) @@ -1788,8 +1787,8 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, else goto stop_poll; } else if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when running poll", rc); + nfc_err(&dev->interface->dev, + "Error %d when running poll\n", rc); goto stop_poll; } } @@ -1821,7 +1820,7 @@ done: return rc; stop_poll: - nfc_dev_err(&dev->interface->dev, "Polling operation has been stopped"); + nfc_err(&dev->interface->dev, "Polling operation has been stopped\n"); pn533_poll_reset_mod_list(dev); dev->poll_protocols = 0; @@ -1863,7 +1862,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) } if (!skb) { - nfc_dev_err(&dev->interface->dev, "Failed to allocate skb."); + nfc_err(&dev->interface->dev, "Failed to allocate skb\n"); return -ENOMEM; } @@ -1871,7 +1870,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); + nfc_err(&dev->interface->dev, "Polling loop error %d\n", rc); } return rc; @@ -1915,14 +1914,14 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, __func__, im_protocols, tm_protocols); if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll with a target already activated"); + nfc_err(&dev->interface->dev, + "Cannot poll with a target already activated\n"); return -EBUSY; } if (dev->tgt_mode) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll while already being activated"); + nfc_err(&dev->interface->dev, + "Cannot poll while already being activated\n"); return -EBUSY; } @@ -1985,8 +1984,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Target activation failed (error 0x%x)", rc); + nfc_err(&dev->interface->dev, + "Target activation failed (error 0x%x)\n", rc); dev_kfree_skb(resp); return -EIO; } @@ -2009,35 +2008,35 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, __func__, protocol); if (dev->poll_mod_count) { - dev_err(&dev->interface->dev, + nfc_err(&dev->interface->dev, "Cannot activate while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "There is already an active target"); + nfc_err(&dev->interface->dev, + "There is already an active target\n"); return -EBUSY; } if (!dev->tgt_available_prots) { - nfc_dev_err(&dev->interface->dev, - "There is no available target to activate"); + nfc_err(&dev->interface->dev, + "There is no available target to activate\n"); return -EINVAL; } if (!(dev->tgt_available_prots & (1 << protocol))) { - nfc_dev_err(&dev->interface->dev, - "Target doesn't support requested proto %u", - protocol); + nfc_err(&dev->interface->dev, + "Target doesn't support requested proto %u\n", + protocol); return -EINVAL; } if (protocol == NFC_PROTO_NFC_DEP) { rc = pn533_activate_target_nfcdep(dev); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Activating target with DEP failed %d", rc); + nfc_err(&dev->interface->dev, + "Activating target with DEP failed %d\n", rc); return rc; } } @@ -2059,7 +2058,7 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, "There is no active target"); + nfc_err(&dev->interface->dev, "There is no active target\n"); return; } @@ -2078,8 +2077,8 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, rc = resp->data[0] & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) - nfc_dev_err(&dev->interface->dev, - "Error 0x%x when releasing the target", rc); + nfc_err(&dev->interface->dev, + "Error 0x%x when releasing the target\n", rc); dev_kfree_skb(resp); return; @@ -2101,8 +2100,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { - nfc_dev_err(&dev->interface->dev, - "The target does not support DEP"); + nfc_err(&dev->interface->dev, + "The target does not support DEP\n"); rc = -EINVAL; goto error; } @@ -2111,8 +2110,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Bringing DEP link up failed (error 0x%x)", rc); + nfc_err(&dev->interface->dev, + "Bringing DEP link up failed (error 0x%x)\n", rc); goto error; } @@ -2161,14 +2160,14 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, dev_dbg(&dev->interface->dev, "%s\n", __func__); if (dev->poll_mod_count) { - nfc_dev_err(&dev->interface->dev, - "Cannot bring the DEP link up while polling"); + nfc_err(&dev->interface->dev, + "Cannot bring the DEP link up while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "There is already an active target"); + nfc_err(&dev->interface->dev, + "There is already an active target\n"); return -EBUSY; } @@ -2318,8 +2317,8 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, skb_pull(resp, sizeof(status)); if (ret != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Exchanging data failed (error 0x%x)", ret); + nfc_err(&dev->interface->dev, + "Exchanging data failed (error 0x%x)\n", ret); rc = -EIO; goto error; } @@ -2412,8 +2411,8 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "Can't exchange data if there is no active target"); + nfc_err(&dev->interface->dev, + "Can't exchange data if there is no active target\n"); rc = -EINVAL; goto error; } @@ -2506,9 +2505,9 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) dev_dbg(&dev->interface->dev, "%s\n", __func__); if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { - nfc_dev_err(&dev->interface->dev, - "Data length greater than the max allowed: %d", - PN533_CMD_DATAEXCH_DATA_MAXLEN); + nfc_err(&dev->interface->dev, + "Data length greater than the max allowed: %d\n", + PN533_CMD_DATAEXCH_DATA_MAXLEN); return -ENOSYS; } @@ -2558,8 +2557,8 @@ static void pn533_wq_mi_recv(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_dev_err(&dev->interface->dev, - "Error %d when trying to perform data_exchange", rc); + nfc_err(&dev->interface->dev, + "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_mi_arg); @@ -2613,8 +2612,8 @@ static void pn533_wq_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_dev_err(&dev->interface->dev, - "Error %d when trying to perform data_exchange", rc); + nfc_err(&dev->interface->dev, + "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_dep_arg); @@ -2742,16 +2741,15 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Reader power on cmd error %d", rc); + nfc_err(&dev->interface->dev, + "Reader power on cmd error %d\n", rc); return rc; } rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Can't submit for reader power on cmd response %d", - rc); + nfc_err(&dev->interface->dev, + "Can't submit reader poweron cmd response %d\n", rc); return rc; } @@ -2772,8 +2770,7 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, (u8 *)&rf_field, 1); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF field"); + nfc_err(&dev->interface->dev, "Error on setting RF field\n"); return rc; } @@ -2826,16 +2823,16 @@ static int pn533_setup(struct pn533 *dev) break; default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); + nfc_err(&dev->interface->dev, "Unknown device type %d\n", + dev->device_type); return -EINVAL; } rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, (u8 *)&max_retries, sizeof(max_retries)); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting MAX_RETRIES config"); + nfc_err(&dev->interface->dev, + "Error on setting MAX_RETRIES config\n"); return rc; } @@ -2843,8 +2840,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, (u8 *)&timing, sizeof(timing)); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF timings"); + nfc_err(&dev->interface->dev, "Error on setting RF timings\n"); return rc; } @@ -2858,8 +2854,8 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, pasori_cfg, 3); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error while settings PASORI config"); + nfc_err(&dev->interface->dev, + "Error while settings PASORI config\n"); return rc; } @@ -2904,8 +2900,8 @@ static int pn533_probe(struct usb_interface *interface, } if (!in_endpoint || !out_endpoint) { - nfc_dev_err(&interface->dev, - "Could not find bulk-in or bulk-out endpoint"); + nfc_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint\n"); rc = -ENODEV; goto error; } @@ -2965,16 +2961,15 @@ static int pn533_probe(struct usb_interface *interface, rc = pn533_acr122_poweron_rdr(dev); if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Couldn't poweron the reader (error %d)", - rc); + nfc_err(&dev->interface->dev, + "Couldn't poweron the reader (error %d)\n", rc); goto destroy_wq; } break; default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); + nfc_err(&dev->interface->dev, "Unknown device type %d\n", + dev->device_type); rc = -EINVAL; goto destroy_wq; } @@ -2984,9 +2979,9 @@ static int pn533_probe(struct usb_interface *interface, if (rc < 0) goto destroy_wq; - nfc_dev_info(&dev->interface->dev, - "NXP PN5%02X firmware ver %d.%d now attached", - fw_ver.ic, fw_ver.ver, fw_ver.rev); + nfc_info(&dev->interface->dev, + "NXP PN5%02X firmware ver %d.%d now attached\n", + fw_ver.ic, fw_ver.ver, fw_ver.rev); dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, @@ -3057,7 +3052,7 @@ static void pn533_disconnect(struct usb_interface *interface) usb_free_urb(dev->out_urb); kfree(dev); - nfc_dev_info(&interface->dev, "NXP PN533 NFC device disconnected"); + nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); } static struct usb_driver pn533_driver = { diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index a164c46bed7e..f5c6a23636f1 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -28,8 +28,8 @@ #include #include -#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg) -#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg) +#define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__) +#define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__) struct nfc_dev; -- cgit From d593751129ec26762412b2fa7afe9c9258923340 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 2 Sep 2013 12:35:39 +0200 Subject: NFC: NCI: Rename spi ndev -> nsdev and nci_dev -> ndev for consistency An hci dev is an hdev. An nci dev is an ndev. Calling an nci spi dev an ndev is misleading since it's not the same thing. The nci dev contained in the nci spi dev is also named inconsistently. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 26 ++++----- net/nfc/nci/spi.c | 128 ++++++++++++++++++++++----------------------- 2 files changed, 77 insertions(+), 77 deletions(-) (limited to 'include') diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 99fc1f3a392a..c08399621c8b 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -210,14 +210,14 @@ int nci_to_errno(__u8 code); struct nci_spi_dev; struct nci_spi_ops { - int (*open)(struct nci_spi_dev *ndev); - int (*close)(struct nci_spi_dev *ndev); - void (*assert_int)(struct nci_spi_dev *ndev); - void (*deassert_int)(struct nci_spi_dev *ndev); + int (*open)(struct nci_spi_dev *nsdev); + int (*close)(struct nci_spi_dev *nsdev); + void (*assert_int)(struct nci_spi_dev *nsdev); + void (*deassert_int)(struct nci_spi_dev *nsdev); }; struct nci_spi_dev { - struct nci_dev *nci_dev; + struct nci_dev *ndev; struct spi_device *spi; struct nci_spi_ops *ops; @@ -238,20 +238,20 @@ struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, u32 supported_se, u8 acknowledge_mode, unsigned int delay); -void nci_spi_free_device(struct nci_spi_dev *ndev); -int nci_spi_register_device(struct nci_spi_dev *ndev); -void nci_spi_unregister_device(struct nci_spi_dev *ndev); -int nci_spi_recv_frame(struct nci_spi_dev *ndev); +void nci_spi_free_device(struct nci_spi_dev *nsdev); +int nci_spi_register_device(struct nci_spi_dev *nsdev); +void nci_spi_unregister_device(struct nci_spi_dev *nsdev); +int nci_spi_recv_frame(struct nci_spi_dev *nsdev); -static inline void nci_spi_set_drvdata(struct nci_spi_dev *ndev, +static inline void nci_spi_set_drvdata(struct nci_spi_dev *nsdev, void *data) { - ndev->driver_data = data; + nsdev->driver_data = data; } -static inline void *nci_spi_get_drvdata(struct nci_spi_dev *ndev) +static inline void *nci_spi_get_drvdata(struct nci_spi_dev *nsdev) { - return ndev->driver_data; + return nsdev->driver_data; } #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index b6795955432d..e66fda4d9ede 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -41,21 +41,21 @@ #define CRC_INIT 0xFFFF -static int nci_spi_open(struct nci_dev *nci_dev) +static int nci_spi_open(struct nci_dev *ndev) { - struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - return ndev->ops->open(ndev); + return nsdev->ops->open(nsdev); } -static int nci_spi_close(struct nci_dev *nci_dev) +static int nci_spi_close(struct nci_dev *ndev) { - struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - return ndev->ops->close(ndev); + return nsdev->ops->close(nsdev); } -static int __nci_spi_send(struct nci_spi_dev *ndev, struct sk_buff *skb) +static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) { struct spi_message m; struct spi_transfer t; @@ -63,32 +63,32 @@ static int __nci_spi_send(struct nci_spi_dev *ndev, struct sk_buff *skb) t.tx_buf = skb->data; t.len = skb->len; t.cs_change = 0; - t.delay_usecs = ndev->xfer_udelay; + t.delay_usecs = nsdev->xfer_udelay; spi_message_init(&m); spi_message_add_tail(&t, &m); - return spi_sync(ndev->spi, &m); + return spi_sync(nsdev->spi, &m); } -static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) +static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) { - struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); unsigned int payload_len = skb->len; unsigned char *hdr; int ret; long completion_rc; - ndev->ops->deassert_int(ndev); + nsdev->ops->deassert_int(nsdev); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); hdr[0] = NCI_SPI_DIRECT_WRITE; - hdr[1] = ndev->acknowledge_mode; + hdr[1] = nsdev->acknowledge_mode; hdr[2] = payload_len >> 8; hdr[3] = payload_len & 0xFF; - if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { u16 crc; crc = crc_ccitt(CRC_INIT, skb->data, skb->len); @@ -96,20 +96,20 @@ static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) *skb_put(skb, 1) = crc & 0xFF; } - ret = __nci_spi_send(ndev, skb); + ret = __nci_spi_send(nsdev, skb); kfree_skb(skb); - ndev->ops->assert_int(ndev); + nsdev->ops->assert_int(nsdev); - if (ret != 0 || ndev->acknowledge_mode == NCI_SPI_CRC_DISABLED) + if (ret != 0 || nsdev->acknowledge_mode == NCI_SPI_CRC_DISABLED) goto done; - init_completion(&ndev->req_completion); - completion_rc = - wait_for_completion_interruptible_timeout(&ndev->req_completion, - NCI_SPI_SEND_TIMEOUT); + init_completion(&nsdev->req_completion); + completion_rc = wait_for_completion_interruptible_timeout( + &nsdev->req_completion, + NCI_SPI_SEND_TIMEOUT); - if (completion_rc <= 0 || ndev->req_result == ACKNOWLEDGE_NACK) + if (completion_rc <= 0 || nsdev->req_result == ACKNOWLEDGE_NACK) ret = -EIO; done: @@ -141,7 +141,7 @@ struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, u8 acknowledge_mode, unsigned int delay) { - struct nci_spi_dev *ndev; + struct nci_spi_dev *nsdev; int tailroom = 0; if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) @@ -150,36 +150,36 @@ struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, if (!supported_protocols) return NULL; - ndev = devm_kzalloc(&spi->dev, sizeof(struct nci_spi_dev), GFP_KERNEL); - if (!ndev) + nsdev = devm_kzalloc(&spi->dev, sizeof(struct nci_spi_dev), GFP_KERNEL); + if (!nsdev) return NULL; - ndev->ops = ops; - ndev->acknowledge_mode = acknowledge_mode; - ndev->xfer_udelay = delay; + nsdev->ops = ops; + nsdev->acknowledge_mode = acknowledge_mode; + nsdev->xfer_udelay = delay; if (acknowledge_mode == NCI_SPI_CRC_ENABLED) tailroom += NCI_SPI_CRC_LEN; - ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, - NCI_SPI_HDR_LEN, tailroom); - if (!ndev->nci_dev) + nsdev->ndev = nci_allocate_device(&nci_spi_ops, supported_protocols, + NCI_SPI_HDR_LEN, tailroom); + if (!nsdev->ndev) return NULL; - nci_set_drvdata(ndev->nci_dev, ndev); + nci_set_drvdata(nsdev->ndev, nsdev); - return ndev; + return nsdev; } EXPORT_SYMBOL_GPL(nci_spi_allocate_device); /** * nci_spi_free_device - deallocate nci spi device * - * @ndev: The nci spi device to deallocate + * @nsdev: The nci spi device to deallocate */ -void nci_spi_free_device(struct nci_spi_dev *ndev) +void nci_spi_free_device(struct nci_spi_dev *nsdev) { - nci_free_device(ndev->nci_dev); + nci_free_device(nsdev->ndev); } EXPORT_SYMBOL_GPL(nci_spi_free_device); @@ -188,9 +188,9 @@ EXPORT_SYMBOL_GPL(nci_spi_free_device); * * @pdev: The nci spi device to register */ -int nci_spi_register_device(struct nci_spi_dev *ndev) +int nci_spi_register_device(struct nci_spi_dev *nsdev) { - return nci_register_device(ndev->nci_dev); + return nci_register_device(nsdev->ndev); } EXPORT_SYMBOL_GPL(nci_spi_register_device); @@ -199,20 +199,20 @@ EXPORT_SYMBOL_GPL(nci_spi_register_device); * * @dev: The nci spi device to unregister */ -void nci_spi_unregister_device(struct nci_spi_dev *ndev) +void nci_spi_unregister_device(struct nci_spi_dev *nsdev) { - nci_unregister_device(ndev->nci_dev); + nci_unregister_device(nsdev->ndev); } EXPORT_SYMBOL_GPL(nci_spi_unregister_device); -static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) +static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) { struct sk_buff *skb; unsigned char *hdr; u16 crc; int ret; - skb = nci_skb_alloc(ndev->nci_dev, 0, GFP_KERNEL); + skb = nci_skb_alloc(nsdev->ndev, 0, GFP_KERNEL); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); @@ -225,14 +225,14 @@ static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) *skb_put(skb, 1) = crc >> 8; *skb_put(skb, 1) = crc & 0xFF; - ret = __nci_spi_send(ndev, skb); + ret = __nci_spi_send(nsdev, skb); kfree_skb(skb); return ret; } -static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) +static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) { struct sk_buff *skb; struct spi_message m; @@ -243,7 +243,7 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) spi_message_init(&m); req[0] = NCI_SPI_DIRECT_READ; - req[1] = ndev->acknowledge_mode; + req[1] = nsdev->acknowledge_mode; tx.tx_buf = req; tx.len = 2; tx.cs_change = 0; @@ -252,18 +252,18 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) rx.len = 2; rx.cs_change = 1; spi_message_add_tail(&rx, &m); - ret = spi_sync(ndev->spi, &m); + ret = spi_sync(nsdev->spi, &m); if (ret) return NULL; - if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + resp_hdr[1] + NCI_SPI_CRC_LEN; else rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; - skb = nci_skb_alloc(ndev->nci_dev, rx_len, GFP_KERNEL); + skb = nci_skb_alloc(nsdev->ndev, rx_len, GFP_KERNEL); if (!skb) return NULL; @@ -271,14 +271,14 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) rx.rx_buf = skb_put(skb, rx_len); rx.len = rx_len; rx.cs_change = 0; - rx.delay_usecs = ndev->xfer_udelay; + rx.delay_usecs = nsdev->xfer_udelay; spi_message_add_tail(&rx, &m); - ret = spi_sync(ndev->spi, &m); + ret = spi_sync(nsdev->spi, &m); if (ret) goto receive_error; - if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { *skb_push(skb, 1) = resp_hdr[1]; *skb_push(skb, 1) = resp_hdr[0]; } @@ -320,7 +320,7 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) /** * nci_spi_recv_frame - receive frame from NCI SPI drivers * - * @ndev: The nci spi device + * @nsdev: The nci spi device * Context: can sleep * * This call may only be used from a context that may sleep. The sleep @@ -328,32 +328,32 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) * * It returns zero on success, else a negative error code. */ -int nci_spi_recv_frame(struct nci_spi_dev *ndev) +int nci_spi_recv_frame(struct nci_spi_dev *nsdev) { struct sk_buff *skb; int ret = 0; - ndev->ops->deassert_int(ndev); + nsdev->ops->deassert_int(nsdev); /* Retrieve frame from SPI */ - skb = __nci_spi_recv_frame(ndev); + skb = __nci_spi_recv_frame(nsdev); if (!skb) { ret = -EIO; goto done; } - if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { if (!nci_spi_check_crc(skb)) { - send_acknowledge(ndev, ACKNOWLEDGE_NACK); + send_acknowledge(nsdev, ACKNOWLEDGE_NACK); goto done; } /* In case of acknowledged mode: if ACK or NACK received, * unblock completion of latest frame sent. */ - ndev->req_result = nci_spi_get_ack(skb); - if (ndev->req_result) - complete(&ndev->req_completion); + nsdev->req_result = nci_spi_get_ack(skb); + if (nsdev->req_result) + complete(&nsdev->req_completion); } /* If there is no payload (ACK/NACK only frame), @@ -364,14 +364,14 @@ int nci_spi_recv_frame(struct nci_spi_dev *ndev) goto done; } - if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) - send_acknowledge(ndev, ACKNOWLEDGE_ACK); + if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + send_acknowledge(nsdev, ACKNOWLEDGE_ACK); /* Forward skb to NCI core layer */ - ret = nci_recv_frame(ndev->nci_dev, skb); + ret = nci_recv_frame(nsdev->ndev, skb); done: - ndev->ops->assert_int(ndev); + nsdev->ops->assert_int(nsdev); return ret; } -- cgit From 08f13acff960d6c95a371f67ab98785aa9969179 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 3 Sep 2013 11:51:00 +0200 Subject: NFC: Move struct nfc_phy_ops out of HCI up to nfc core level struct nfc_phy_ops is not an HCI structure only, it can also be used by NCI or direct NFC Core drivers. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/hci.h | 6 ------ include/net/nfc/nfc.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index b64b7bce4b94..2eca2960ca9c 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -24,12 +24,6 @@ #include -struct nfc_phy_ops { - int (*write)(void *dev_id, struct sk_buff *skb); - int (*enable)(void *dev_id); - void (*disable)(void *dev_id); -}; - struct nfc_hci_dev; struct nfc_hci_ops { diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index f5c6a23636f1..c2aee4875b65 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -31,6 +31,12 @@ #define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__) #define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__) +struct nfc_phy_ops { + int (*write)(void *dev_id, struct sk_buff *skb); + int (*enable)(void *dev_id); + void (*disable)(void *dev_id); +}; + struct nfc_dev; /** -- cgit From fa544fff62aeeb0cf8008c61077aae10fb1407a9 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Thu, 5 Sep 2013 11:02:21 +0200 Subject: NFC: NCI: Simplify NCI SPI to become a simple framing/checking layer NCI SPI layer should not manage the nci dev, this is the job of the nci chipset driver. This layer should be limited to frame/deframe nci packets, and optionnaly check integrity (crc) and manage the ack/nak protocol. The NCI SPI must not be mixed up with an NCI dev. spi_[dev|device] are therefore renamed to a simple spi for more clarity. The header and crc sizes are moved to nci.h so that drivers can use them to reserve space in outgoing skbs. nci_spi_send() is exported to be accessible by drivers. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/nci.h | 4 + include/net/nfc/nci_core.h | 41 +++-------- net/nfc/nci/spi.c | 180 ++++++++++++++------------------------------- 3 files changed, 70 insertions(+), 155 deletions(-) (limited to 'include') diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h index 88785e5c6b2c..e5aa5acafea0 100644 --- a/include/net/nfc/nci.h +++ b/include/net/nfc/nci.h @@ -166,6 +166,10 @@ #define NCI_GID_NFCEE_MGMT 0x2 #define NCI_GID_PROPRIETARY 0xf +/* ----- NCI over SPI head/crc(tail) room needed for outgoing frames ----- */ +#define NCI_SPI_HDR_LEN 4 +#define NCI_SPI_CRC_LEN 2 + /* ---- NCI Packet structures ---- */ #define NCI_CTRL_HDR_SIZE 3 #define NCI_DATA_HDR_SIZE 3 diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index c08399621c8b..37ba06f2dfa9 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -207,16 +207,14 @@ int nci_to_errno(__u8 code); #define NCI_SPI_CRC_ENABLED 0x01 /* ----- NCI SPI structures ----- */ -struct nci_spi_dev; +struct nci_spi; struct nci_spi_ops { - int (*open)(struct nci_spi_dev *nsdev); - int (*close)(struct nci_spi_dev *nsdev); - void (*assert_int)(struct nci_spi_dev *nsdev); - void (*deassert_int)(struct nci_spi_dev *nsdev); + void (*assert_int)(struct nci_spi *nspi); + void (*deassert_int)(struct nci_spi *nspi); }; -struct nci_spi_dev { +struct nci_spi { struct nci_dev *ndev; struct spi_device *spi; struct nci_spi_ops *ops; @@ -227,31 +225,14 @@ struct nci_spi_dev { struct completion req_completion; u8 req_result; - - void *driver_data; }; -/* ----- NCI SPI Devices ----- */ -struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, - struct nci_spi_ops *ops, - u32 supported_protocols, - u32 supported_se, - u8 acknowledge_mode, - unsigned int delay); -void nci_spi_free_device(struct nci_spi_dev *nsdev); -int nci_spi_register_device(struct nci_spi_dev *nsdev); -void nci_spi_unregister_device(struct nci_spi_dev *nsdev); -int nci_spi_recv_frame(struct nci_spi_dev *nsdev); - -static inline void nci_spi_set_drvdata(struct nci_spi_dev *nsdev, - void *data) -{ - nsdev->driver_data = data; -} - -static inline void *nci_spi_get_drvdata(struct nci_spi_dev *nsdev) -{ - return nsdev->driver_data; -} +/* ----- NCI SPI ----- */ +struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, + struct nci_spi_ops *ops, + u8 acknowledge_mode, unsigned int delay, + struct nci_dev *ndev); +int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb); +int nci_spi_recv_frame(struct nci_spi *nspi); #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index e66fda4d9ede..910dfd8015f4 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -24,8 +24,6 @@ #include #include -#define NCI_SPI_HDR_LEN 4 -#define NCI_SPI_CRC_LEN 2 #define NCI_SPI_ACK_SHIFT 6 #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F @@ -41,21 +39,7 @@ #define CRC_INIT 0xFFFF -static int nci_spi_open(struct nci_dev *ndev) -{ - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - - return nsdev->ops->open(nsdev); -} - -static int nci_spi_close(struct nci_dev *ndev) -{ - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - - return nsdev->ops->close(nsdev); -} - -static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) +static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) { struct spi_message m; struct spi_transfer t; @@ -63,32 +47,31 @@ static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) t.tx_buf = skb->data; t.len = skb->len; t.cs_change = 0; - t.delay_usecs = nsdev->xfer_udelay; + t.delay_usecs = nspi->xfer_udelay; spi_message_init(&m); spi_message_add_tail(&t, &m); - return spi_sync(nsdev->spi, &m); + return spi_sync(nspi->spi, &m); } -static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) +int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) { - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); unsigned int payload_len = skb->len; unsigned char *hdr; int ret; long completion_rc; - nsdev->ops->deassert_int(nsdev); + nspi->ops->deassert_int(nspi); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); hdr[0] = NCI_SPI_DIRECT_WRITE; - hdr[1] = nsdev->acknowledge_mode; + hdr[1] = nspi->acknowledge_mode; hdr[2] = payload_len >> 8; hdr[3] = payload_len & 0xFF; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { u16 crc; crc = crc_ccitt(CRC_INIT, skb->data, skb->len); @@ -96,123 +79,70 @@ static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) *skb_put(skb, 1) = crc & 0xFF; } - ret = __nci_spi_send(nsdev, skb); + ret = __nci_spi_send(nspi, skb); kfree_skb(skb); - nsdev->ops->assert_int(nsdev); + nspi->ops->assert_int(nspi); - if (ret != 0 || nsdev->acknowledge_mode == NCI_SPI_CRC_DISABLED) + if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) goto done; - init_completion(&nsdev->req_completion); + init_completion(&nspi->req_completion); completion_rc = wait_for_completion_interruptible_timeout( - &nsdev->req_completion, + &nspi->req_completion, NCI_SPI_SEND_TIMEOUT); - if (completion_rc <= 0 || nsdev->req_result == ACKNOWLEDGE_NACK) + if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK) ret = -EIO; done: return ret; } - -static struct nci_ops nci_spi_ops = { - .open = nci_spi_open, - .close = nci_spi_close, - .send = nci_spi_send, -}; +EXPORT_SYMBOL_GPL(nci_spi_send); /* ---- Interface to NCI SPI drivers ---- */ /** - * nci_spi_allocate_device - allocate a new nci spi device + * nci_spi_allocate_spi - allocate a new nci spi * * @spi: SPI device * @ops: device operations - * @supported_protocols: NFC protocols supported by the device - * @supported_se: NFC Secure Elements supported by the device - * @acknowledge_mode: Acknowledge mode used by the device + * @acknowledge_mode: Acknowledge mode used by the NFC device * @delay: delay between transactions in us + * @ndev: nci dev to send incoming nci frames to */ -struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, - struct nci_spi_ops *ops, - u32 supported_protocols, - u32 supported_se, - u8 acknowledge_mode, - unsigned int delay) +struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, + struct nci_spi_ops *ops, + u8 acknowledge_mode, unsigned int delay, + struct nci_dev *ndev) { - struct nci_spi_dev *nsdev; - int tailroom = 0; - - if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) - return NULL; - - if (!supported_protocols) - return NULL; + struct nci_spi *nspi; - nsdev = devm_kzalloc(&spi->dev, sizeof(struct nci_spi_dev), GFP_KERNEL); - if (!nsdev) + if (!ops->assert_int || !ops->deassert_int) return NULL; - nsdev->ops = ops; - nsdev->acknowledge_mode = acknowledge_mode; - nsdev->xfer_udelay = delay; - - if (acknowledge_mode == NCI_SPI_CRC_ENABLED) - tailroom += NCI_SPI_CRC_LEN; - - nsdev->ndev = nci_allocate_device(&nci_spi_ops, supported_protocols, - NCI_SPI_HDR_LEN, tailroom); - if (!nsdev->ndev) + nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); + if (!nspi) return NULL; - nci_set_drvdata(nsdev->ndev, nsdev); - - return nsdev; -} -EXPORT_SYMBOL_GPL(nci_spi_allocate_device); - -/** - * nci_spi_free_device - deallocate nci spi device - * - * @nsdev: The nci spi device to deallocate - */ -void nci_spi_free_device(struct nci_spi_dev *nsdev) -{ - nci_free_device(nsdev->ndev); -} -EXPORT_SYMBOL_GPL(nci_spi_free_device); + nspi->ops = ops; + nspi->acknowledge_mode = acknowledge_mode; + nspi->xfer_udelay = delay; -/** - * nci_spi_register_device - register a nci spi device in the nfc subsystem - * - * @pdev: The nci spi device to register - */ -int nci_spi_register_device(struct nci_spi_dev *nsdev) -{ - return nci_register_device(nsdev->ndev); -} -EXPORT_SYMBOL_GPL(nci_spi_register_device); + nspi->ndev = ndev; -/** - * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem - * - * @dev: The nci spi device to unregister - */ -void nci_spi_unregister_device(struct nci_spi_dev *nsdev) -{ - nci_unregister_device(nsdev->ndev); + return nspi; } -EXPORT_SYMBOL_GPL(nci_spi_unregister_device); +EXPORT_SYMBOL_GPL(nci_spi_allocate_spi); -static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) +static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) { struct sk_buff *skb; unsigned char *hdr; u16 crc; int ret; - skb = nci_skb_alloc(nsdev->ndev, 0, GFP_KERNEL); + skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); @@ -225,14 +155,14 @@ static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) *skb_put(skb, 1) = crc >> 8; *skb_put(skb, 1) = crc & 0xFF; - ret = __nci_spi_send(nsdev, skb); + ret = __nci_spi_send(nspi, skb); kfree_skb(skb); return ret; } -static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) +static struct sk_buff *__nci_spi_recv_frame(struct nci_spi *nspi) { struct sk_buff *skb; struct spi_message m; @@ -243,7 +173,7 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) spi_message_init(&m); req[0] = NCI_SPI_DIRECT_READ; - req[1] = nsdev->acknowledge_mode; + req[1] = nspi->acknowledge_mode; tx.tx_buf = req; tx.len = 2; tx.cs_change = 0; @@ -252,18 +182,18 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) rx.len = 2; rx.cs_change = 1; spi_message_add_tail(&rx, &m); - ret = spi_sync(nsdev->spi, &m); + ret = spi_sync(nspi->spi, &m); if (ret) return NULL; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + resp_hdr[1] + NCI_SPI_CRC_LEN; else rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; - skb = nci_skb_alloc(nsdev->ndev, rx_len, GFP_KERNEL); + skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL); if (!skb) return NULL; @@ -271,14 +201,14 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) rx.rx_buf = skb_put(skb, rx_len); rx.len = rx_len; rx.cs_change = 0; - rx.delay_usecs = nsdev->xfer_udelay; + rx.delay_usecs = nspi->xfer_udelay; spi_message_add_tail(&rx, &m); - ret = spi_sync(nsdev->spi, &m); + ret = spi_sync(nspi->spi, &m); if (ret) goto receive_error; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { *skb_push(skb, 1) = resp_hdr[1]; *skb_push(skb, 1) = resp_hdr[0]; } @@ -320,7 +250,7 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) /** * nci_spi_recv_frame - receive frame from NCI SPI drivers * - * @nsdev: The nci spi device + * @nspi: The nci spi * Context: can sleep * * This call may only be used from a context that may sleep. The sleep @@ -328,32 +258,32 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) * * It returns zero on success, else a negative error code. */ -int nci_spi_recv_frame(struct nci_spi_dev *nsdev) +int nci_spi_recv_frame(struct nci_spi *nspi) { struct sk_buff *skb; int ret = 0; - nsdev->ops->deassert_int(nsdev); + nspi->ops->deassert_int(nspi); /* Retrieve frame from SPI */ - skb = __nci_spi_recv_frame(nsdev); + skb = __nci_spi_recv_frame(nspi); if (!skb) { ret = -EIO; goto done; } - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { if (!nci_spi_check_crc(skb)) { - send_acknowledge(nsdev, ACKNOWLEDGE_NACK); + send_acknowledge(nspi, ACKNOWLEDGE_NACK); goto done; } /* In case of acknowledged mode: if ACK or NACK received, * unblock completion of latest frame sent. */ - nsdev->req_result = nci_spi_get_ack(skb); - if (nsdev->req_result) - complete(&nsdev->req_completion); + nspi->req_result = nci_spi_get_ack(skb); + if (nspi->req_result) + complete(&nspi->req_completion); } /* If there is no payload (ACK/NACK only frame), @@ -364,14 +294,14 @@ int nci_spi_recv_frame(struct nci_spi_dev *nsdev) goto done; } - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) - send_acknowledge(nsdev, ACKNOWLEDGE_ACK); + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) + send_acknowledge(nspi, ACKNOWLEDGE_ACK); /* Forward skb to NCI core layer */ - ret = nci_recv_frame(nsdev->ndev, skb); + ret = nci_recv_frame(nspi->ndev, skb); done: - nsdev->ops->assert_int(nsdev); + nspi->ops->assert_int(nspi); return ret; } -- cgit From 4b10884eb428c243ae2070a539612e645f3d9b93 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 19 Sep 2013 17:55:25 +0200 Subject: NFC: Digital Protocol stack implementation This is the initial commit of the NFC Digital Protocol stack implementation. It offers an interface for devices that don't have an embedded NFC Digital protocol stack. The driver instantiates the digital stack by calling nfc_digital_allocate_device(). Within the nfc_digital_ops structure, the driver specifies a set of function pointers for driver operations. These functions must be implemented by the driver and are: in_configure_hw: Hardware configuration for RF technology and communication framing in initiator mode. This is a synchronous function. in_send_cmd: Initiator mode data exchange using RF technology and framing previously set with in_configure_hw. The peer response is returned through callback cb. If an io error occurs or the peer didn't reply within the specified timeout (ms), the error code is passed back through the resp pointer. This is an asynchronous function. tg_configure_hw: Hardware configuration for RF technology and communication framing in target mode. This is a synchronous function. tg_send_cmd: Target mode data exchange using RF technology and framing previously set with tg_configure_hw. The peer next command is returned through callback cb. If an io error occurs or the peer didn't reply within the specified timeout (ms), the error code is passed back through the resp pointer. This is an asynchronous function. tg_listen: Put the device in listen mode waiting for data from the peer device. This is an asynchronous function. tg_listen_mdaa: If supported, put the device in automatic listen mode with mode detection and automatic anti-collision. In this mode, the device automatically detects the RF technology and executes the anti-collision detection using the command responses specified in mdaa_params. The mdaa_params structure contains SENS_RES, NFCID1, and SEL_RES for 106A RF tech. NFCID2 and system code (sc) for 212F and 424F. The driver returns the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF tech by analyzing the SoD of the frame containing the ATR_REQ command. This is an asynchronous function. switch_rf: Turns device radio on or off. The stack does not call explicitly switch_rf to turn the radio on. A call to in|tg_configure_hw must turn the device radio on. abort_cmd: Discard the last sent command. Then the driver registers itself against the digital stack by using nfc_digital_register_device() which in turn registers the digital stack against the NFC core layer. The digital stack implements common NFC operations like dev_up(), dev_down(), start_poll(), stop_poll(), etc. This patch is only a skeleton and NFC operations are just stubs. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- include/net/nfc/digital.h | 199 ++++++++++++++++++++++++++++++++++++++++++++++ net/nfc/Kconfig | 12 +++ net/nfc/Makefile | 2 + net/nfc/digital.h | 27 +++++++ net/nfc/digital_core.c | 151 +++++++++++++++++++++++++++++++++++ 5 files changed, 391 insertions(+) create mode 100644 include/net/nfc/digital.h create mode 100644 net/nfc/digital.h create mode 100644 net/nfc/digital_core.c (limited to 'include') diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h new file mode 100644 index 000000000000..8e16b6e0265a --- /dev/null +++ b/include/net/nfc/digital.h @@ -0,0 +1,199 @@ +/* + * NFC Digital Protocol stack + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __NFC_DIGITAL_H +#define __NFC_DIGITAL_H + +#include +#include + +/** + * Configuration types for in_configure_hw and tg_configure_hw. + */ +enum { + NFC_DIGITAL_CONFIG_RF_TECH = 0, + NFC_DIGITAL_CONFIG_FRAMING, +}; + +/** + * RF technology values passed as param argument to in_configure_hw and + * tg_configure_hw for NFC_DIGITAL_CONFIG_RF_TECH configuration type. + */ +enum { + NFC_DIGITAL_RF_TECH_106A = 0, + NFC_DIGITAL_RF_TECH_212F, + NFC_DIGITAL_RF_TECH_424F, + + NFC_DIGITAL_RF_TECH_LAST, +}; + +/** + * Framing configuration passed as param argument to in_configure_hw and + * tg_configure_hw for NFC_DIGITAL_CONFIG_FRAMING configuration type. + */ +enum { + NFC_DIGITAL_FRAMING_NFCA_SHORT = 0, + NFC_DIGITAL_FRAMING_NFCA_STANDARD, + NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A, + + NFC_DIGITAL_FRAMING_NFCA_T1T, + NFC_DIGITAL_FRAMING_NFCA_T2T, + NFC_DIGITAL_FRAMING_NFCA_NFC_DEP, + + NFC_DIGITAL_FRAMING_NFCF, + NFC_DIGITAL_FRAMING_NFCF_T3T, + NFC_DIGITAL_FRAMING_NFCF_NFC_DEP, + NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED, + + NFC_DIGITAL_FRAMING_LAST, +}; + +#define DIGITAL_MDAA_NFCID1_SIZE 3 + +struct digital_tg_mdaa_params { + u16 sens_res; + u8 nfcid1[DIGITAL_MDAA_NFCID1_SIZE]; + u8 sel_res; + + u8 nfcid2[NFC_NFCID2_MAXSIZE]; + u16 sc; +}; + +struct nfc_digital_dev; + +/** + * nfc_digital_cmd_complete_t - Definition of command result callback + * + * @ddev: nfc_digital_device ref + * @arg: user data + * @resp: response data + * + * resp pointer can be an error code and will be checked with IS_ERR() macro. + * The callback is responsible for freeing resp sk_buff. + */ +typedef void (*nfc_digital_cmd_complete_t)(struct nfc_digital_dev *ddev, + void *arg, struct sk_buff *resp); + +/** + * Device side NFC Digital operations + * + * Initiator mode: + * @in_configure_hw: Hardware configuration for RF technology and communication + * framing in initiator mode. This is a synchronous function. + * @in_send_cmd: Initiator mode data exchange using RF technology and framing + * previously set with in_configure_hw. The peer response is returned + * through callback cb. If an io error occurs or the peer didn't reply + * within the specified timeout (ms), the error code is passed back through + * the resp pointer. This is an asynchronous function. + * + * Target mode: Only NFC-DEP protocol is supported in target mode. + * @tg_configure_hw: Hardware configuration for RF technology and communication + * framing in target mode. This is a synchronous function. + * @tg_send_cmd: Target mode data exchange using RF technology and framing + * previously set with tg_configure_hw. The peer next command is returned + * through callback cb. If an io error occurs or the peer didn't reply + * within the specified timeout (ms), the error code is passed back through + * the resp pointer. This is an asynchronous function. + * @tg_listen: Put the device in listen mode waiting for data from the peer + * device. This is an asynchronous function. + * @tg_listen_mdaa: If supported, put the device in automatic listen mode with + * mode detection and automatic anti-collision. In this mode, the device + * automatically detects the RF technology and executes the anti-collision + * detection using the command responses specified in mdaa_params. The + * mdaa_params structure contains SENS_RES, NFCID1, and SEL_RES for 106A RF + * tech. NFCID2 and system code (sc) for 212F and 424F. The driver returns + * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF + * tech by analyzing the SoD of the frame containing the ATR_REQ command. + * This is an asynchronous function. + * + * @switch_rf: Turns device radio on or off. The stack does not call explicitly + * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn + * the device radio on. + * @abort_cmd: Discard the last sent command. + */ +struct nfc_digital_ops { + int (*in_configure_hw)(struct nfc_digital_dev *ddev, int type, + int param); + int (*in_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb, + u16 timeout, nfc_digital_cmd_complete_t cb, + void *arg); + + int (*tg_configure_hw)(struct nfc_digital_dev *ddev, int type, + int param); + int (*tg_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb, + u16 timeout, nfc_digital_cmd_complete_t cb, + void *arg); + int (*tg_listen)(struct nfc_digital_dev *ddev, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg); + int (*tg_listen_mdaa)(struct nfc_digital_dev *ddev, + struct digital_tg_mdaa_params *mdaa_params, + u16 timeout, nfc_digital_cmd_complete_t cb, + void *arg); + + int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); + void (*abort_cmd)(struct nfc_digital_dev *ddev); +}; + +/** + * Driver capabilities - bit mask made of the following values + * + * @NFC_DIGITAL_DRV_CAPS_IN_CRC: The driver handles CRC calculation in initiator + * mode. + * @NFC_DIGITAL_DRV_CAPS_TG_CRC: The driver handles CRC calculation in target + * mode. + */ +#define NFC_DIGITAL_DRV_CAPS_IN_CRC 0x0001 +#define NFC_DIGITAL_DRV_CAPS_TG_CRC 0x0002 + +struct nfc_digital_dev { + struct nfc_dev *nfc_dev; + struct nfc_digital_ops *ops; + + u32 protocols; + + int tx_headroom; + int tx_tailroom; + + u32 driver_capabilities; + void *driver_data; +}; + +struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, + __u32 supported_protocols, + __u32 driver_capabilities, + int tx_headroom, + int tx_tailroom); +void nfc_digital_free_device(struct nfc_digital_dev *ndev); +int nfc_digital_register_device(struct nfc_digital_dev *ndev); +void nfc_digital_unregister_device(struct nfc_digital_dev *ndev); + +static inline void nfc_digital_set_parent_dev(struct nfc_digital_dev *ndev, + struct device *dev) +{ + nfc_set_parent_dev(ndev->nfc_dev, dev); +} + +static inline void nfc_digital_set_drvdata(struct nfc_digital_dev *dev, + void *data) +{ + dev->driver_data = data; +} + +static inline void *nfc_digital_get_drvdata(struct nfc_digital_dev *dev) +{ + return dev->driver_data; +} + +#endif /* __NFC_DIGITAL_H */ diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 5948b2fc72f6..13e1237e1ea1 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig @@ -14,6 +14,18 @@ menuconfig NFC To compile this support as a module, choose M here: the module will be called nfc. +config NFC_DIGITAL + depends on NFC + tristate "NFC Digital Protocol stack support" + default n + help + Say Y if you want to build NFC digital protocol stack support. + This is needed by NFC chipsets whose firmware only implement + the NFC analog layer. + + To compile this support as a module, choose M here: the module will + be called nfc_digital. + source "net/nfc/nci/Kconfig" source "net/nfc/hci/Kconfig" diff --git a/net/nfc/Makefile b/net/nfc/Makefile index a76f4533cb6c..8e0cabd85e99 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile @@ -5,7 +5,9 @@ obj-$(CONFIG_NFC) += nfc.o obj-$(CONFIG_NFC_NCI) += nci/ obj-$(CONFIG_NFC_HCI) += hci/ +obj-$(CONFIG_NFC_DIGITAL) += nfc_digital.o nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ llcp_sock.o +nfc_digital-objs := digital_core.o diff --git a/net/nfc/digital.h b/net/nfc/digital.h new file mode 100644 index 000000000000..8d91ed820912 --- /dev/null +++ b/net/nfc/digital.h @@ -0,0 +1,27 @@ +/* + * NFC Digital Protocol stack + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DIGITAL_H +#define __DIGITAL_H + +#include +#include + +#define PR_DBG(fmt, ...) pr_debug("%s: " fmt "\n", __func__, ##__VA_ARGS__) +#define PR_ERR(fmt, ...) pr_err("%s: " fmt "\n", __func__, ##__VA_ARGS__) +#define PROTOCOL_ERR(req) pr_err("%s:%d: NFC Digital Protocol error: %s\n", \ + __func__, __LINE__, req) + +#endif /* __DIGITAL_H */ diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c new file mode 100644 index 000000000000..471188a0d2e0 --- /dev/null +++ b/net/nfc/digital_core.c @@ -0,0 +1,151 @@ +/* + * NFC Digital Protocol stack + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include + +#include "digital.h" + +static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, + __u32 tm_protocols) +{ + return -EOPNOTSUPP; +} + +static void digital_stop_poll(struct nfc_dev *nfc_dev) +{ +} + +static int digital_dev_up(struct nfc_dev *nfc_dev) +{ + return -EOPNOTSUPP; +} + +static int digital_dev_down(struct nfc_dev *nfc_dev) +{ + return -EOPNOTSUPP; +} + +static int digital_dep_link_up(struct nfc_dev *nfc_dev, + struct nfc_target *target, + __u8 comm_mode, __u8 *gb, size_t gb_len) +{ + return -EOPNOTSUPP; +} + +static int digital_dep_link_down(struct nfc_dev *nfc_dev) +{ + return -EOPNOTSUPP; +} + +static int digital_activate_target(struct nfc_dev *nfc_dev, + struct nfc_target *target, __u32 protocol) +{ + return -EOPNOTSUPP; +} + +static void digital_deactivate_target(struct nfc_dev *nfc_dev, + struct nfc_target *target) +{ +} + +static int digital_tg_send(struct nfc_dev *dev, struct sk_buff *skb) +{ + return -EOPNOTSUPP; +} + +static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, + struct sk_buff *skb, data_exchange_cb_t cb, + void *cb_context) +{ + return -EOPNOTSUPP; +} + +static struct nfc_ops digital_nfc_ops = { + .dev_up = digital_dev_up, + .dev_down = digital_dev_down, + .start_poll = digital_start_poll, + .stop_poll = digital_stop_poll, + .dep_link_up = digital_dep_link_up, + .dep_link_down = digital_dep_link_down, + .activate_target = digital_activate_target, + .deactivate_target = digital_deactivate_target, + .tm_send = digital_tg_send, + .im_transceive = digital_in_send, +}; + +struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, + __u32 supported_protocols, + __u32 driver_capabilities, + int tx_headroom, int tx_tailroom) +{ + struct nfc_digital_dev *ddev; + + if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || + !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || + !ops->switch_rf) + return NULL; + + ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); + if (!ddev) { + PR_ERR("kzalloc failed"); + return NULL; + } + + ddev->driver_capabilities = driver_capabilities; + ddev->ops = ops; + + ddev->tx_headroom = tx_headroom; + ddev->tx_tailroom = tx_tailroom; + + ddev->nfc_dev = nfc_allocate_device(&digital_nfc_ops, ddev->protocols, + ddev->tx_headroom, + ddev->tx_tailroom); + if (!ddev->nfc_dev) { + PR_ERR("nfc_allocate_device failed"); + goto free_dev; + } + + nfc_set_drvdata(ddev->nfc_dev, ddev); + + return ddev; + +free_dev: + kfree(ddev); + + return NULL; +} +EXPORT_SYMBOL(nfc_digital_allocate_device); + +void nfc_digital_free_device(struct nfc_digital_dev *ddev) +{ + nfc_free_device(ddev->nfc_dev); + + kfree(ddev); +} +EXPORT_SYMBOL(nfc_digital_free_device); + +int nfc_digital_register_device(struct nfc_digital_dev *ddev) +{ + return nfc_register_device(ddev->nfc_dev); +} +EXPORT_SYMBOL(nfc_digital_register_device); + +void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) +{ + nfc_unregister_device(ddev->nfc_dev); +} +EXPORT_SYMBOL(nfc_digital_unregister_device); + +MODULE_LICENSE("GPL"); -- cgit From 59ee2361c9248f07846f7a6e585768dcce18fb16 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 19 Sep 2013 17:55:26 +0200 Subject: NFC Digital: Implement driver commands mechanism This implements the mechanism used to send commands to the driver in initiator mode through in_send_cmd(). Commands are serialized and sent to the driver by using a work item on the system workqueue. Responses are handled asynchronously by another work item. Once the digital stack receives the response through the command_complete callback, the next command is sent to the driver. This also implements the polling mechanism. It's handled by a work item cycling on all supported protocols. The start poll command for a given protocol is sent to the driver using the mechanism described above. The process continues until a peer is discovered or stop_poll is called. This patch implements the poll function for NFC-A that sends a SENS_REQ command and waits for the SENS_RES response. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- include/net/nfc/digital.h | 25 ++++ net/nfc/Makefile | 2 +- net/nfc/digital.h | 29 ++++ net/nfc/digital_core.c | 340 ++++++++++++++++++++++++++++++++++++++++++- net/nfc/digital_technology.c | 64 ++++++++ 5 files changed, 452 insertions(+), 8 deletions(-) create mode 100644 net/nfc/digital_technology.c (limited to 'include') diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index 8e16b6e0265a..aabd89400d23 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h @@ -146,6 +146,15 @@ struct nfc_digital_ops { void (*abort_cmd)(struct nfc_digital_dev *ddev); }; +#define NFC_DIGITAL_POLL_MODE_COUNT_MAX 6 /* 106A, 212F, and 424F in & tg */ + +typedef int (*digital_poll_t)(struct nfc_digital_dev *ddev, u8 rf_tech); + +struct digital_poll_tech { + u8 rf_tech; + digital_poll_t poll_func; +}; + /** * Driver capabilities - bit mask made of the following values * @@ -168,6 +177,22 @@ struct nfc_digital_dev { u32 driver_capabilities; void *driver_data; + + struct digital_poll_tech poll_techs[NFC_DIGITAL_POLL_MODE_COUNT_MAX]; + u8 poll_tech_count; + u8 poll_tech_index; + struct mutex poll_lock; + + struct work_struct cmd_work; + struct work_struct cmd_complete_work; + struct list_head cmd_queue; + struct mutex cmd_lock; + + struct work_struct poll_work; + + u8 curr_protocol; + u8 curr_rf_tech; + u8 curr_nfc_dep_pni; }; struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, diff --git a/net/nfc/Makefile b/net/nfc/Makefile index 8e0cabd85e99..2db39713a907 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile @@ -10,4 +10,4 @@ obj-$(CONFIG_NFC_DIGITAL) += nfc_digital.o nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ llcp_sock.o -nfc_digital-objs := digital_core.o +nfc_digital-objs := digital_core.o digital_technology.o diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 8d91ed820912..0a2767098daa 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h @@ -24,4 +24,33 @@ #define PROTOCOL_ERR(req) pr_err("%s:%d: NFC Digital Protocol error: %s\n", \ __func__, __LINE__, req) +#define DIGITAL_CMD_IN_SEND 0 +#define DIGITAL_CMD_TG_SEND 1 +#define DIGITAL_CMD_TG_LISTEN 2 +#define DIGITAL_CMD_TG_LISTEN_MDAA 3 + +#define DIGITAL_MAX_HEADER_LEN 7 +#define DIGITAL_CRC_LEN 2 + +struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, + unsigned int len); + +int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, + struct sk_buff *skb, u16 timeout, + nfc_digital_cmd_complete_t cmd_cb, void *cb_context); + +int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param); +static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev, + struct sk_buff *skb, u16 timeout, + nfc_digital_cmd_complete_t cmd_cb, + void *cb_context) +{ + return digital_send_cmd(ddev, DIGITAL_CMD_IN_SEND, skb, timeout, cmd_cb, + cb_context); +} + +void digital_poll_next_tech(struct nfc_digital_dev *ddev); + +int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); + #endif /* __DIGITAL_H */ diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 471188a0d2e0..13abd293ca37 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -17,24 +17,319 @@ #include "digital.h" +#define DIGITAL_PROTO_NFCA_RF_TECH \ + (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK) + +struct digital_cmd { + struct list_head queue; + + u8 type; + u8 pending; + + u16 timeout; + struct sk_buff *req; + struct sk_buff *resp; + + nfc_digital_cmd_complete_t cmd_cb; + void *cb_context; +}; + +struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, + unsigned int len) +{ + struct sk_buff *skb; + + skb = alloc_skb(len + ddev->tx_headroom + ddev->tx_tailroom, + GFP_KERNEL); + if (skb) + skb_reserve(skb, ddev->tx_headroom); + + return skb; +} + +static inline void digital_switch_rf(struct nfc_digital_dev *ddev, bool on) +{ + ddev->ops->switch_rf(ddev, on); +} + +static inline void digital_abort_cmd(struct nfc_digital_dev *ddev) +{ + ddev->ops->abort_cmd(ddev); +} + +static void digital_wq_cmd_complete(struct work_struct *work) +{ + struct digital_cmd *cmd; + struct nfc_digital_dev *ddev = container_of(work, + struct nfc_digital_dev, + cmd_complete_work); + + mutex_lock(&ddev->cmd_lock); + + cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, + queue); + if (!cmd) { + mutex_unlock(&ddev->cmd_lock); + return; + } + + list_del(&cmd->queue); + + mutex_unlock(&ddev->cmd_lock); + + if (!IS_ERR(cmd->resp)) + print_hex_dump_debug("DIGITAL RX: ", DUMP_PREFIX_NONE, 16, 1, + cmd->resp->data, cmd->resp->len, false); + + cmd->cmd_cb(ddev, cmd->cb_context, cmd->resp); + + kfree(cmd); + + schedule_work(&ddev->cmd_work); +} + +static void digital_send_cmd_complete(struct nfc_digital_dev *ddev, + void *arg, struct sk_buff *resp) +{ + struct digital_cmd *cmd = arg; + + cmd->resp = resp; + + schedule_work(&ddev->cmd_complete_work); +} + +static void digital_wq_cmd(struct work_struct *work) +{ + int rc; + struct digital_cmd *cmd; + struct nfc_digital_dev *ddev = container_of(work, + struct nfc_digital_dev, + cmd_work); + + mutex_lock(&ddev->cmd_lock); + + cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, + queue); + if (!cmd || cmd->pending) { + mutex_unlock(&ddev->cmd_lock); + return; + } + + mutex_unlock(&ddev->cmd_lock); + + if (cmd->req) + print_hex_dump_debug("DIGITAL TX: ", DUMP_PREFIX_NONE, 16, 1, + cmd->req->data, cmd->req->len, false); + + switch (cmd->type) { + case DIGITAL_CMD_IN_SEND: + rc = ddev->ops->in_send_cmd(ddev, cmd->req, cmd->timeout, + digital_send_cmd_complete, cmd); + break; + default: + PR_ERR("Unknown cmd type %d", cmd->type); + return; + } + + if (!rc) + return; + + PR_ERR("in_send_command returned err %d", rc); + + mutex_lock(&ddev->cmd_lock); + list_del(&cmd->queue); + mutex_unlock(&ddev->cmd_lock); + + kfree_skb(cmd->req); + kfree(cmd); + + schedule_work(&ddev->cmd_work); +} + +int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, + struct sk_buff *skb, u16 timeout, + nfc_digital_cmd_complete_t cmd_cb, void *cb_context) +{ + struct digital_cmd *cmd; + + cmd = kzalloc(sizeof(struct digital_cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->type = cmd_type; + cmd->timeout = timeout; + cmd->req = skb; + cmd->cmd_cb = cmd_cb; + cmd->cb_context = cb_context; + INIT_LIST_HEAD(&cmd->queue); + + mutex_lock(&ddev->cmd_lock); + list_add_tail(&cmd->queue, &ddev->cmd_queue); + mutex_unlock(&ddev->cmd_lock); + + schedule_work(&ddev->cmd_work); + + return 0; +} + +int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param) +{ + int rc; + + rc = ddev->ops->in_configure_hw(ddev, type, param); + if (rc) + PR_ERR("in_configure_hw failed: %d", rc); + + return rc; +} + +void digital_poll_next_tech(struct nfc_digital_dev *ddev) +{ + digital_switch_rf(ddev, 0); + + mutex_lock(&ddev->poll_lock); + + if (!ddev->poll_tech_count) { + mutex_unlock(&ddev->poll_lock); + return; + } + + ddev->poll_tech_index = (ddev->poll_tech_index + 1) % + ddev->poll_tech_count; + + mutex_unlock(&ddev->poll_lock); + + schedule_work(&ddev->poll_work); +} + +static void digital_wq_poll(struct work_struct *work) +{ + int rc; + struct digital_poll_tech *poll_tech; + struct nfc_digital_dev *ddev = container_of(work, + struct nfc_digital_dev, + poll_work); + mutex_lock(&ddev->poll_lock); + + if (!ddev->poll_tech_count) { + mutex_unlock(&ddev->poll_lock); + return; + } + + poll_tech = &ddev->poll_techs[ddev->poll_tech_index]; + + mutex_unlock(&ddev->poll_lock); + + rc = poll_tech->poll_func(ddev, poll_tech->rf_tech); + if (rc) + digital_poll_next_tech(ddev); +} + +static void digital_add_poll_tech(struct nfc_digital_dev *ddev, u8 rf_tech, + digital_poll_t poll_func) +{ + struct digital_poll_tech *poll_tech; + + if (ddev->poll_tech_count >= NFC_DIGITAL_POLL_MODE_COUNT_MAX) + return; + + poll_tech = &ddev->poll_techs[ddev->poll_tech_count++]; + + poll_tech->rf_tech = rf_tech; + poll_tech->poll_func = poll_func; +} + +/** + * start_poll operation + * + * For every supported protocol, the corresponding polling function is added + * to the table of polling technologies (ddev->poll_techs[]) using + * digital_add_poll_tech(). + * When a polling function fails (by timeout or protocol error) the next one is + * schedule by digital_poll_next_tech() on the poll workqueue (ddev->poll_work). + */ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, __u32 tm_protocols) { - return -EOPNOTSUPP; + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + u32 matching_im_protocols, matching_tm_protocols; + + PR_DBG("protocols: im 0x%x, tm 0x%x, supported 0x%x", im_protocols, + tm_protocols, ddev->protocols); + + matching_im_protocols = ddev->protocols & im_protocols; + matching_tm_protocols = ddev->protocols & tm_protocols; + + if (!matching_im_protocols && !matching_tm_protocols) { + PR_ERR("No known protocol"); + return -EINVAL; + } + + if (ddev->poll_tech_count) { + PR_ERR("Already polling"); + return -EBUSY; + } + + if (ddev->curr_protocol) { + PR_ERR("A target is already active"); + return -EBUSY; + } + + ddev->poll_tech_count = 0; + ddev->poll_tech_index = 0; + + if (matching_im_protocols & DIGITAL_PROTO_NFCA_RF_TECH) + digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, + digital_in_send_sens_req); + + if (!ddev->poll_tech_count) { + PR_ERR("Unsupported protocols: im=0x%x, tm=0x%x", + matching_im_protocols, matching_tm_protocols); + return -EINVAL; + } + + schedule_work(&ddev->poll_work); + + return 0; } static void digital_stop_poll(struct nfc_dev *nfc_dev) { + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + + mutex_lock(&ddev->poll_lock); + + if (!ddev->poll_tech_count) { + PR_ERR("Polling operation was not running"); + mutex_unlock(&ddev->poll_lock); + return; + } + + ddev->poll_tech_count = 0; + + mutex_unlock(&ddev->poll_lock); + + cancel_work_sync(&ddev->poll_work); + + digital_abort_cmd(ddev); } static int digital_dev_up(struct nfc_dev *nfc_dev) { - return -EOPNOTSUPP; + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + + digital_switch_rf(ddev, 1); + + return 0; } static int digital_dev_down(struct nfc_dev *nfc_dev) { - return -EOPNOTSUPP; + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + + digital_switch_rf(ddev, 0); + + return 0; } static int digital_dep_link_up(struct nfc_dev *nfc_dev, @@ -52,12 +347,15 @@ static int digital_dep_link_down(struct nfc_dev *nfc_dev) static int digital_activate_target(struct nfc_dev *nfc_dev, struct nfc_target *target, __u32 protocol) { - return -EOPNOTSUPP; + return 0; } static void digital_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target) { + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + + ddev->curr_protocol = 0; } static int digital_tg_send(struct nfc_dev *dev, struct sk_buff *skb) @@ -106,8 +404,22 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, ddev->driver_capabilities = driver_capabilities; ddev->ops = ops; - ddev->tx_headroom = tx_headroom; - ddev->tx_tailroom = tx_tailroom; + mutex_init(&ddev->cmd_lock); + INIT_LIST_HEAD(&ddev->cmd_queue); + + INIT_WORK(&ddev->cmd_work, digital_wq_cmd); + INIT_WORK(&ddev->cmd_complete_work, digital_wq_cmd_complete); + + mutex_init(&ddev->poll_lock); + INIT_WORK(&ddev->poll_work, digital_wq_poll); + + if (supported_protocols & NFC_PROTO_JEWEL_MASK) + ddev->protocols |= NFC_PROTO_JEWEL_MASK; + if (supported_protocols & NFC_PROTO_MIFARE_MASK) + ddev->protocols |= NFC_PROTO_MIFARE_MASK; + + ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; + ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; ddev->nfc_dev = nfc_allocate_device(&digital_nfc_ops, ddev->protocols, ddev->tx_headroom, @@ -131,7 +443,6 @@ EXPORT_SYMBOL(nfc_digital_allocate_device); void nfc_digital_free_device(struct nfc_digital_dev *ddev) { nfc_free_device(ddev->nfc_dev); - kfree(ddev); } EXPORT_SYMBOL(nfc_digital_free_device); @@ -144,7 +455,22 @@ EXPORT_SYMBOL(nfc_digital_register_device); void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) { + struct digital_cmd *cmd, *n; + nfc_unregister_device(ddev->nfc_dev); + + mutex_lock(&ddev->poll_lock); + ddev->poll_tech_count = 0; + mutex_unlock(&ddev->poll_lock); + + cancel_work_sync(&ddev->poll_work); + cancel_work_sync(&ddev->cmd_work); + cancel_work_sync(&ddev->cmd_complete_work); + + list_for_each_entry_safe(cmd, n, &ddev->cmd_queue, queue) { + list_del(&cmd->queue); + kfree(cmd); + } } EXPORT_SYMBOL(nfc_digital_unregister_device); diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c new file mode 100644 index 000000000000..084b0fba5f4d --- /dev/null +++ b/net/nfc/digital_technology.c @@ -0,0 +1,64 @@ +/* + * NFC Digital Protocol stack + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "digital.h" + +#define DIGITAL_CMD_SENS_REQ 0x26 +#define DIGITAL_CMD_ALL_REQ 0x52 +#define DIGITAL_CMD_SEL_REQ_CL1 0x93 +#define DIGITAL_CMD_SEL_REQ_CL2 0x95 +#define DIGITAL_CMD_SEL_REQ_CL3 0x97 + +#define DIGITAL_SDD_REQ_SEL_PAR 0x20 + +#define DIGITAL_SDD_RES_CT 0x88 +#define DIGITAL_SDD_RES_LEN 5 + +static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg, + struct sk_buff *resp) +{ + if (!IS_ERR(resp)) + dev_kfree_skb(resp); + + digital_poll_next_tech(ddev); +} + +int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech) +{ + struct sk_buff *skb; + int rc; + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, + NFC_DIGITAL_RF_TECH_106A); + if (rc) + return rc; + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_NFCA_SHORT); + if (rc) + return rc; + + skb = digital_skb_alloc(ddev, 1); + if (!skb) + return -ENOMEM; + + *skb_put(skb, sizeof(u8)) = DIGITAL_CMD_SENS_REQ; + + rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sens_res, NULL); + if (rc) + kfree_skb(skb); + + return rc; +} -- cgit From 2c66daecc4092e6049673c281b2e6f0d5e59a94c Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 19 Sep 2013 17:55:27 +0200 Subject: NFC Digital: Add NFC-A technology support This adds support for NFC-A technology at 106 kbits/s. The stack can detect tags of type 1 and 2. There is no support for collision detection. Tags can be read and written by using a user space application or a daemon like neard. The flow of polling operations for NFC-A detection is as follow: 1 - The digital stack sends the SENS_REQ command to the NFC device. 2 - The NFC device receives a SENS_RES response from a peer device and passes it to the digital stack. 3 - If the SENS_RES response identifies a type 1 tag, detection ends. NFC core is notified through nfc_targets_found(). 4 - Otherwise, the digital stack sets the cascade level of NFCID1 to CL1 and sends the SDD_REQ command. 5 - The digital stack selects SEL_CMD and SEL_PAR according to the cascade level and sends the SDD_REQ command. 4 - The digital stack receives a SDD_RES response for the cascade level passed in the SDD_REQ command. 5 - The digital stack analyses (part of) NFCID1 and verify BCC. 6 - The digital stack sends the SEL_REQ command with the NFCID1 received in the SDD_RES. 6 - The peer device replies with a SEL_RES response 7 - Detection ends if NFCID1 is complete. NFC core notified of new target by nfc_targets_found(). 8 - If NFCID1 is not complete, the cascade level is incremented (up to and including CL3) and the execution continues at step 5 to get the remaining bytes of NFCID1. Once target detection is done, type 1 and 2 tag commands must be handled by a user space application (i.e neard) through the NFC core. Responses for type 1 tag are returned directly to user space via NFC core. Responses of type 2 commands are handled differently. The digital stack doesn't analyse the type of commands sent through im_transceive() and must differentiate valid responses from error ones. The response process flow is as follow: 1 - If the response length is 16 bytes, it is a valid response of a READ command. the packet is returned to the NFC core through the callback passed to im_transceive(). Processing stops. 2 - If the response is 1 byte long and is a ACK byte (0x0A), it is a valid response of a WRITE command for example. First packet byte is set to 0 for no-error and passed back to the NFC core. Processing stops. 3 - Any other response is treated as an error and -EIO error code is returned to the NFC core through the response callback. Moreover, since the driver can't differentiate success response from a NACK response, the digital stack has to handle CRC calculation. Thus, this patch also adds support for CRC calculation. If the driver doesn't handle it, the digital stack will calculate CRC and will add it to sent frames. CRC will also be checked and removed from received frames. Pointers to the correct CRC calculation functions are stored in the digital stack device structure when a target is detected. This avoids the need to check the current target type for every call to im_transceive() and for every response received from a peer device. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- include/net/nfc/digital.h | 3 + net/nfc/Kconfig | 1 + net/nfc/digital.h | 58 +++++++++ net/nfc/digital_core.c | 145 +++++++++++++++++++++- net/nfc/digital_technology.c | 288 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 491 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index aabd89400d23..36acecd5f06c 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h @@ -193,6 +193,9 @@ struct nfc_digital_dev { u8 curr_protocol; u8 curr_rf_tech; u8 curr_nfc_dep_pni; + + int (*skb_check_crc)(struct sk_buff *skb); + void (*skb_add_crc)(struct sk_buff *skb); }; struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 13e1237e1ea1..4f4d2481325a 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig @@ -16,6 +16,7 @@ menuconfig NFC config NFC_DIGITAL depends on NFC + select CRC_CCITT tristate "NFC Digital Protocol stack support" default n help diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 0a2767098daa..fb5324b792de 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h @@ -19,6 +19,8 @@ #include #include +#include + #define PR_DBG(fmt, ...) pr_debug("%s: " fmt "\n", __func__, ##__VA_ARGS__) #define PR_ERR(fmt, ...) pr_err("%s: " fmt "\n", __func__, ##__VA_ARGS__) #define PROTOCOL_ERR(req) pr_err("%s:%d: NFC Digital Protocol error: %s\n", \ @@ -32,6 +34,16 @@ #define DIGITAL_MAX_HEADER_LEN 7 #define DIGITAL_CRC_LEN 2 +#define DIGITAL_DRV_CAPS_IN_CRC(ddev) \ + ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_IN_CRC) +#define DIGITAL_DRV_CAPS_TG_CRC(ddev) \ + ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_TG_CRC) + +struct digital_data_exch { + data_exchange_cb_t cb; + void *cb_context; +}; + struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, unsigned int len); @@ -53,4 +65,50 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev); int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); +int digital_target_found(struct nfc_digital_dev *ddev, + struct nfc_target *target, u8 protocol); + +int digital_in_recv_mifare_res(struct sk_buff *resp); + +typedef u16 (*crc_func_t)(u16, const u8 *, size_t); + +#define CRC_A_INIT 0x6363 +#define CRC_B_INIT 0xFFFF + +void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, + u8 bitwise_inv, u8 msb_first); + +static inline void digital_skb_add_crc_a(struct sk_buff *skb) +{ + digital_skb_add_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); +} + +static inline void digital_skb_add_crc_b(struct sk_buff *skb) +{ + digital_skb_add_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); +} + +static inline void digital_skb_add_crc_none(struct sk_buff *skb) +{ + return; +} + +int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, + u16 crc_init, u8 bitwise_inv, u8 msb_first); + +static inline int digital_skb_check_crc_a(struct sk_buff *skb) +{ + return digital_skb_check_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); +} + +static inline int digital_skb_check_crc_b(struct sk_buff *skb) +{ + return digital_skb_check_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); +} + +static inline int digital_skb_check_crc_none(struct sk_buff *skb) +{ + return 0; +} + #endif /* __DIGITAL_H */ diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 13abd293ca37..4b3ceb45834b 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -47,6 +47,51 @@ struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, return skb; } +void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, + u8 bitwise_inv, u8 msb_first) +{ + u16 crc; + + crc = crc_func(init, skb->data, skb->len); + + if (bitwise_inv) + crc = ~crc; + + if (msb_first) + crc = __fswab16(crc); + + *skb_put(skb, 1) = crc & 0xFF; + *skb_put(skb, 1) = (crc >> 8) & 0xFF; +} + +int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, + u16 crc_init, u8 bitwise_inv, u8 msb_first) +{ + int rc; + u16 crc; + + if (skb->len <= 2) + return -EIO; + + crc = crc_func(crc_init, skb->data, skb->len - 2); + + if (bitwise_inv) + crc = ~crc; + + if (msb_first) + crc = __swab16(crc); + + rc = (skb->data[skb->len - 2] - (crc & 0xFF)) + + (skb->data[skb->len - 1] - ((crc >> 8) & 0xFF)); + + if (rc) + return -EIO; + + skb_trim(skb, skb->len - 2); + + return 0; +} + static inline void digital_switch_rf(struct nfc_digital_dev *ddev, bool on) { ddev->ops->switch_rf(ddev, on); @@ -183,6 +228,62 @@ int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param) return rc; } +int digital_target_found(struct nfc_digital_dev *ddev, + struct nfc_target *target, u8 protocol) +{ + int rc; + u8 framing; + u8 rf_tech; + int (*check_crc)(struct sk_buff *skb); + void (*add_crc)(struct sk_buff *skb); + + rf_tech = ddev->poll_techs[ddev->poll_tech_index].rf_tech; + + switch (protocol) { + case NFC_PROTO_JEWEL: + framing = NFC_DIGITAL_FRAMING_NFCA_T1T; + check_crc = digital_skb_check_crc_b; + add_crc = digital_skb_add_crc_b; + break; + + case NFC_PROTO_MIFARE: + framing = NFC_DIGITAL_FRAMING_NFCA_T2T; + check_crc = digital_skb_check_crc_a; + add_crc = digital_skb_add_crc_a; + break; + + default: + PR_ERR("Invalid protocol %d", protocol); + return -EINVAL; + } + + PR_DBG("rf_tech=%d, protocol=%d", rf_tech, protocol); + + ddev->curr_rf_tech = rf_tech; + ddev->curr_protocol = protocol; + + if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { + ddev->skb_add_crc = digital_skb_add_crc_none; + ddev->skb_check_crc = digital_skb_check_crc_none; + } else { + ddev->skb_add_crc = add_crc; + ddev->skb_check_crc = check_crc; + } + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, framing); + if (rc) + return rc; + + target->supported_protocols = (1 << protocol); + rc = nfc_targets_found(ddev->nfc_dev, target, 1); + if (rc) + return rc; + + ddev->poll_tech_count = 0; + + return 0; +} + void digital_poll_next_tech(struct nfc_digital_dev *ddev) { digital_switch_rf(ddev, 0); @@ -363,11 +464,53 @@ static int digital_tg_send(struct nfc_dev *dev, struct sk_buff *skb) return -EOPNOTSUPP; } +static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, + struct sk_buff *resp) +{ + struct digital_data_exch *data_exch = arg; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + goto done; + } + + if (ddev->curr_protocol == NFC_PROTO_MIFARE) + rc = digital_in_recv_mifare_res(resp); + else + rc = ddev->skb_check_crc(resp); + + if (rc) { + kfree_skb(resp); + resp = NULL; + } + +done: + data_exch->cb(data_exch->cb_context, resp, rc); + + kfree(data_exch); +} + static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context) { - return -EOPNOTSUPP; + struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + struct digital_data_exch *data_exch; + + data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); + if (!data_exch) { + PR_ERR("Failed to allocate data_exch struct"); + return -ENOMEM; + } + + data_exch->cb = cb; + data_exch->cb_context = cb_context; + + ddev->skb_add_crc(skb); + + return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, + data_exch); } static struct nfc_ops digital_nfc_ops = { diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 084b0fba5f4d..0cad38001c5f 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c @@ -26,13 +26,269 @@ #define DIGITAL_SDD_RES_CT 0x88 #define DIGITAL_SDD_RES_LEN 5 +#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) +#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) + +#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x000C) == 0x000C) +#define DIGITAL_SENS_RES_IS_VALID(sens_res) \ + ((!((sens_res) & 0x1F00) && (((sens_res) & 0x000C) == 0x000C)) || \ + (((sens_res) & 0x1F00) && ((sens_res) & 0x000C) != 0x000C)) + +#define DIGITAL_MIFARE_READ_RES_LEN 16 +#define DIGITAL_MIFARE_ACK_RES 0x0A + +struct digital_sdd_res { + u8 nfcid1[4]; + u8 bcc; +} __packed; + +struct digital_sel_req { + u8 sel_cmd; + u8 b2; + u8 nfcid1[4]; + u8 bcc; +} __packed; + +static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, + struct nfc_target *target); + +static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, + struct sk_buff *resp) +{ + struct nfc_target *target = arg; + int rc; + u8 sel_res; + u8 nfc_proto; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + resp = NULL; + goto exit; + } + + if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) { + rc = digital_skb_check_crc_a(resp); + if (rc) { + PROTOCOL_ERR("4.4.1.3"); + goto exit; + } + } + + if (!resp->len) { + rc = -EIO; + goto exit; + } + + sel_res = resp->data[0]; + + if (!DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res)) { + rc = digital_in_send_sdd_req(ddev, target); + if (rc) + goto exit; + + goto exit_free_skb; + } + + if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { + nfc_proto = NFC_PROTO_MIFARE; + } else { + rc = -EOPNOTSUPP; + goto exit; + } + + target->sel_res = sel_res; + + rc = digital_target_found(ddev, target, nfc_proto); + +exit: + kfree(target); + +exit_free_skb: + dev_kfree_skb(resp); + + if (rc) + digital_poll_next_tech(ddev); +} + +static int digital_in_send_sel_req(struct nfc_digital_dev *ddev, + struct nfc_target *target, + struct digital_sdd_res *sdd_res) +{ + struct sk_buff *skb; + struct digital_sel_req *sel_req; + u8 sel_cmd; + int rc; + + skb = digital_skb_alloc(ddev, sizeof(struct digital_sel_req)); + if (!skb) + return -ENOMEM; + + skb_put(skb, sizeof(struct digital_sel_req)); + sel_req = (struct digital_sel_req *)skb->data; + + if (target->nfcid1_len <= 4) + sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; + else if (target->nfcid1_len < 10) + sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; + else + sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; + + sel_req->sel_cmd = sel_cmd; + sel_req->b2 = 0x70; + memcpy(sel_req->nfcid1, sdd_res->nfcid1, 4); + sel_req->bcc = sdd_res->bcc; + + if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A); + if (rc) + goto exit; + } else { + digital_skb_add_crc_a(skb); + } + + rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sel_res, + target); +exit: + if (rc) + kfree_skb(skb); + + return rc; +} + +static void digital_in_recv_sdd_res(struct nfc_digital_dev *ddev, void *arg, + struct sk_buff *resp) +{ + struct nfc_target *target = arg; + struct digital_sdd_res *sdd_res; + int rc; + u8 offset, size; + u8 i, bcc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + resp = NULL; + goto exit; + } + + if (resp->len < DIGITAL_SDD_RES_LEN) { + PROTOCOL_ERR("4.7.2.8"); + rc = -EINVAL; + goto exit; + } + + sdd_res = (struct digital_sdd_res *)resp->data; + + for (i = 0, bcc = 0; i < 4; i++) + bcc ^= sdd_res->nfcid1[i]; + + if (bcc != sdd_res->bcc) { + PROTOCOL_ERR("4.7.2.6"); + rc = -EINVAL; + goto exit; + } + + if (sdd_res->nfcid1[0] == DIGITAL_SDD_RES_CT) { + offset = 1; + size = 3; + } else { + offset = 0; + size = 4; + } + + memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset, + size); + target->nfcid1_len += size; + + rc = digital_in_send_sel_req(ddev, target, sdd_res); + +exit: + dev_kfree_skb(resp); + + if (rc) { + kfree(target); + digital_poll_next_tech(ddev); + } +} + +static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, + struct nfc_target *target) +{ + int rc; + struct sk_buff *skb; + u8 sel_cmd; + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_NFCA_STANDARD); + if (rc) + return rc; + + skb = digital_skb_alloc(ddev, 2); + if (!skb) { + PR_ERR("alloc_skb failed"); + return -ENOMEM; + } + + if (target->nfcid1_len == 0) + sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; + else if (target->nfcid1_len == 3) + sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; + else + sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; + + *skb_put(skb, sizeof(u8)) = sel_cmd; + *skb_put(skb, sizeof(u8)) = DIGITAL_SDD_REQ_SEL_PAR; + + return digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res, + target); +} + static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg, struct sk_buff *resp) { - if (!IS_ERR(resp)) - dev_kfree_skb(resp); + struct nfc_target *target = NULL; + u16 sens_res; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + resp = NULL; + goto exit; + } + + if (resp->len < sizeof(u16)) { + rc = -EIO; + goto exit; + } + + target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); + if (!target) { + rc = -ENOMEM; + goto exit; + } + + memcpy(&target->sens_res, resp->data, sizeof(u16)); - digital_poll_next_tech(ddev); + sens_res = be16_to_cpu(target->sens_res); + + if (!DIGITAL_SENS_RES_IS_VALID(sens_res)) { + PROTOCOL_ERR("4.6.3.3"); + rc = -EINVAL; + goto exit; + } + + if (DIGITAL_SENS_RES_IS_T1T(sens_res)) + rc = digital_target_found(ddev, target, NFC_PROTO_JEWEL); + else + rc = digital_in_send_sdd_req(ddev, target); + +exit: + dev_kfree_skb(resp); + + if (rc) { + kfree(target); + digital_poll_next_tech(ddev); + } } int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech) @@ -62,3 +318,29 @@ int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech) return rc; } + +int digital_in_recv_mifare_res(struct sk_buff *resp) +{ + /* Successful READ command response is 16 data bytes + 2 CRC bytes long. + * Since the driver can't differentiate a ACK/NACK response from a valid + * READ response, the CRC calculation must be handled at digital level + * even if the driver supports it for this technology. + */ + if (resp->len == DIGITAL_MIFARE_READ_RES_LEN + DIGITAL_CRC_LEN) { + if (digital_skb_check_crc_a(resp)) { + PROTOCOL_ERR("9.4.1.2"); + return -EIO; + } + + return 0; + } + + /* ACK response (i.e. successful WRITE). */ + if (resp->len == 1 && resp->data[0] == DIGITAL_MIFARE_ACK_RES) { + resp->data[0] = 0; + return 0; + } + + /* NACK and any other responses are treated as error. */ + return -EIO; +} -- cgit From b9c0c678f7267831b73e1d73fb30c9b4658e91ec Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 24 Sep 2013 12:40:44 +0200 Subject: NFC: Document NFC targets sens_res field SENS_RES has no specific endiannes attached to it, the kernel ABI is the following one: Byte 2 (As described by the NFC Forum Digital spec) is the u16 most significant byte. Signed-off-by: Samuel Ortiz --- include/net/nfc/nfc.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index c2aee4875b65..5329804ebb70 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -85,6 +85,14 @@ struct nfc_ops { #define NFC_MAX_GT_LEN 48 #define NFC_ATR_RES_GT_OFFSET 15 +/** + * struct nfc_target - NFC target descriptiom + * + * @sens_res: 2 bytes describing the target SENS_RES response, if the target + * is a type A one. The %sens_res most significant byte must be byte 2 + * as described by the NFC Forum digital specification (i.e. the platform + * configuration one) while %sens_res least significant byte is byte 1. + */ struct nfc_target { u32 idx; u32 supported_protocols; -- cgit From 72b70b6ec4fa7da86a3ac0aacee699b18d94fc3b Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 28 Aug 2013 00:39:48 +0200 Subject: NFC: Define secure element IO API and commands In order to send and receive ISO7816 APDUs to and from NFC embedded secure elements, we define a specific netlink command. On a typical SE use case, host applications will send very few APDUs (Less than 10) per transaction. This is why we decided to go for a simple netlink API. Defining another NFC socket protocol for such low traffic would have been overengineered. Signed-off-by: Samuel Ortiz --- include/net/nfc/nfc.h | 5 +++++ include/uapi/linux/nfc.h | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 5329804ebb70..82fc4e43fc6e 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -53,6 +53,8 @@ struct nfc_dev; typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, int err); +typedef void (*se_io_cb_t)(void *context, u8 *apdu, size_t apdu_len, int err); + struct nfc_target; struct nfc_ops { @@ -79,6 +81,9 @@ struct nfc_ops { int (*discover_se)(struct nfc_dev *dev); int (*enable_se)(struct nfc_dev *dev, u32 se_idx); int (*disable_se)(struct nfc_dev *dev, u32 se_idx); + int (*se_io) (struct nfc_dev *dev, u32 se_idx, + u8 *apdu, size_t apdu_length, + se_io_cb_t cb, void *cb_context); }; #define NFC_TARGET_IDX_ANY -1 diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 29bed72a4ac4..6ad6cc03ccd3 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -85,6 +85,7 @@ * a specific SE notifies us about the end of a transaction. The parameter * for this event is the application ID (AID). * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller. + * @NFC_CMD_SE_IO: Send/Receive APDUs to/from the selected secure element. */ enum nfc_commands { NFC_CMD_UNSPEC, @@ -114,6 +115,7 @@ enum nfc_commands { NFC_EVENT_SE_CONNECTIVITY, NFC_EVENT_SE_TRANSACTION, NFC_CMD_GET_SE, + NFC_CMD_SE_IO, /* private: internal use only */ __NFC_CMD_AFTER_LAST }; @@ -147,6 +149,7 @@ enum nfc_commands { * @NFC_ATTR_SE_INDEX: Secure element index * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) * @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status + * @NFC_ATTR_APDU: Secure element APDU */ enum nfc_attrs { NFC_ATTR_UNSPEC, @@ -174,6 +177,7 @@ enum nfc_attrs { NFC_ATTR_SE_TYPE, NFC_ATTR_SE_AID, NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, + NFC_ATTR_SE_APDU, /* private: internal use only */ __NFC_ATTR_AFTER_LAST }; -- cgit From 04fa2f7f837601903e5fe0f93bc2af8559d8c035 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 24 Sep 2013 15:21:19 -0600 Subject: iommu: Add iommu_error class event to iommu trace iommu_error class event can be enabled to trigger when an iommu error occurs. This trace event is intended to be called to report the error information. Trace information includes driver name, device name, iova, and flags. iommu_error:io_page_fault Signed-off-by: Shuah Khan Signed-off-by: Joerg Roedel --- drivers/iommu/iommu-traces.c | 3 +++ include/trace/events/iommu.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) (limited to 'include') diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c index a2af60f31810..bf3b317ff0c1 100644 --- a/drivers/iommu/iommu-traces.c +++ b/drivers/iommu/iommu-traces.c @@ -22,3 +22,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain); /* iommu_map_unmap */ EXPORT_TRACEPOINT_SYMBOL_GPL(map); EXPORT_TRACEPOINT_SYMBOL_GPL(unmap); + +/* iommu_error */ +EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault); diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h index 86bcc5a9fedc..a8f5c32d174b 100644 --- a/include/trace/events/iommu.h +++ b/include/trace/events/iommu.h @@ -123,6 +123,39 @@ DEFINE_EVENT_PRINT(iommu_map_unmap, unmap, __entry->iova, __entry->size ) ); + +DECLARE_EVENT_CLASS(iommu_error, + + TP_PROTO(struct device *dev, unsigned long iova, int flags), + + TP_ARGS(dev, iova, flags), + + TP_STRUCT__entry( + __string(device, dev_name(dev)) + __string(driver, dev_driver_string(dev)) + __field(u64, iova) + __field(int, flags) + ), + + TP_fast_assign( + __assign_str(device, dev_name(dev)); + __assign_str(driver, dev_driver_string(dev)); + __entry->iova = iova; + __entry->flags = flags; + ), + + TP_printk("IOMMU:%s %s iova=0x%016llx flags=0x%04x", + __get_str(driver), __get_str(device), + __entry->iova, __entry->flags + ) +); + +DEFINE_EVENT(iommu_error, io_page_fault, + + TP_PROTO(struct device *dev, unsigned long iova, int flags), + + TP_ARGS(dev, iova, flags) +); #endif /* _TRACE_IOMMU_H */ /* This part must be outside protection */ -- cgit From 56fa484969c367e3ae43a012a7b99f75bb4f3bdb Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 24 Sep 2013 15:21:20 -0600 Subject: iommu: Change iommu driver to call io_page_fault trace event Change iommu driver call io_page_fault trace event. This iommu_error class event can be enabled to trigger when an iommu error occurs. Trace information includes driver name, device name, iova, and flags. Testing: Added trace calls to iommu_prepare_identity_map() for testing some of the conditions that are hard to trigger. Here is the trace from the testing: swapper/0-1 [003] .... 2.003774: io_page_fault: IOMMU:pci 0000:00:02.0 iova=0x00000000cb800000 flags=0x0002 swapper/0-1 [003] .... 2.004098: io_page_fault: IOMMU:pci 0000:00:1d.0 iova=0x00000000cadc6000 flags=0x0002 swapper/0-1 [003] .... 2.004115: io_page_fault: IOMMU:pci 0000:00:1a.0 iova=0x00000000cadc6000 flags=0x0002 swapper/0-1 [003] .... 2.004129: io_page_fault: IOMMU:pci 0000:00:1f.0 iova=0x0000000000000000 flags=0x0002 Signed-off-by: Shuah Khan Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7ea319e95b47..a444c790fa72 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -22,6 +22,7 @@ #include #include #include +#include #define IOMMU_READ (1) #define IOMMU_WRITE (2) @@ -227,6 +228,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain, ret = domain->handler(domain, dev, iova, flags, domain->handler_token); + trace_io_page_fault(dev, iova, flags); return ret; } -- cgit From ed37ddffe201bfad7be3c45bc08bd65b5298adca Mon Sep 17 00:00:00 2001 From: Roy Franz Date: Sun, 22 Sep 2013 15:45:26 -0700 Subject: efi: Add proper definitions for some EFI function pointers. The x86/AMD64 EFI stubs must use a call wrapper to convert between the Linux and EFI ABIs, so void pointers are sufficient. For ARM, the ABIs are compatible, so we can directly invoke the function pointers. The functions that are used by the ARM stub are updated to match the EFI definitions. Also add some EFI types used by EFI functions. Signed-off-by: Roy Franz Acked-by: Mark Salter Reviewed-by: Grant Likely Signed-off-by: Matt Fleming --- arch/x86/boot/compressed/eboot.h | 8 ------- include/linux/efi.h | 50 +++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index e5b0a8f91c5f..02265107cce3 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -10,8 +10,6 @@ #define SEG_GRANULARITY_4KB (1 << 0) #define DESC_TYPE_CODE_DATA (1 << 0) - -#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) #define EFI_READ_CHUNK_SIZE (1024 * 1024) #define EFI_CONSOLE_OUT_DEVICE_GUID \ @@ -62,10 +60,4 @@ struct efi_uga_draw_protocol { void *blt; }; -struct efi_simple_text_output_protocol { - void *reset; - void *output_string; - void *test_string; -}; - #endif /* BOOT_COMPRESSED_EBOOT_H */ diff --git a/include/linux/efi.h b/include/linux/efi.h index c084b6d942c3..bc5687d0f315 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -39,6 +39,8 @@ typedef unsigned long efi_status_t; typedef u8 efi_bool_t; typedef u16 efi_char16_t; /* UNICODE character */ +typedef u64 efi_physical_addr_t; +typedef void *efi_handle_t; typedef struct { @@ -96,6 +98,7 @@ typedef struct { #define EFI_MEMORY_DESCRIPTOR_VERSION 1 #define EFI_PAGE_SHIFT 12 +#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) typedef struct { u32 type; @@ -157,11 +160,13 @@ typedef struct { efi_table_hdr_t hdr; void *raise_tpl; void *restore_tpl; - void *allocate_pages; - void *free_pages; - void *get_memory_map; - void *allocate_pool; - void *free_pool; + efi_status_t (*allocate_pages)(int, int, unsigned long, + efi_physical_addr_t *); + efi_status_t (*free_pages)(efi_physical_addr_t, unsigned long); + efi_status_t (*get_memory_map)(unsigned long *, void *, unsigned long *, + unsigned long *, u32 *); + efi_status_t (*allocate_pool)(int, unsigned long, void **); + efi_status_t (*free_pool)(void *); void *create_event; void *set_timer; void *wait_for_event; @@ -171,7 +176,7 @@ typedef struct { void *install_protocol_interface; void *reinstall_protocol_interface; void *uninstall_protocol_interface; - void *handle_protocol; + efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **); void *__reserved; void *register_protocol_notify; void *locate_handle; @@ -181,7 +186,7 @@ typedef struct { void *start_image; void *exit; void *unload_image; - void *exit_boot_services; + efi_status_t (*exit_boot_services)(efi_handle_t, unsigned long); void *get_next_monotonic_count; void *stall; void *set_watchdog_timer; @@ -494,10 +499,6 @@ typedef struct { unsigned long unload; } efi_loaded_image_t; -typedef struct { - u64 revision; - void *open_volume; -} efi_file_io_interface_t; typedef struct { u64 size; @@ -510,20 +511,30 @@ typedef struct { efi_char16_t filename[1]; } efi_file_info_t; -typedef struct { +typedef struct _efi_file_handle { u64 revision; - void *open; - void *close; + efi_status_t (*open)(struct _efi_file_handle *, + struct _efi_file_handle **, + efi_char16_t *, u64, u64); + efi_status_t (*close)(struct _efi_file_handle *); void *delete; - void *read; + efi_status_t (*read)(struct _efi_file_handle *, unsigned long *, + void *); void *write; void *get_position; void *set_position; - void *get_info; + efi_status_t (*get_info)(struct _efi_file_handle *, efi_guid_t *, + unsigned long *, void *); void *set_info; void *flush; } efi_file_handle_t; +typedef struct _efi_file_io_interface { + u64 revision; + int (*open_volume)(struct _efi_file_io_interface *, + efi_file_handle_t **); +} efi_file_io_interface_t; + #define EFI_FILE_MODE_READ 0x0000000000000001 #define EFI_FILE_MODE_WRITE 0x0000000000000002 #define EFI_FILE_MODE_CREATE 0x8000000000000000 @@ -792,6 +803,13 @@ struct efivar_entry { struct kobject kobj; }; + +struct efi_simple_text_output_protocol { + void *reset; + efi_status_t (*output_string)(void *, void *); + void *test_string; +}; + extern struct list_head efivar_sysfs_list; static inline void -- cgit From 3150398626466c6cc626732f60bc901d58f40677 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 12 Sep 2013 15:10:31 +0200 Subject: sched: Remove {set,clear}_need_resched Preemption semantics are going to change which mandate a change. All DRM usage sites are already broken and will not be affected (much) by this change. DRM people are aware and will remove the last few stragglers. For now, leave an empty stub that generates a warning, once all users are gone we can remove this. Signed-off-by: Peter Zijlstra Cc: airlied@linux.ie Cc: daniel.vetter@ffwll.ch Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/n/tip-qfc1el2zvhxiyut4ai99ij4n@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/thread_info.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index e7e04736802f..a629e4b23217 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -104,8 +104,19 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag) #define test_thread_flag(flag) \ test_ti_thread_flag(current_thread_info(), flag) -#define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) -#define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) +static inline __deprecated void set_need_resched(void) +{ + /* + * Use of this function in deprecated. + * + * As of this writing there are only a few users in the DRM tree left + * all of which are wrong and can be removed without causing too much + * grief. + * + * The DRM people are aware and are working on removing the last few + * instances. + */ +} #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK /* -- cgit From ea8117478918a4734586d35ff530721b682425be Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Sep 2013 12:43:13 +0200 Subject: sched, idle: Fix the idle polling state logic Mike reported that commit 7d1a9417 ("x86: Use generic idle loop") regressed several workloads and caused excessive reschedule interrupts. The patch in question failed to notice that the x86 code had an inverted sense of the polling state versus the new generic code (x86: default polling, generic: default !polling). Fix the two prominent x86 mwait based idle drivers and introduce a few new generic polling helpers (fixing the wrong smp_mb__after_clear_bit usage). Also switch the idle routines to using tif_need_resched() which is an immediate TIF_NEED_RESCHED test as opposed to need_resched which will end up being slightly different. Reported-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: lenb@kernel.org Cc: tglx@linutronix.de Link: http://lkml.kernel.org/n/tip-nc03imb0etuefmzybzj7sprf@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/process.c | 6 ++-- drivers/acpi/processor_idle.c | 46 ++++++------------------- drivers/idle/intel_idle.c | 2 +- include/linux/sched.h | 78 +++++++++++++++++++++++++++++++++++++++---- include/linux/thread_info.h | 2 ++ kernel/cpu/idle.c | 9 +++-- 6 files changed, 91 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index c83516be1052..3fb8d95ab8b5 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -391,9 +391,9 @@ static void amd_e400_idle(void) * The switch back from broadcast mode needs to be * called with interrupts disabled. */ - local_irq_disable(); - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); - local_irq_enable(); + local_irq_disable(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); + local_irq_enable(); } else default_idle(); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f98dd00b51a9..c7414a545a4f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -119,17 +119,10 @@ static struct dmi_system_id processor_power_dmi_table[] = { */ static void acpi_safe_halt(void) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) { + if (!tif_need_resched()) { safe_halt(); local_irq_disable(); } - current_thread_info()->status |= TS_POLLING; } #ifdef ARCH_APICTIMER_STOPS_ON_C3 @@ -737,6 +730,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) + return -EINVAL; + } + lapic_timer_state_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); @@ -790,18 +788,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } /* @@ -819,9 +808,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } @@ -858,18 +844,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, } } - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } acpi_unlazy_tlb(smp_processor_id()); @@ -915,9 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index fa6964d8681a..f116d664b473 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -359,7 +359,7 @@ static int intel_idle(struct cpuidle_device *dev, if (!(lapic_timer_reliable_states & (1 << (cstate)))) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); - if (!need_resched()) { + if (!current_set_polling_and_test()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); diff --git a/include/linux/sched.h b/include/linux/sched.h index b5344de1658b..e783ec52295a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2479,34 +2479,98 @@ static inline int tsk_is_polling(struct task_struct *p) { return task_thread_info(p)->status & TS_POLLING; } -static inline void current_set_polling(void) +static inline void __current_set_polling(void) { current_thread_info()->status |= TS_POLLING; } -static inline void current_clr_polling(void) +static inline bool __must_check current_set_polling_and_test(void) +{ + __current_set_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb(); + + return unlikely(tif_need_resched()); +} + +static inline void __current_clr_polling(void) { current_thread_info()->status &= ~TS_POLLING; - smp_mb__after_clear_bit(); +} + +static inline bool __must_check current_clr_polling_and_test(void) +{ + __current_clr_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb(); + + return unlikely(tif_need_resched()); } #elif defined(TIF_POLLING_NRFLAG) static inline int tsk_is_polling(struct task_struct *p) { return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG); } -static inline void current_set_polling(void) + +static inline void __current_set_polling(void) { set_thread_flag(TIF_POLLING_NRFLAG); } -static inline void current_clr_polling(void) +static inline bool __must_check current_set_polling_and_test(void) +{ + __current_set_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + * + * XXX: assumes set/clear bit are identical barrier wise. + */ + smp_mb__after_clear_bit(); + + return unlikely(tif_need_resched()); +} + +static inline void __current_clr_polling(void) { clear_thread_flag(TIF_POLLING_NRFLAG); } + +static inline bool __must_check current_clr_polling_and_test(void) +{ + __current_clr_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb__after_clear_bit(); + + return unlikely(tif_need_resched()); +} + #else static inline int tsk_is_polling(struct task_struct *p) { return 0; } -static inline void current_set_polling(void) { } -static inline void current_clr_polling(void) { } +static inline void __current_set_polling(void) { } +static inline void __current_clr_polling(void) { } + +static inline bool __must_check current_set_polling_and_test(void) +{ + return unlikely(tif_need_resched()); +} +static inline bool __must_check current_clr_polling_and_test(void) +{ + return unlikely(tif_need_resched()); +} #endif /* diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index a629e4b23217..fddbe2023a5d 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -118,6 +118,8 @@ static inline __deprecated void set_need_resched(void) */ } +#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED) + #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK /* * An arch can define its own version of set_restore_sigmask() to get the diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index e695c0a0bcb5..c261409500e4 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c @@ -44,7 +44,7 @@ static inline int cpu_idle_poll(void) rcu_idle_enter(); trace_cpu_idle_rcuidle(0, smp_processor_id()); local_irq_enable(); - while (!need_resched()) + while (!tif_need_resched()) cpu_relax(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); rcu_idle_exit(); @@ -92,8 +92,7 @@ static void cpu_idle_loop(void) if (cpu_idle_force_poll || tick_check_broadcast_expired()) { cpu_idle_poll(); } else { - current_clr_polling(); - if (!need_resched()) { + if (!current_clr_polling_and_test()) { stop_critical_timings(); rcu_idle_enter(); arch_cpu_idle(); @@ -103,7 +102,7 @@ static void cpu_idle_loop(void) } else { local_irq_enable(); } - current_set_polling(); + __current_set_polling(); } arch_cpu_idle_exit(); } @@ -129,7 +128,7 @@ void cpu_startup_entry(enum cpuhp_state state) */ boot_init_stack_canary(); #endif - current_set_polling(); + __current_set_polling(); arch_cpu_idle_prepare(); cpu_idle_loop(); } -- cgit From 4a2b4b222743bb07fedf985b884550f2ca067ea9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Aug 2013 14:55:24 +0200 Subject: sched: Introduce preempt_count accessor functions Replace the single preempt_count() 'function' that's an lvalue with two proper functions: preempt_count() - returns the preempt_count value as rvalue preempt_count_set() - Allows setting the preempt-count value Also provide preempt_count_ptr() as a convenience wrapper to implement all modifying operations. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-orxrbycjozopqfhb4dxdkdvb@git.kernel.org [ Fixed build failure. ] Signed-off-by: Ingo Molnar --- include/linux/preempt.h | 25 +++++++++++++++++++------ init/main.c | 2 +- kernel/sched/core.c | 4 ++-- kernel/softirq.c | 4 ++-- kernel/timer.c | 8 ++++---- lib/locking-selftest.c | 2 +- lib/smp_processor_id.c | 3 +-- 7 files changed, 30 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/linux/preempt.h b/include/linux/preempt.h index f5d4723cdb3d..eaac52a8fe6a 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -10,19 +10,32 @@ #include #include +static __always_inline int preempt_count(void) +{ + return current_thread_info()->preempt_count; +} + +static __always_inline int *preempt_count_ptr(void) +{ + return ¤t_thread_info()->preempt_count; +} + +static __always_inline void preempt_count_set(int pc) +{ + *preempt_count_ptr() = pc; +} + #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) extern void add_preempt_count(int val); extern void sub_preempt_count(int val); #else -# define add_preempt_count(val) do { preempt_count() += (val); } while (0) -# define sub_preempt_count(val) do { preempt_count() -= (val); } while (0) +# define add_preempt_count(val) do { *preempt_count_ptr() += (val); } while (0) +# define sub_preempt_count(val) do { *preempt_count_ptr() -= (val); } while (0) #endif #define inc_preempt_count() add_preempt_count(1) #define dec_preempt_count() sub_preempt_count(1) -#define preempt_count() (current_thread_info()->preempt_count) - #ifdef CONFIG_PREEMPT asmlinkage void preempt_schedule(void); @@ -81,9 +94,9 @@ do { \ /* For debugging and tracer internals only! */ #define add_preempt_count_notrace(val) \ - do { preempt_count() += (val); } while (0) + do { *preempt_count_ptr() += (val); } while (0) #define sub_preempt_count_notrace(val) \ - do { preempt_count() -= (val); } while (0) + do { *preempt_count_ptr() -= (val); } while (0) #define inc_preempt_count_notrace() add_preempt_count_notrace(1) #define dec_preempt_count_notrace() sub_preempt_count_notrace(1) diff --git a/init/main.c b/init/main.c index af310afbef28..7cc4b7889a88 100644 --- a/init/main.c +++ b/init/main.c @@ -692,7 +692,7 @@ int __init_or_module do_one_initcall(initcall_t fn) if (preempt_count() != count) { sprintf(msgbuf, "preemption imbalance "); - preempt_count() = count; + preempt_count_set(count); } if (irqs_disabled()) { strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 242da0c03aba..fe89afac4d09 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2219,7 +2219,7 @@ void __kprobes add_preempt_count(int val) if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) return; #endif - preempt_count() += val; + add_preempt_count_notrace(val); #ifdef CONFIG_DEBUG_PREEMPT /* * Spinlock count overflowing soon? @@ -2250,7 +2250,7 @@ void __kprobes sub_preempt_count(int val) if (preempt_count() == val) trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); - preempt_count() -= val; + sub_preempt_count_notrace(val); } EXPORT_SYMBOL(sub_preempt_count); diff --git a/kernel/softirq.c b/kernel/softirq.c index 53cc09ceb0b8..a90de70cf1f3 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -106,7 +106,7 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) * We must manually increment preempt_count here and manually * call the trace_preempt_off later. */ - preempt_count() += cnt; + add_preempt_count_notrace(cnt); /* * Were softirqs turned off above: */ @@ -256,7 +256,7 @@ restart: " exited with %08x?\n", vec_nr, softirq_to_name[vec_nr], h->action, prev_count, preempt_count()); - preempt_count() = prev_count; + preempt_count_set(prev_count); } rcu_bh_qs(cpu); diff --git a/kernel/timer.c b/kernel/timer.c index 4296d13db3d1..6582b82fa966 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1092,7 +1092,7 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index) static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long), unsigned long data) { - int preempt_count = preempt_count(); + int count = preempt_count(); #ifdef CONFIG_LOCKDEP /* @@ -1119,16 +1119,16 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long), lock_map_release(&lockdep_map); - if (preempt_count != preempt_count()) { + if (count != preempt_count()) { WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n", - fn, preempt_count, preempt_count()); + fn, count, preempt_count()); /* * Restore the preempt count. That gives us a decent * chance to survive and extract information. If the * callback kept a lock held, bad luck, but not worse * than the BUG() we had. */ - preempt_count() = preempt_count; + preempt_count_set(count); } } diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index 6dc09d8f4c24..872a15a2a637 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -1002,7 +1002,7 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) * Some tests (e.g. double-unlock) might corrupt the preemption * count, so restore it: */ - preempt_count() = saved_preempt_count; + preempt_count_set(saved_preempt_count); #ifdef CONFIG_TRACE_IRQFLAGS if (softirq_count()) current->softirqs_enabled = 0; diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 4c0d0e51d49e..04abe53f12a1 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -9,10 +9,9 @@ notrace unsigned int debug_smp_processor_id(void) { - unsigned long preempt_count = preempt_count(); int this_cpu = raw_smp_processor_id(); - if (likely(preempt_count)) + if (likely(preempt_count())) goto out; if (irqs_disabled()) -- cgit From f27dde8deef33c9e58027df11ceab2198601d6a6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Aug 2013 14:55:31 +0200 Subject: sched: Add NEED_RESCHED to the preempt_count In order to combine the preemption and need_resched test we need to fold the need_resched information into the preempt_count value. Since the NEED_RESCHED flag is set across CPUs this needs to be an atomic operation, however we very much want to avoid making preempt_count atomic, therefore we keep the existing TIF_NEED_RESCHED infrastructure in place but at 3 sites test it and fold its value into preempt_count; namely: - resched_task() when setting TIF_NEED_RESCHED on the current task - scheduler_ipi() when resched_task() sets TIF_NEED_RESCHED on a remote task it follows it up with a reschedule IPI and we can modify the cpu local preempt_count from there. - cpu_idle_loop() for when resched_task() found tsk_is_polling(). We use an inverted bitmask to indicate need_resched so that a 0 means both need_resched and !atomic. Also remove the barrier() in preempt_enable() between preempt_enable_no_resched() and preempt_check_resched() to avoid having to reload the preemption value and allow the compiler to use the flags of the previuos decrement. I couldn't come up with any sane reason for this barrier() to be there as preempt_enable_no_resched() already has a barrier() before doing the decrement. Suggested-by: Ingo Molnar Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-7a7m5qqbn5pmwnd4wko9u6da@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/preempt.h | 47 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/sched.h | 7 +++++-- kernel/cpu/idle.c | 7 +++++++ kernel/sched/core.c | 20 +++++++++++++++----- 4 files changed, 69 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/linux/preempt.h b/include/linux/preempt.h index eaac52a8fe6a..92e341853e4b 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -10,9 +10,19 @@ #include #include +/* + * We use the MSB mostly because its available; see for + * the other bits -- can't include that header due to inclusion hell. + */ +#define PREEMPT_NEED_RESCHED 0x80000000 + +/* + * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users + * that think a non-zero value indicates we cannot preempt. + */ static __always_inline int preempt_count(void) { - return current_thread_info()->preempt_count; + return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED; } static __always_inline int *preempt_count_ptr(void) @@ -20,11 +30,40 @@ static __always_inline int *preempt_count_ptr(void) return ¤t_thread_info()->preempt_count; } +/* + * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the + * alternative is loosing a reschedule. Better schedule too often -- also this + * should be a very rare operation. + */ static __always_inline void preempt_count_set(int pc) { *preempt_count_ptr() = pc; } +/* + * We fold the NEED_RESCHED bit into the preempt count such that + * preempt_enable() can decrement and test for needing to reschedule with a + * single instruction. + * + * We invert the actual bit, so that when the decrement hits 0 we know we both + * need to resched (the bit is cleared) and can resched (no preempt count). + */ + +static __always_inline void set_preempt_need_resched(void) +{ + *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED; +} + +static __always_inline void clear_preempt_need_resched(void) +{ + *preempt_count_ptr() |= PREEMPT_NEED_RESCHED; +} + +static __always_inline bool test_preempt_need_resched(void) +{ + return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED); +} + #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) extern void add_preempt_count(int val); extern void sub_preempt_count(int val); @@ -42,7 +81,7 @@ asmlinkage void preempt_schedule(void); #define preempt_check_resched() \ do { \ - if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ + if (unlikely(!*preempt_count_ptr())) \ preempt_schedule(); \ } while (0) @@ -52,7 +91,7 @@ void preempt_schedule_context(void); #define preempt_check_resched_context() \ do { \ - if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ + if (unlikely(!*preempt_count_ptr())) \ preempt_schedule_context(); \ } while (0) #else @@ -88,7 +127,6 @@ do { \ #define preempt_enable() \ do { \ preempt_enable_no_resched(); \ - barrier(); \ preempt_check_resched(); \ } while (0) @@ -116,7 +154,6 @@ do { \ #define preempt_enable_notrace() \ do { \ preempt_enable_no_resched_notrace(); \ - barrier(); \ preempt_check_resched_context(); \ } while (0) diff --git a/include/linux/sched.h b/include/linux/sched.h index e783ec52295a..9fa151fb968e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -22,6 +22,7 @@ struct sched_param { #include #include #include +#include #include #include @@ -434,7 +435,9 @@ struct task_cputime { * We include PREEMPT_ACTIVE to avoid cond_resched() from working * before the scheduler is active -- see should_resched(). */ -#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE) +#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE + PREEMPT_NEED_RESCHED) +#define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED) +#define PREEMPT_DISABLED (1 + PREEMPT_NEED_RESCHED) /** * struct thread_group_cputimer - thread group interval timer counts @@ -2408,7 +2411,7 @@ static inline int signal_pending_state(long state, struct task_struct *p) static inline int need_resched(void) { - return unlikely(test_thread_flag(TIF_NEED_RESCHED)); + return unlikely(test_preempt_need_resched()); } /* diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index c261409500e4..988573a9a387 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c @@ -105,6 +105,13 @@ static void cpu_idle_loop(void) __current_set_polling(); } arch_cpu_idle_exit(); + /* + * We need to test and propagate the TIF_NEED_RESCHED + * bit here because we might not have send the + * reschedule IPI to idle tasks. + */ + if (tif_need_resched()) + set_preempt_need_resched(); } tick_nohz_idle_exit(); schedule_preempt_disabled(); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index fe89afac4d09..ee61f5affd20 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -525,8 +525,10 @@ void resched_task(struct task_struct *p) set_tsk_need_resched(p); cpu = task_cpu(p); - if (cpu == smp_processor_id()) + if (cpu == smp_processor_id()) { + set_preempt_need_resched(); return; + } /* NEED_RESCHED must be visible before we test polling */ smp_mb(); @@ -1391,6 +1393,14 @@ static void sched_ttwu_pending(void) void scheduler_ipi(void) { + /* + * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting + * TIF_NEED_RESCHED remotely (for the first time) will also send + * this IPI. + */ + if (tif_need_resched()) + set_preempt_need_resched(); + if (llist_empty(&this_rq()->wake_list) && !tick_nohz_full_cpu(smp_processor_id()) && !got_nohz_idle_kick()) @@ -1714,7 +1724,7 @@ void sched_fork(struct task_struct *p) #endif #ifdef CONFIG_PREEMPT_COUNT /* Want to start with kernel preemption disabled. */ - task_thread_info(p)->preempt_count = 1; + task_thread_info(p)->preempt_count = PREEMPT_DISABLED; #endif #ifdef CONFIG_SMP plist_node_init(&p->pushable_tasks, MAX_PRIO); @@ -2425,6 +2435,7 @@ need_resched: put_prev_task(rq, prev); next = pick_next_task(rq); clear_tsk_need_resched(prev); + clear_preempt_need_resched(); rq->skip_clock_update = 0; if (likely(prev != next)) { @@ -2536,11 +2547,10 @@ EXPORT_SYMBOL(preempt_schedule); */ asmlinkage void __sched preempt_schedule_irq(void) { - struct thread_info *ti = current_thread_info(); enum ctx_state prev_state; /* Catch callers which need to be fixed */ - BUG_ON(ti->preempt_count || !irqs_disabled()); + BUG_ON(preempt_count() || !irqs_disabled()); prev_state = exception_enter(); @@ -4207,7 +4217,7 @@ void init_idle(struct task_struct *idle, int cpu) raw_spin_unlock_irqrestore(&rq->lock, flags); /* Set the preempt count _outside_ the spinlocks! */ - task_thread_info(idle)->preempt_count = 0; + task_thread_info(idle)->preempt_count = PREEMPT_ENABLED; /* * The idle tasks have their own, simple scheduling class: -- cgit From a787870924dbd6f321661e06d4ec1c7a408c9ccf Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Aug 2013 14:55:40 +0200 Subject: sched, arch: Create asm/preempt.h In order to prepare to per-arch implementations of preempt_count move the required bits into an asm-generic header and use this for all archs. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-h5j0c1r3e3fk015m30h8f1zx@git.kernel.org Signed-off-by: Ingo Molnar --- arch/alpha/include/asm/Kbuild | 1 + arch/arc/include/asm/Kbuild | 1 + arch/arm/include/asm/Kbuild | 1 + arch/arm64/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/h8300/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/m68k/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/openrisc/include/asm/Kbuild | 1 + arch/parisc/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/sh/include/asm/Kbuild | 1 + arch/sparc/include/asm/Kbuild | 1 + arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/x86/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/preempt.h | 54 ++++++++++++++++++++++++++++++++++++++ include/linux/preempt.h | 49 +--------------------------------- 32 files changed, 85 insertions(+), 48 deletions(-) create mode 100644 include/asm-generic/preempt.h (limited to 'include') diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild index a6e85f448c1c..f01fb505ad52 100644 --- a/arch/alpha/include/asm/Kbuild +++ b/arch/alpha/include/asm/Kbuild @@ -3,3 +3,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index d8dd660898b9..5943f7f9d325 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -46,3 +46,4 @@ generic-y += ucontext.h generic-y += user.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index d3db39860b9c..4e6838d4ddf6 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -33,3 +33,4 @@ generic-y += timex.h generic-y += trace_clock.h generic-y += types.h generic-y += unaligned.h +generic-y += preempt.h diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 79a642d199f2..519f89f5b6a3 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -50,3 +50,4 @@ generic-y += unaligned.h generic-y += user.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index d22af851f3f6..b946080ee8bb 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -3,3 +3,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += trace_clock.h generic-y += param.h +generic-y += preempt.h diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 127826f8a375..f2b43474b0e2 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -44,3 +44,4 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index e49f918531ad..fc0b3c356027 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -56,3 +56,4 @@ generic-y += ucontext.h generic-y += user.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index c8325455520e..b06caf649a95 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -11,3 +11,4 @@ generic-y += module.h generic-y += trace_clock.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index c5d767028306..74742dc6a3da 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -2,3 +2,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 8ada3cf0c98d..7e0e7213a481 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild @@ -6,3 +6,4 @@ generic-y += mmu.h generic-y += module.h generic-y += trace_clock.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 1da17caac23c..67c3450309b7 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -53,3 +53,4 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index a3456f34f672..f93ee087e8fe 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -3,4 +3,5 @@ generic-y += clkdev.h generic-y += exec.h generic-y += kvm_para.h generic-y += trace_clock.h +generic-y += preempt.h generic-y += vtime.h \ No newline at end of file diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index bebdc36ebb0a..2b58c5f0bc38 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -3,3 +3,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += module.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 09d77a862da3..a5d27f272a59 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -31,3 +31,4 @@ generic-y += trace_clock.h generic-y += types.h generic-y += word-at-a-time.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index 6ae0ccb632cb..84d0c1d6b9b3 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -52,3 +52,4 @@ generic-y += unaligned.h generic-y += user.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index d3c51a6a601d..ce0bbf8f5640 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -3,3 +3,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += trace_clock.h generic-y += syscalls.h +generic-y += preempt.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 454ddf9bb76f..1acbb8b77a71 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -11,5 +11,6 @@ generic-y += sections.h generic-y += segment.h generic-y += serial.h generic-y += trace_clock.h +generic-y += preempt.h generic-y += ucontext.h generic-y += xor.h diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index c5d767028306..74742dc6a3da 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -2,3 +2,4 @@ generic-y += clkdev.h generic-y += exec.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index 195653e851da..78405625e799 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -67,3 +67,4 @@ generic-y += ucontext.h generic-y += user.h generic-y += word-at-a-time.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index ff4c9faed546..a603b9ebe54c 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild @@ -4,3 +4,4 @@ generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \ div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \ poll.h xor.h clkdev.h exec.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 704e6f10ae80..d8f9d2f18a23 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -2,4 +2,5 @@ generic-y += clkdev.h generic-y += rwsem.h generic-y += trace_clock.h +generic-y += preempt.h generic-y += vtime.h \ No newline at end of file diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index f313f9cbcf44..7a5288f3479a 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -2,3 +2,4 @@ generic-y += clkdev.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index e1c7bb999b06..f3414ade77a3 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -4,3 +4,4 @@ header-y += generic-y += clkdev.h generic-y += trace_clock.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 280bea9e5e2b..231efbb68108 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -34,3 +34,4 @@ generic-y += termios.h generic-y += trace_clock.h generic-y += ucontext.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 7e4a97fbded4..bf390667657a 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -16,3 +16,4 @@ generic-y += serial.h generic-y += trace_clock.h generic-y += types.h generic-y += word-at-a-time.h +generic-y += preempt.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index 664d6ad23f80..22f3bd147fa7 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -38,3 +38,4 @@ generic-y += termios.h generic-y += trace_clock.h generic-y += types.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index b30f34a79882..fdde187e6087 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -3,3 +3,4 @@ generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h generic-y += switch_to.h clkdev.h generic-y += trace_clock.h +generic-y += preempt.h diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 89d8b6c4e39a..00045cbe5c63 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -60,3 +60,4 @@ generic-y += unaligned.h generic-y += user.h generic-y += vga.h generic-y += xor.h +generic-y += preempt.h diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild index 7f669853317a..eca20286a91c 100644 --- a/arch/x86/include/asm/Kbuild +++ b/arch/x86/include/asm/Kbuild @@ -5,3 +5,4 @@ genhdr-y += unistd_64.h genhdr-y += unistd_x32.h generic-y += clkdev.h +generic-y += preempt.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 1b982641ec35..228d6aee3a16 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -28,3 +28,4 @@ generic-y += termios.h generic-y += topology.h generic-y += trace_clock.h generic-y += xor.h +generic-y += preempt.h diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h new file mode 100644 index 000000000000..a1fc6590a743 --- /dev/null +++ b/include/asm-generic/preempt.h @@ -0,0 +1,54 @@ +#ifndef __ASM_PREEMPT_H +#define __ASM_PREEMPT_H + +#include + +/* + * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users + * that think a non-zero value indicates we cannot preempt. + */ +static __always_inline int preempt_count(void) +{ + return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED; +} + +static __always_inline int *preempt_count_ptr(void) +{ + return ¤t_thread_info()->preempt_count; +} + +/* + * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the + * alternative is loosing a reschedule. Better schedule too often -- also this + * should be a very rare operation. + */ +static __always_inline void preempt_count_set(int pc) +{ + *preempt_count_ptr() = pc; +} + +/* + * We fold the NEED_RESCHED bit into the preempt count such that + * preempt_enable() can decrement and test for needing to reschedule with a + * single instruction. + * + * We invert the actual bit, so that when the decrement hits 0 we know we both + * need to resched (the bit is cleared) and can resched (no preempt count). + */ + +static __always_inline void set_preempt_need_resched(void) +{ + *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED; +} + +static __always_inline void clear_preempt_need_resched(void) +{ + *preempt_count_ptr() |= PREEMPT_NEED_RESCHED; +} + +static __always_inline bool test_preempt_need_resched(void) +{ + return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED); +} + +#endif /* __ASM_PREEMPT_H */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 92e341853e4b..df8e245e8729 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -6,7 +6,6 @@ * preempt_count (used for kernel preemption, interrupt count, etc.) */ -#include #include #include @@ -16,53 +15,7 @@ */ #define PREEMPT_NEED_RESCHED 0x80000000 -/* - * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users - * that think a non-zero value indicates we cannot preempt. - */ -static __always_inline int preempt_count(void) -{ - return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED; -} - -static __always_inline int *preempt_count_ptr(void) -{ - return ¤t_thread_info()->preempt_count; -} - -/* - * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the - * alternative is loosing a reschedule. Better schedule too often -- also this - * should be a very rare operation. - */ -static __always_inline void preempt_count_set(int pc) -{ - *preempt_count_ptr() = pc; -} - -/* - * We fold the NEED_RESCHED bit into the preempt count such that - * preempt_enable() can decrement and test for needing to reschedule with a - * single instruction. - * - * We invert the actual bit, so that when the decrement hits 0 we know we both - * need to resched (the bit is cleared) and can resched (no preempt count). - */ - -static __always_inline void set_preempt_need_resched(void) -{ - *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED; -} - -static __always_inline void clear_preempt_need_resched(void) -{ - *preempt_count_ptr() |= PREEMPT_NEED_RESCHED; -} - -static __always_inline bool test_preempt_need_resched(void) -{ - return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED); -} +#include #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) extern void add_preempt_count(int val); -- cgit From 01028747559ac6c6f642a7bbd2875cc4f66b2feb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Aug 2013 14:55:46 +0200 Subject: sched: Create more preempt_count accessors We need a few special preempt_count accessors: - task_preempt_count() for when we're interested in the preemption count of another (non-running) task. - init_task_preempt_count() for properly initializing the preemption count. - init_idle_preempt_count() a special case of the above for the idle threads. With these no generic code ever touches thread_info::preempt_count anymore and architectures could choose to remove it. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-jf5swrio8l78j37d06fzmo4r@git.kernel.org Signed-off-by: Ingo Molnar --- include/asm-generic/preempt.h | 14 ++++++++++++++ include/trace/events/sched.h | 2 +- kernel/sched/core.c | 7 +++---- 3 files changed, 18 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index a1fc6590a743..8100b1ec1715 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -27,6 +27,20 @@ static __always_inline void preempt_count_set(int pc) *preempt_count_ptr() = pc; } +/* + * must be macros to avoid header recursion hell + */ +#define task_preempt_count(p) \ + (task_thread_info(p)->preempt_count & ~PREEMPT_NEED_RESCHED) + +#define init_task_preempt_count(p) do { \ + task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \ +} while (0) + +#define init_idle_preempt_count(p, cpu) do { \ + task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \ +} while (0) + /* * We fold the NEED_RESCHED bit into the preempt count such that * preempt_enable() can decrement and test for needing to reschedule with a diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index 2e7d9947a10d..613381bcde40 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -100,7 +100,7 @@ static inline long __trace_sched_switch_state(struct task_struct *p) /* * For all intents and purposes a preempted task is a running task. */ - if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE) + if (task_preempt_count(p) & PREEMPT_ACTIVE) state = TASK_RUNNING | TASK_STATE_MAX; #endif diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ee61f5affd20..0ba4e4192390 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -983,7 +983,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) * ttwu() will sort out the placement. */ WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING && - !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)); + !(task_preempt_count(p) & PREEMPT_ACTIVE)); #ifdef CONFIG_LOCKDEP /* @@ -1723,8 +1723,7 @@ void sched_fork(struct task_struct *p) p->on_cpu = 0; #endif #ifdef CONFIG_PREEMPT_COUNT - /* Want to start with kernel preemption disabled. */ - task_thread_info(p)->preempt_count = PREEMPT_DISABLED; + init_task_preempt_count(p); #endif #ifdef CONFIG_SMP plist_node_init(&p->pushable_tasks, MAX_PRIO); @@ -4217,7 +4216,7 @@ void init_idle(struct task_struct *idle, int cpu) raw_spin_unlock_irqrestore(&rq->lock, flags); /* Set the preempt count _outside_ the spinlocks! */ - task_thread_info(idle)->preempt_count = PREEMPT_ENABLED; + init_idle_preempt_count(idle, cpu); /* * The idle tasks have their own, simple scheduling class: -- cgit From bdb43806589096ac4272fe1307e789846ac08d7c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 10 Sep 2013 12:15:23 +0200 Subject: sched: Extract the basic add/sub preempt_count modifiers Rewrite the preempt_count macros in order to extract the 3 basic preempt_count value modifiers: __preempt_count_add() __preempt_count_sub() and the new: __preempt_count_dec_and_test() And since we're at it anyway, replace the unconventional $op_preempt_count names with the more conventional preempt_count_$op. Since these basic operators are equivalent to the previous _notrace() variants, do away with the _notrace() versions. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-ewbpdbupy9xpsjhg960zwbv8@git.kernel.org Signed-off-by: Ingo Molnar --- arch/mips/mm/init.c | 5 +- arch/x86/kernel/traps.c | 4 +- include/asm-generic/preempt.h | 35 ++++++++++++++ include/linux/hardirq.h | 8 ++-- include/linux/preempt.h | 106 +++++++++++++++++++----------------------- include/linux/sched.h | 5 -- include/linux/uaccess.h | 8 +--- kernel/context_tracking.c | 2 +- kernel/sched/core.c | 29 +++++------- kernel/softirq.c | 14 +++--- 10 files changed, 113 insertions(+), 103 deletions(-) (limited to 'include') diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index e205ef598e97..12156176c7ca 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -124,7 +124,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) BUG_ON(Page_dcache_dirty(page)); - inc_preempt_count(); + pagefault_disable(); idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); #ifdef CONFIG_MIPS_MT_SMTC idx += FIX_N_COLOURS * smp_processor_id() + @@ -193,8 +193,7 @@ void kunmap_coherent(void) write_c0_entryhi(old_ctx); EXIT_CRITICAL(flags); #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } void copy_user_highpage(struct page *to, struct page *from, diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 8c8093b146ca..729aa779ff75 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -88,7 +88,7 @@ static inline void conditional_sti(struct pt_regs *regs) static inline void preempt_conditional_sti(struct pt_regs *regs) { - inc_preempt_count(); + preempt_count_inc(); if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } @@ -103,7 +103,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) { if (regs->flags & X86_EFLAGS_IF) local_irq_disable(); - dec_preempt_count(); + preempt_count_dec(); } static int __kprobes diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index 8100b1ec1715..82d958fc3823 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -65,4 +65,39 @@ static __always_inline bool test_preempt_need_resched(void) return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED); } +/* + * The various preempt_count add/sub methods + */ + +static __always_inline void __preempt_count_add(int val) +{ + *preempt_count_ptr() += val; +} + +static __always_inline void __preempt_count_sub(int val) +{ + *preempt_count_ptr() -= val; +} + +static __always_inline bool __preempt_count_dec_and_test(void) +{ + return !--*preempt_count_ptr(); +} + +/* + * Returns true when we need to resched -- even if we can not. + */ +static __always_inline bool need_resched(void) +{ + return unlikely(test_preempt_need_resched()); +} + +/* + * Returns true when we need to resched and can (barring IRQ state). + */ +static __always_inline bool should_resched(void) +{ + return unlikely(!*preempt_count_ptr()); +} + #endif /* __ASM_PREEMPT_H */ diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 1e041063b226..d9cf963ac832 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -33,7 +33,7 @@ extern void rcu_nmi_exit(void); #define __irq_enter() \ do { \ account_irq_enter_time(current); \ - add_preempt_count(HARDIRQ_OFFSET); \ + preempt_count_add(HARDIRQ_OFFSET); \ trace_hardirq_enter(); \ } while (0) @@ -49,7 +49,7 @@ extern void irq_enter(void); do { \ trace_hardirq_exit(); \ account_irq_exit_time(current); \ - sub_preempt_count(HARDIRQ_OFFSET); \ + preempt_count_sub(HARDIRQ_OFFSET); \ } while (0) /* @@ -62,7 +62,7 @@ extern void irq_exit(void); lockdep_off(); \ ftrace_nmi_enter(); \ BUG_ON(in_nmi()); \ - add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \ + preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \ rcu_nmi_enter(); \ trace_hardirq_enter(); \ } while (0) @@ -72,7 +72,7 @@ extern void irq_exit(void); trace_hardirq_exit(); \ rcu_nmi_exit(); \ BUG_ON(!in_nmi()); \ - sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \ + preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \ ftrace_nmi_exit(); \ lockdep_on(); \ } while (0) diff --git a/include/linux/preempt.h b/include/linux/preempt.h index df8e245e8729..2343d8715299 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -18,97 +18,86 @@ #include #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) - extern void add_preempt_count(int val); - extern void sub_preempt_count(int val); +extern void preempt_count_add(int val); +extern void preempt_count_sub(int val); +#define preempt_count_dec_and_test() ({ preempt_count_sub(1); should_resched(); }) #else -# define add_preempt_count(val) do { *preempt_count_ptr() += (val); } while (0) -# define sub_preempt_count(val) do { *preempt_count_ptr() -= (val); } while (0) +#define preempt_count_add(val) __preempt_count_add(val) +#define preempt_count_sub(val) __preempt_count_sub(val) +#define preempt_count_dec_and_test() __preempt_count_dec_and_test() #endif -#define inc_preempt_count() add_preempt_count(1) -#define dec_preempt_count() sub_preempt_count(1) - -#ifdef CONFIG_PREEMPT - -asmlinkage void preempt_schedule(void); - -#define preempt_check_resched() \ -do { \ - if (unlikely(!*preempt_count_ptr())) \ - preempt_schedule(); \ -} while (0) - -#ifdef CONFIG_CONTEXT_TRACKING - -void preempt_schedule_context(void); - -#define preempt_check_resched_context() \ -do { \ - if (unlikely(!*preempt_count_ptr())) \ - preempt_schedule_context(); \ -} while (0) -#else - -#define preempt_check_resched_context() preempt_check_resched() - -#endif /* CONFIG_CONTEXT_TRACKING */ - -#else /* !CONFIG_PREEMPT */ - -#define preempt_check_resched() do { } while (0) -#define preempt_check_resched_context() do { } while (0) - -#endif /* CONFIG_PREEMPT */ +#define __preempt_count_inc() __preempt_count_add(1) +#define __preempt_count_dec() __preempt_count_sub(1) +#define preempt_count_inc() preempt_count_add(1) +#define preempt_count_dec() preempt_count_sub(1) #ifdef CONFIG_PREEMPT_COUNT #define preempt_disable() \ do { \ - inc_preempt_count(); \ + preempt_count_inc(); \ barrier(); \ } while (0) #define sched_preempt_enable_no_resched() \ do { \ barrier(); \ - dec_preempt_count(); \ + preempt_count_dec(); \ } while (0) -#define preempt_enable_no_resched() sched_preempt_enable_no_resched() +#define preempt_enable_no_resched() sched_preempt_enable_no_resched() +#ifdef CONFIG_PREEMPT +asmlinkage void preempt_schedule(void); #define preempt_enable() \ do { \ - preempt_enable_no_resched(); \ - preempt_check_resched(); \ + barrier(); \ + if (unlikely(preempt_count_dec_and_test())) \ + preempt_schedule(); \ } while (0) -/* For debugging and tracer internals only! */ -#define add_preempt_count_notrace(val) \ - do { *preempt_count_ptr() += (val); } while (0) -#define sub_preempt_count_notrace(val) \ - do { *preempt_count_ptr() -= (val); } while (0) -#define inc_preempt_count_notrace() add_preempt_count_notrace(1) -#define dec_preempt_count_notrace() sub_preempt_count_notrace(1) +#define preempt_check_resched() \ +do { \ + if (should_resched()) \ + preempt_schedule(); \ +} while (0) + +#else +#define preempt_enable() preempt_enable_no_resched() +#define preempt_check_resched() do { } while (0) +#endif #define preempt_disable_notrace() \ do { \ - inc_preempt_count_notrace(); \ + __preempt_count_inc(); \ barrier(); \ } while (0) #define preempt_enable_no_resched_notrace() \ do { \ barrier(); \ - dec_preempt_count_notrace(); \ + __preempt_count_dec(); \ } while (0) -/* preempt_check_resched is OK to trace */ +#ifdef CONFIG_PREEMPT + +#ifdef CONFIG_CONTEXT_TRACKING +asmlinkage void preempt_schedule_context(void); +#else +#define preempt_schedule_context() preempt_schedule() +#endif + #define preempt_enable_notrace() \ do { \ - preempt_enable_no_resched_notrace(); \ - preempt_check_resched_context(); \ + barrier(); \ + if (unlikely(__preempt_count_dec_and_test())) \ + preempt_schedule_context(); \ } while (0) +#else +#define preempt_enable_notrace() preempt_enable_no_resched_notrace() +#endif #else /* !CONFIG_PREEMPT_COUNT */ @@ -118,10 +107,11 @@ do { \ * that can cause faults and scheduling migrate into our preempt-protected * region. */ -#define preempt_disable() barrier() +#define preempt_disable() barrier() #define sched_preempt_enable_no_resched() barrier() -#define preempt_enable_no_resched() barrier() -#define preempt_enable() barrier() +#define preempt_enable_no_resched() barrier() +#define preempt_enable() barrier() +#define preempt_check_resched() do { } while (0) #define preempt_disable_notrace() barrier() #define preempt_enable_no_resched_notrace() barrier() diff --git a/include/linux/sched.h b/include/linux/sched.h index 9fa151fb968e..06ac17c7e639 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2409,11 +2409,6 @@ static inline int signal_pending_state(long state, struct task_struct *p) return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p); } -static inline int need_resched(void) -{ - return unlikely(test_preempt_need_resched()); -} - /* * cond_resched() and cond_resched_lock(): latency reduction via * explicit rescheduling in places that are safe. The return diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 5ca0951e1855..9d8cf056e661 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -15,7 +15,7 @@ */ static inline void pagefault_disable(void) { - inc_preempt_count(); + preempt_count_inc(); /* * make sure to have issued the store before a pagefault * can hit. @@ -30,11 +30,7 @@ static inline void pagefault_enable(void) * the pagefault handler again. */ barrier(); - dec_preempt_count(); - /* - * make sure we do.. - */ - barrier(); + preempt_count_dec(); preempt_check_resched(); } diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c index 247091bf0587..013161f1c807 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c @@ -111,7 +111,7 @@ void context_tracking_user_enter(void) * instead of preempt_schedule() to exit user context if needed before * calling the scheduler. */ -void __sched notrace preempt_schedule_context(void) +asmlinkage void __sched notrace preempt_schedule_context(void) { enum ctx_state prev_ctx; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0ba4e4192390..9c84a9ab1892 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2219,7 +2219,7 @@ notrace unsigned long get_parent_ip(unsigned long addr) #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ defined(CONFIG_PREEMPT_TRACER)) -void __kprobes add_preempt_count(int val) +void __kprobes preempt_count_add(int val) { #ifdef CONFIG_DEBUG_PREEMPT /* @@ -2228,7 +2228,7 @@ void __kprobes add_preempt_count(int val) if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) return; #endif - add_preempt_count_notrace(val); + __preempt_count_add(val); #ifdef CONFIG_DEBUG_PREEMPT /* * Spinlock count overflowing soon? @@ -2239,9 +2239,9 @@ void __kprobes add_preempt_count(int val) if (preempt_count() == val) trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); } -EXPORT_SYMBOL(add_preempt_count); +EXPORT_SYMBOL(preempt_count_add); -void __kprobes sub_preempt_count(int val) +void __kprobes preempt_count_sub(int val) { #ifdef CONFIG_DEBUG_PREEMPT /* @@ -2259,9 +2259,9 @@ void __kprobes sub_preempt_count(int val) if (preempt_count() == val) trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); - sub_preempt_count_notrace(val); + __preempt_count_sub(val); } -EXPORT_SYMBOL(sub_preempt_count); +EXPORT_SYMBOL(preempt_count_sub); #endif @@ -2525,9 +2525,9 @@ asmlinkage void __sched notrace preempt_schedule(void) return; do { - add_preempt_count_notrace(PREEMPT_ACTIVE); + __preempt_count_add(PREEMPT_ACTIVE); __schedule(); - sub_preempt_count_notrace(PREEMPT_ACTIVE); + __preempt_count_sub(PREEMPT_ACTIVE); /* * Check again in case we missed a preemption opportunity @@ -2554,11 +2554,11 @@ asmlinkage void __sched preempt_schedule_irq(void) prev_state = exception_enter(); do { - add_preempt_count(PREEMPT_ACTIVE); + __preempt_count_add(PREEMPT_ACTIVE); local_irq_enable(); __schedule(); local_irq_disable(); - sub_preempt_count(PREEMPT_ACTIVE); + __preempt_count_sub(PREEMPT_ACTIVE); /* * Check again in case we missed a preemption opportunity @@ -3798,16 +3798,11 @@ SYSCALL_DEFINE0(sched_yield) return 0; } -static inline int should_resched(void) -{ - return need_resched() && !(preempt_count() & PREEMPT_ACTIVE); -} - static void __cond_resched(void) { - add_preempt_count(PREEMPT_ACTIVE); + __preempt_count_add(PREEMPT_ACTIVE); __schedule(); - sub_preempt_count(PREEMPT_ACTIVE); + __preempt_count_sub(PREEMPT_ACTIVE); } int __sched _cond_resched(void) diff --git a/kernel/softirq.c b/kernel/softirq.c index a90de70cf1f3..3e88612fc87e 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -100,13 +100,13 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) raw_local_irq_save(flags); /* - * The preempt tracer hooks into add_preempt_count and will break + * The preempt tracer hooks into preempt_count_add and will break * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET * is set and before current->softirq_enabled is cleared. * We must manually increment preempt_count here and manually * call the trace_preempt_off later. */ - add_preempt_count_notrace(cnt); + __preempt_count_add(cnt); /* * Were softirqs turned off above: */ @@ -120,7 +120,7 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) #else /* !CONFIG_TRACE_IRQFLAGS */ static inline void __local_bh_disable(unsigned long ip, unsigned int cnt) { - add_preempt_count(cnt); + preempt_count_add(cnt); barrier(); } #endif /* CONFIG_TRACE_IRQFLAGS */ @@ -139,7 +139,7 @@ static void __local_bh_enable(unsigned int cnt) if (softirq_count() == cnt) trace_softirqs_on(_RET_IP_); - sub_preempt_count(cnt); + preempt_count_sub(cnt); } /* @@ -169,12 +169,12 @@ static inline void _local_bh_enable_ip(unsigned long ip) * Keep preemption disabled until we are done with * softirq processing: */ - sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1); + preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1); if (unlikely(!in_interrupt() && local_softirq_pending())) do_softirq(); - dec_preempt_count(); + preempt_count_dec(); #ifdef CONFIG_TRACE_IRQFLAGS local_irq_enable(); #endif @@ -360,7 +360,7 @@ void irq_exit(void) account_irq_exit_time(current); trace_hardirq_exit(); - sub_preempt_count(HARDIRQ_OFFSET); + preempt_count_sub(HARDIRQ_OFFSET); if (!in_interrupt() && local_softirq_pending()) invoke_softirq(); -- cgit From a233f1120c37724938f7201fe2353b2577adaaf9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 23 Sep 2013 19:04:26 +0200 Subject: sched: Prepare for per-cpu preempt_count When using per-cpu preempt_count variables we need to save/restore the preempt_count on context switch (into per task storage; for instance the old thread_info::preempt_count variable) because of PREEMPT_ACTIVE. However, this means that on fork() the preempt_count value of the last context switch gets copied and if we had a PREEMPT_ACTIVE switch right before cloning a child task the child task will now too have PREEMPT_ACTIVE set and start its life with an extra PREEMPT_ACTIVE count. Therefore we need to make init_task_preempt_count() unconditional; this resets whatever preempt_count we inherited from our parent process. Doing so for !per-cpu implementations is harmless. For !PREEMPT_COUNT kernels we need to be careful not to start life with an increased preempt_count. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-4k0b7oy1rcdyzochwiixuwi9@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/sched.h | 12 +++++++++--- kernel/sched/core.c | 2 -- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index 06ac17c7e639..b09798b672f3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -428,6 +428,14 @@ struct task_cputime { .sum_exec_runtime = 0, \ } +#define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED) + +#ifdef CONFIG_PREEMPT_COUNT +#define PREEMPT_DISABLED (1 + PREEMPT_ENABLED) +#else +#define PREEMPT_DISABLED PREEMPT_ENABLED +#endif + /* * Disable preemption until the scheduler is running. * Reset by start_kernel()->sched_init()->init_idle(). @@ -435,9 +443,7 @@ struct task_cputime { * We include PREEMPT_ACTIVE to avoid cond_resched() from working * before the scheduler is active -- see should_resched(). */ -#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE + PREEMPT_NEED_RESCHED) -#define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED) -#define PREEMPT_DISABLED (1 + PREEMPT_NEED_RESCHED) +#define INIT_PREEMPT_COUNT (PREEMPT_DISABLED + PREEMPT_ACTIVE) /** * struct thread_group_cputimer - thread group interval timer counts diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9c84a9ab1892..f575d5bd7e7a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1722,9 +1722,7 @@ void sched_fork(struct task_struct *p) #if defined(CONFIG_SMP) p->on_cpu = 0; #endif -#ifdef CONFIG_PREEMPT_COUNT init_task_preempt_count(p); -#endif #ifdef CONFIG_SMP plist_node_init(&p->pushable_tasks, MAX_PRIO); #endif -- cgit From 1a338ac32ca630f67df25b4a16436cccc314e997 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Aug 2013 14:51:00 +0200 Subject: sched, x86: Optimize the preempt_schedule() call Remove the bloat of the C calling convention out of the preempt_enable() sites by creating an ASM wrapper which allows us to do an asm("call ___preempt_schedule") instead. calling.h bits by Andi Kleen Suggested-by: Linus Torvalds Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-tk7xdi1cvvxewixzke8t8le1@git.kernel.org [ Fixed build error. ] Signed-off-by: Ingo Molnar --- arch/x86/include/asm/calling.h | 50 ++++++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/preempt.h | 10 ++++++++ arch/x86/kernel/Makefile | 2 ++ arch/x86/kernel/i386_ksyms_32.c | 7 ++++++ arch/x86/kernel/preempt.S | 25 ++++++++++++++++++++ arch/x86/kernel/x8664_ksyms_64.c | 7 ++++++ include/asm-generic/preempt.h | 10 ++++++++ include/linux/preempt.h | 13 ++++------- 8 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 arch/x86/kernel/preempt.S (limited to 'include') diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index 0fa675033912..cb4c73bfeb48 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h @@ -48,6 +48,8 @@ For 32-bit we have the following conventions - kernel is built with #include +#ifdef CONFIG_X86_64 + /* * 64-bit system call stack frame layout defines and helpers, * for assembly code: @@ -192,3 +194,51 @@ For 32-bit we have the following conventions - kernel is built with .macro icebp .byte 0xf1 .endm + +#else /* CONFIG_X86_64 */ + +/* + * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These + * are different from the entry_32.S versions in not changing the segment + * registers. So only suitable for in kernel use, not when transitioning + * from or to user space. The resulting stack frame is not a standard + * pt_regs frame. The main use case is calling C code from assembler + * when all the registers need to be preserved. + */ + + .macro SAVE_ALL + pushl_cfi %eax + CFI_REL_OFFSET eax, 0 + pushl_cfi %ebp + CFI_REL_OFFSET ebp, 0 + pushl_cfi %edi + CFI_REL_OFFSET edi, 0 + pushl_cfi %esi + CFI_REL_OFFSET esi, 0 + pushl_cfi %edx + CFI_REL_OFFSET edx, 0 + pushl_cfi %ecx + CFI_REL_OFFSET ecx, 0 + pushl_cfi %ebx + CFI_REL_OFFSET ebx, 0 + .endm + + .macro RESTORE_ALL + popl_cfi %ebx + CFI_RESTORE ebx + popl_cfi %ecx + CFI_RESTORE ecx + popl_cfi %edx + CFI_RESTORE edx + popl_cfi %esi + CFI_RESTORE esi + popl_cfi %edi + CFI_RESTORE edi + popl_cfi %ebp + CFI_RESTORE ebp + popl_cfi %eax + CFI_RESTORE eax + .endm + +#endif /* CONFIG_X86_64 */ + diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h index 1309942b95e5..1de41690ff99 100644 --- a/arch/x86/include/asm/preempt.h +++ b/arch/x86/include/asm/preempt.h @@ -95,4 +95,14 @@ static __always_inline bool should_resched(void) return unlikely(!__this_cpu_read_4(__preempt_count)); } +#ifdef CONFIG_PREEMPT + extern asmlinkage void ___preempt_schedule(void); +# define __preempt_schedule() asm ("call ___preempt_schedule") + extern asmlinkage void preempt_schedule(void); +# ifdef CONFIG_CONTEXT_TRACKING + extern asmlinkage void ___preempt_schedule_context(void); +# define __preempt_schedule_context() asm ("call ___preempt_schedule_context") +# endif +#endif + #endif /* __ASM_PREEMPT_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a5408b965c9d..9b0a34e2cd79 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -36,6 +36,8 @@ obj-y += tsc.o io_delay.o rtc.o obj-y += pci-iommu_table.o obj-y += resource.o +obj-$(CONFIG_PREEMPT) += preempt.o + obj-y += process.o obj-y += i387.o xsave.o obj-y += ptrace.o diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 0fa69127209a..05fd74f537d6 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c @@ -37,3 +37,10 @@ EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(empty_zero_page); + +#ifdef CONFIG_PREEMPT +EXPORT_SYMBOL(___preempt_schedule); +#ifdef CONFIG_CONTEXT_TRACKING +EXPORT_SYMBOL(___preempt_schedule_context); +#endif +#endif diff --git a/arch/x86/kernel/preempt.S b/arch/x86/kernel/preempt.S new file mode 100644 index 000000000000..ca7f0d58a87d --- /dev/null +++ b/arch/x86/kernel/preempt.S @@ -0,0 +1,25 @@ + +#include +#include +#include +#include + +ENTRY(___preempt_schedule) + CFI_STARTPROC + SAVE_ALL + call preempt_schedule + RESTORE_ALL + ret + CFI_ENDPROC + +#ifdef CONFIG_CONTEXT_TRACKING + +ENTRY(___preempt_schedule_context) + CFI_STARTPROC + SAVE_ALL + call preempt_schedule_context + RESTORE_ALL + ret + CFI_ENDPROC + +#endif diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index b014d9414d08..040681928e9d 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -66,3 +66,10 @@ EXPORT_SYMBOL(empty_zero_page); #ifndef CONFIG_PARAVIRT EXPORT_SYMBOL(native_load_gs_index); #endif + +#ifdef CONFIG_PREEMPT +EXPORT_SYMBOL(___preempt_schedule); +#ifdef CONFIG_CONTEXT_TRACKING +EXPORT_SYMBOL(___preempt_schedule_context); +#endif +#endif diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index 82d958fc3823..5dc14ed3791c 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -100,4 +100,14 @@ static __always_inline bool should_resched(void) return unlikely(!*preempt_count_ptr()); } +#ifdef CONFIG_PREEMPT +extern asmlinkage void preempt_schedule(void); +#define __preempt_schedule() preempt_schedule() + +#ifdef CONFIG_CONTEXT_TRACKING +extern asmlinkage void preempt_schedule_context(void); +#define __preempt_schedule_context() preempt_schedule_context() +#endif +#endif /* CONFIG_PREEMPT */ + #endif /* __ASM_PREEMPT_H */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 2343d8715299..a3d9dc8c2c00 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -50,18 +50,17 @@ do { \ #define preempt_enable_no_resched() sched_preempt_enable_no_resched() #ifdef CONFIG_PREEMPT -asmlinkage void preempt_schedule(void); #define preempt_enable() \ do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ - preempt_schedule(); \ + __preempt_schedule(); \ } while (0) #define preempt_check_resched() \ do { \ if (should_resched()) \ - preempt_schedule(); \ + __preempt_schedule(); \ } while (0) #else @@ -83,17 +82,15 @@ do { \ #ifdef CONFIG_PREEMPT -#ifdef CONFIG_CONTEXT_TRACKING -asmlinkage void preempt_schedule_context(void); -#else -#define preempt_schedule_context() preempt_schedule() +#ifndef CONFIG_CONTEXT_TRACKING +#define __preempt_schedule_context() __preempt_schedule() #endif #define preempt_enable_notrace() \ do { \ barrier(); \ if (unlikely(__preempt_count_dec_and_test())) \ - preempt_schedule_context(); \ + __preempt_schedule_context(); \ } while (0) #else #define preempt_enable_notrace() preempt_enable_no_resched_notrace() -- cgit From 22d4aae5897fb8355130b8f7d9a3af153eac9714 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 23 Sep 2013 17:56:31 +0200 Subject: NFC: NCI: nci_spi_recv_frame() now returns (not forward) the read frame Previously, nci_spi_recv_frame() would directly transmit incoming frames to the NCI Core. However, it turns out that some NFC NCI Chips will add additional proprietary headers that must be handled/removed before NCI Core gets a chance to handle the frame. With this modification, the chip phy or driver are now responsible to transmit incoming frames to NCI Core after proper treatment, and NCI SPI becomes a driver helper instead of sitting between the NFC driver and NCI Core. As a general rule in NFC, *_recv_frame() APIs are used to deliver an incoming frame to an upper layer. To better suit the actual purpose of nci_spi_recv_frame(), and go along with its nci_spi_send() counterpart, the function is renamed to nci_spi_read() The skb is returned as the function result Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 2 +- net/nfc/nci/spi.c | 26 ++++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 37ba06f2dfa9..1d505317dc67 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -233,6 +233,6 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, u8 acknowledge_mode, unsigned int delay, struct nci_dev *ndev); int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb); -int nci_spi_recv_frame(struct nci_spi *nspi); +struct sk_buff *nci_spi_read(struct nci_spi *nspi); #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index c111506b36d1..734c6dde7751 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #define NCI_SPI_ACK_SHIFT 6 @@ -164,7 +163,7 @@ static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) return ret; } -static struct sk_buff *__nci_spi_recv_frame(struct nci_spi *nspi) +static struct sk_buff *__nci_spi_read(struct nci_spi *nspi) { struct sk_buff *skb; struct spi_message m; @@ -258,7 +257,7 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) } /** - * nci_spi_recv_frame - receive frame from NCI SPI drivers + * nci_spi_read - read frame from NCI SPI drivers * * @nspi: The nci spi * Context: can sleep @@ -266,21 +265,18 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) * This call may only be used from a context that may sleep. The sleep * is non-interruptible, and has no timeout. * - * It returns zero on success, else a negative error code. + * It returns an allocated skb containing the frame on success, or NULL. */ -int nci_spi_recv_frame(struct nci_spi *nspi) +struct sk_buff *nci_spi_read(struct nci_spi *nspi) { struct sk_buff *skb; - int ret = 0; nspi->ops->deassert_int(nspi); /* Retrieve frame from SPI */ - skb = __nci_spi_recv_frame(nspi); - if (!skb) { - ret = -EIO; + skb = __nci_spi_read(nspi); + if (!skb) goto done; - } if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { if (!nci_spi_check_crc(skb)) { @@ -299,20 +295,18 @@ int nci_spi_recv_frame(struct nci_spi *nspi) /* If there is no payload (ACK/NACK only frame), * free the socket buffer */ - if (skb->len == 0) { + if (!skb->len) { kfree_skb(skb); + skb = NULL; goto done; } if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) send_acknowledge(nspi, ACKNOWLEDGE_ACK); - /* Forward skb to NCI core layer */ - ret = nci_recv_frame(nspi->ndev, skb); - done: nspi->ops->assert_int(nspi); - return ret; + return skb; } -EXPORT_SYMBOL_GPL(nci_spi_recv_frame); +EXPORT_SYMBOL_GPL(nci_spi_read); -- cgit From 2bed27851767d93b5d2823eee110857f350a9fbe Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 23 Sep 2013 17:56:43 +0200 Subject: NFC: NCI: Modify NCI SPI to implement CS/INT handshake per the spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NFC Forum NCI specification defines both a hardware and software protocol when using a SPI physical transport to connect an NFC NCI Chipset. The hardware requirement is that, after having raised the chip select line, the SPI driver must wait for an INT line from the NFC chipset to raise before it sends the data. The chip select must be raised first though, because this is the signal that the NFC chipset will detect to wake up and then raise its INT line. If the INT line doesn't raise in a timely fashion, the SPI driver should abort operation. When data is transferred from Device host (DH) to NFC Controller (NFCC), the signaling sequence is the following: Data Transfer from DH to NFCC • 1-Master asserts SPI_CSN • 2-Slave asserts SPI_INT • 3-Master sends NCI-over-SPI protocol header and payload data • 4-Slave deasserts SPI_INT • 5-Master deasserts SPI_CSN When data must be transferred from NFCC to DH, things are a little bit different. Data Transfer from NFCC to DH • 1-Slave asserts SPI_INT -> NFC chipset irq handler called -> process reading from SPI • 2-Master asserts SPI_CSN • 3-Master send 2-octet NCI-over-SPI protocol header • 4-Slave sends 2-octet NCI-over-SPI protocol payload length • 5-Slave sends NCI-over-SPI protocol payload • 6-Master deasserts SPI_CSN In this case, SPI driver should function normally as it does today. Note that the INT line can and will be lowered anytime between beginning of step 3 and end of step 5. A low INT is therefore valid after chip select has been raised. This would be easily implemented in a single driver. Unfortunately, we don't write the SPI driver and I had to imagine some workaround trick to get the SPI and NFC drivers to work in a synchronized fashion. The trick is the following: - send an empty spi message: this will raise the chip select line, and send nothing. We expect the /CS line will stay arisen because we asked for it in the spi_transfer cs_change field - wait for a completion, that will be completed by the NFC driver IRQ handler when it knows we are in the process of sending data (NFC spec says that we use SPI in a half duplex mode, so we are either sending or receiving). - when completed, proceed with the normal data send. This has been tested and verified to work very consistently on a Nexus 10 (spi-s3c64xx driver). It may not work the same with other spi drivers. The previously defined nci_spi_ops{} whose intended purpose were to address this problem are not used anymore and therefore totally removed. The nci_spi_send() takes a new optional write_handshake_completion completion pointer. If non NULL, the nci spi layer will run the above trick when sending data to the NFC Chip. If NULL, the data is sent normally all at once and it is then the NFC driver responsibility to know what it's doing. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 13 +++--------- net/nfc/nci/spi.c | 53 +++++++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 1d505317dc67..6126f1f992b4 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -207,17 +207,9 @@ int nci_to_errno(__u8 code); #define NCI_SPI_CRC_ENABLED 0x01 /* ----- NCI SPI structures ----- */ -struct nci_spi; - -struct nci_spi_ops { - void (*assert_int)(struct nci_spi *nspi); - void (*deassert_int)(struct nci_spi *nspi); -}; - struct nci_spi { struct nci_dev *ndev; struct spi_device *spi; - struct nci_spi_ops *ops; unsigned int xfer_udelay; /* microseconds delay between transactions */ @@ -229,10 +221,11 @@ struct nci_spi { /* ----- NCI SPI ----- */ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, - struct nci_spi_ops *ops, u8 acknowledge_mode, unsigned int delay, struct nci_dev *ndev); -int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb); +int nci_spi_send(struct nci_spi *nspi, + struct completion *write_handshake_completion, + struct sk_buff *skb); struct sk_buff *nci_spi_read(struct nci_spi *nspi); #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index 734c6dde7751..f1d426f10cce 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -38,15 +38,23 @@ #define CRC_INIT 0xFFFF -static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) +static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb, + int cs_change) { struct spi_message m; struct spi_transfer t; memset(&t, 0, sizeof(struct spi_transfer)); - t.tx_buf = skb->data; - t.len = skb->len; - t.cs_change = 0; + /* a NULL skb means we just want the SPI chip select line to raise */ + if (skb) { + t.tx_buf = skb->data; + t.len = skb->len; + } else { + /* still set tx_buf non NULL to make the driver happy */ + t.tx_buf = &t; + t.len = 0; + } + t.cs_change = cs_change; t.delay_usecs = nspi->xfer_udelay; spi_message_init(&m); @@ -55,15 +63,15 @@ static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) return spi_sync(nspi->spi, &m); } -int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) +int nci_spi_send(struct nci_spi *nspi, + struct completion *write_handshake_completion, + struct sk_buff *skb) { unsigned int payload_len = skb->len; unsigned char *hdr; int ret; long completion_rc; - nspi->ops->deassert_int(nspi); - /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); hdr[0] = NCI_SPI_DIRECT_WRITE; @@ -79,11 +87,21 @@ int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) *skb_put(skb, 1) = crc & 0xFF; } - ret = __nci_spi_send(nspi, skb); + if (write_handshake_completion) { + /* Trick SPI driver to raise chip select */ + ret = __nci_spi_send(nspi, NULL, 1); + if (ret) + goto done; - kfree_skb(skb); - nspi->ops->assert_int(nspi); + /* wait for NFC chip hardware handshake to complete */ + if (wait_for_completion_timeout(write_handshake_completion, + msecs_to_jiffies(1000)) == 0) { + ret = -ETIME; + goto done; + } + } + ret = __nci_spi_send(nspi, skb, 0); if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) goto done; @@ -96,6 +114,8 @@ int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) ret = -EIO; done: + kfree_skb(skb); + return ret; } EXPORT_SYMBOL_GPL(nci_spi_send); @@ -106,26 +126,20 @@ EXPORT_SYMBOL_GPL(nci_spi_send); * nci_spi_allocate_spi - allocate a new nci spi * * @spi: SPI device - * @ops: device operations * @acknowledge_mode: Acknowledge mode used by the NFC device * @delay: delay between transactions in us * @ndev: nci dev to send incoming nci frames to */ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, - struct nci_spi_ops *ops, u8 acknowledge_mode, unsigned int delay, struct nci_dev *ndev) { struct nci_spi *nspi; - if (!ops->assert_int || !ops->deassert_int) - return NULL; - nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); if (!nspi) return NULL; - nspi->ops = ops; nspi->acknowledge_mode = acknowledge_mode; nspi->xfer_udelay = delay; @@ -156,7 +170,7 @@ static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) *skb_put(skb, 1) = crc >> 8; *skb_put(skb, 1) = crc & 0xFF; - ret = __nci_spi_send(nspi, skb); + ret = __nci_spi_send(nspi, skb, 0); kfree_skb(skb); @@ -189,7 +203,6 @@ static struct sk_buff *__nci_spi_read(struct nci_spi *nspi) spi_message_add_tail(&rx, &m); ret = spi_sync(nspi->spi, &m); - if (ret) return NULL; @@ -213,7 +226,6 @@ static struct sk_buff *__nci_spi_read(struct nci_spi *nspi) spi_message_add_tail(&rx, &m); ret = spi_sync(nspi->spi, &m); - if (ret) goto receive_error; @@ -271,8 +283,6 @@ struct sk_buff *nci_spi_read(struct nci_spi *nspi) { struct sk_buff *skb; - nspi->ops->deassert_int(nspi); - /* Retrieve frame from SPI */ skb = __nci_spi_read(nspi); if (!skb) @@ -305,7 +315,6 @@ struct sk_buff *nci_spi_read(struct nci_spi *nspi) send_acknowledge(nspi, ACKNOWLEDGE_ACK); done: - nspi->ops->assert_int(nspi); return skb; } -- cgit From cc6783f788d8fe8b23ec6fc2762f5e8c9a418eee Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 6 Sep 2013 17:39:49 -0700 Subject: rcu: Is it safe to enter an RCU read-side critical section? There is currently no way for kernel code to determine whether it is safe to enter an RCU read-side critical section, in other words, whether or not RCU is paying attention to the currently running CPU. Given the large and increasing quantity of code shared by the idle loop and non-idle code, the this shortcoming is becoming increasingly painful. This commit therefore adds __rcu_is_watching(), which returns true if it is safe to enter an RCU read-side critical section on the currently running CPU. This function is quite fast, using only a __this_cpu_read(). However, the caller must disable preemption. Reported-by: Steven Rostedt Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett --- include/linux/rcupdate.h | 8 ++++---- include/linux/rcutiny.h | 9 +++++++++ include/linux/rcutree.h | 2 ++ kernel/rcutiny.c | 4 ++-- kernel/rcutree.c | 13 +++++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index f1f1bc39346b..a53a21a2808c 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -261,6 +261,10 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev, rcu_irq_exit(); \ } while (0) +#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) +extern int rcu_is_cpu_idle(void); +#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ + /* * Infrastructure to implement the synchronize_() primitives in * TREE_RCU and rcu_barrier_() primitives in TINY_RCU. @@ -297,10 +301,6 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head) } #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ -#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) -extern int rcu_is_cpu_idle(void); -#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) */ - #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) bool rcu_lockdep_current_cpu_online(void); #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */ diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index e31005ee339e..bee665964878 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -132,4 +132,13 @@ static inline void rcu_scheduler_starting(void) } #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +#ifdef CONFIG_RCU_TRACE + +static inline bool __rcu_is_watching(void) +{ + return !rcu_is_cpu_idle(); +} + +#endif /* #ifdef CONFIG_RCU_TRACE */ + #endif /* __LINUX_RCUTINY_H */ diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 226169d1bd2b..293613dfd2a5 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -90,4 +90,6 @@ extern void exit_rcu(void); extern void rcu_scheduler_starting(void); extern int rcu_scheduler_active __read_mostly; +extern bool __rcu_is_watching(void); + #endif /* __LINUX_RCUTREE_H */ diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 9ed6075dc562..b4bc61874d77 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -174,7 +174,7 @@ void rcu_irq_enter(void) } EXPORT_SYMBOL_GPL(rcu_irq_enter); -#ifdef CONFIG_DEBUG_LOCK_ALLOC +#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) /* * Test whether RCU thinks that the current CPU is idle. @@ -185,7 +185,7 @@ int rcu_is_cpu_idle(void) } EXPORT_SYMBOL(rcu_is_cpu_idle); -#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +#endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */ /* * Test whether the current CPU was interrupted from idle. Nested diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 32618b3fe4e6..910d868808dc 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -671,6 +671,19 @@ int rcu_is_cpu_idle(void) } EXPORT_SYMBOL(rcu_is_cpu_idle); +/** + * __rcu_is_watching - are RCU read-side critical sections safe? + * + * Return true if RCU is watching the running CPU, which means that + * this CPU can safely enter RCU read-side critical sections. Unlike + * rcu_is_cpu_idle(), the caller of __rcu_is_watching() must have at + * least disabled preemption. + */ +bool __rcu_is_watching(void) +{ + return !!(atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1); +} + #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) /* -- cgit From 5c173eb8bcb9c1aa888bd6d14a4cb746f3dd2420 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 13 Sep 2013 17:20:11 -0700 Subject: rcu: Consistent rcu_is_watching() naming The old rcu_is_cpu_idle() function is just __rcu_is_watching() with preemption disabled. This commit therefore renames rcu_is_cpu_idle() to rcu_is_watching. Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett --- include/linux/rcupdate.h | 18 +++++++++--------- include/linux/rcutiny.h | 16 ++++++++++++---- include/linux/rcutree.h | 2 +- kernel/lockdep.c | 4 ++-- kernel/rcupdate.c | 2 +- kernel/rcutiny.c | 6 +++--- kernel/rcutree.c | 36 ++++++++++++++++++------------------ 7 files changed, 46 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index a53a21a2808c..39cbb889e20d 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -262,7 +262,7 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev, } while (0) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) -extern int rcu_is_cpu_idle(void); +extern bool __rcu_is_watching(void); #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ /* @@ -351,7 +351,7 @@ static inline int rcu_read_lock_held(void) { if (!debug_lockdep_rcu_enabled()) return 1; - if (rcu_is_cpu_idle()) + if (!rcu_is_watching()) return 0; if (!rcu_lockdep_current_cpu_online()) return 0; @@ -402,7 +402,7 @@ static inline int rcu_read_lock_sched_held(void) if (!debug_lockdep_rcu_enabled()) return 1; - if (rcu_is_cpu_idle()) + if (!rcu_is_watching()) return 0; if (!rcu_lockdep_current_cpu_online()) return 0; @@ -771,7 +771,7 @@ static inline void rcu_read_lock(void) __rcu_read_lock(); __acquire(RCU); rcu_lock_acquire(&rcu_lock_map); - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_lock() used illegally while idle"); } @@ -792,7 +792,7 @@ static inline void rcu_read_lock(void) */ static inline void rcu_read_unlock(void) { - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_unlock() used illegally while idle"); rcu_lock_release(&rcu_lock_map); __release(RCU); @@ -821,7 +821,7 @@ static inline void rcu_read_lock_bh(void) local_bh_disable(); __acquire(RCU_BH); rcu_lock_acquire(&rcu_bh_lock_map); - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_lock_bh() used illegally while idle"); } @@ -832,7 +832,7 @@ static inline void rcu_read_lock_bh(void) */ static inline void rcu_read_unlock_bh(void) { - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_unlock_bh() used illegally while idle"); rcu_lock_release(&rcu_bh_lock_map); __release(RCU_BH); @@ -857,7 +857,7 @@ static inline void rcu_read_lock_sched(void) preempt_disable(); __acquire(RCU_SCHED); rcu_lock_acquire(&rcu_sched_lock_map); - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_lock_sched() used illegally while idle"); } @@ -875,7 +875,7 @@ static inline notrace void rcu_read_lock_sched_notrace(void) */ static inline void rcu_read_unlock_sched(void) { - rcu_lockdep_assert(!rcu_is_cpu_idle(), + rcu_lockdep_assert(rcu_is_watching(), "rcu_read_unlock_sched() used illegally while idle"); rcu_lock_release(&rcu_sched_lock_map); __release(RCU_SCHED); diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index bee665964878..09ebcbe9fd78 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -132,13 +132,21 @@ static inline void rcu_scheduler_starting(void) } #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ -#ifdef CONFIG_RCU_TRACE +#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) -static inline bool __rcu_is_watching(void) +static inline bool rcu_is_watching(void) { - return !rcu_is_cpu_idle(); + return __rcu_is_watching(); } -#endif /* #ifdef CONFIG_RCU_TRACE */ +#else /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */ + +static inline bool rcu_is_watching(void) +{ + return true; +} + + +#endif /* #else defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */ #endif /* __LINUX_RCUTINY_H */ diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 293613dfd2a5..4b9c81548742 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -90,6 +90,6 @@ extern void exit_rcu(void); extern void rcu_scheduler_starting(void); extern int rcu_scheduler_active __read_mostly; -extern bool __rcu_is_watching(void); +extern bool rcu_is_watching(void); #endif /* __LINUX_RCUTREE_H */ diff --git a/kernel/lockdep.c b/kernel/lockdep.c index e16c45b9ee77..4e8e14c34e42 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -4224,7 +4224,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s) printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n", !rcu_lockdep_current_cpu_online() ? "RCU used illegally from offline CPU!\n" - : rcu_is_cpu_idle() + : !rcu_is_watching() ? "RCU used illegally from idle CPU!\n" : "", rcu_scheduler_active, debug_locks); @@ -4247,7 +4247,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s) * So complain bitterly if someone does call rcu_read_lock(), * rcu_read_lock_bh() and so on from extended quiescent states. */ - if (rcu_is_cpu_idle()) + if (!rcu_is_watching()) printk("RCU used illegally from extended quiescent state!\n"); lockdep_print_held_locks(curr); diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index b02a339836b4..3b3c0464d1eb 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -148,7 +148,7 @@ int rcu_read_lock_bh_held(void) { if (!debug_lockdep_rcu_enabled()) return 1; - if (rcu_is_cpu_idle()) + if (!rcu_is_watching()) return 0; if (!rcu_lockdep_current_cpu_online()) return 0; diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index b4bc61874d77..0fa061dfa55d 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -179,11 +179,11 @@ EXPORT_SYMBOL_GPL(rcu_irq_enter); /* * Test whether RCU thinks that the current CPU is idle. */ -int rcu_is_cpu_idle(void) +bool __rcu_is_watching(void) { - return !rcu_dynticks_nesting; + return rcu_dynticks_nesting; } -EXPORT_SYMBOL(rcu_is_cpu_idle); +EXPORT_SYMBOL(__rcu_is_watching); #endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */ diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 1b123e179d71..981d0c15a389 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -655,34 +655,34 @@ void rcu_nmi_exit(void) } /** - * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle + * __rcu_is_watching - are RCU read-side critical sections safe? + * + * Return true if RCU is watching the running CPU, which means that + * this CPU can safely enter RCU read-side critical sections. Unlike + * rcu_is_watching(), the caller of __rcu_is_watching() must have at + * least disabled preemption. + */ +bool __rcu_is_watching(void) +{ + return atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1; +} + +/** + * rcu_is_watching - see if RCU thinks that the current CPU is idle * * If the current CPU is in its idle loop and is neither in an interrupt * or NMI handler, return true. */ -int rcu_is_cpu_idle(void) +bool rcu_is_watching(void) { int ret; preempt_disable(); - ret = (atomic_read(&__get_cpu_var(rcu_dynticks).dynticks) & 0x1) == 0; + ret = __rcu_is_watching(); preempt_enable(); return ret; } -EXPORT_SYMBOL_GPL(rcu_is_cpu_idle); - -/** - * __rcu_is_watching - are RCU read-side critical sections safe? - * - * Return true if RCU is watching the running CPU, which means that - * this CPU can safely enter RCU read-side critical sections. Unlike - * rcu_is_cpu_idle(), the caller of __rcu_is_watching() must have at - * least disabled preemption. - */ -bool __rcu_is_watching(void) -{ - return !!(atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1); -} +EXPORT_SYMBOL_GPL(rcu_is_watching); #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) @@ -2268,7 +2268,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, * If called from an extended quiescent state, invoke the RCU * core in order to force a re-evaluation of RCU's idleness. */ - if (rcu_is_cpu_idle() && cpu_online(smp_processor_id())) + if (!rcu_is_watching() && cpu_online(smp_processor_id())) invoke_rcu_core(); /* If interrupts were disabled or CPU offline, don't invoke RCU core. */ -- cgit From 9abc4e66eb839c28516916543768be08c814a3c8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:15:10 +0100 Subject: KEYS: Rename public key parameter name arrays Rename the arrays of public key parameters (public key algorithm names, hash algorithm names and ID type names) so that the array name ends in "_name". Signed-off-by: David Howells Reviewed-by: Kees Cook Reviewed-by: Josh Boyer --- crypto/asymmetric_keys/public_key.c | 14 +++++++------- crypto/asymmetric_keys/x509_public_key.c | 8 ++++---- include/crypto/public_key.h | 6 +++--- kernel/module_signing.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index cb2e29180a87..b313df1bd253 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -22,13 +22,13 @@ MODULE_LICENSE("GPL"); -const char *const pkey_algo[PKEY_ALGO__LAST] = { +const char *const pkey_algo_name[PKEY_ALGO__LAST] = { [PKEY_ALGO_DSA] = "DSA", [PKEY_ALGO_RSA] = "RSA", }; -EXPORT_SYMBOL_GPL(pkey_algo); +EXPORT_SYMBOL_GPL(pkey_algo_name); -const char *const pkey_hash_algo[PKEY_HASH__LAST] = { +const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { [PKEY_HASH_MD4] = "md4", [PKEY_HASH_MD5] = "md5", [PKEY_HASH_SHA1] = "sha1", @@ -38,13 +38,13 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = { [PKEY_HASH_SHA512] = "sha512", [PKEY_HASH_SHA224] = "sha224", }; -EXPORT_SYMBOL_GPL(pkey_hash_algo); +EXPORT_SYMBOL_GPL(pkey_hash_algo_name); -const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { +const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { [PKEY_ID_PGP] = "PGP", [PKEY_ID_X509] = "X509", }; -EXPORT_SYMBOL_GPL(pkey_id_type); +EXPORT_SYMBOL_GPL(pkey_id_type_name); /* * Provide a part of a description of the key for /proc/keys. @@ -56,7 +56,7 @@ static void public_key_describe(const struct key *asymmetric_key, if (key) seq_printf(m, "%s.%s", - pkey_id_type[key->id_type], key->algo->name); + pkey_id_type_name[key->id_type], key->algo->name); } /* diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 06007f0e880c..afbbc362f85a 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -49,7 +49,7 @@ static int x509_check_signature(const struct public_key *pub, /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); + tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); @@ -117,7 +117,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Issuer: %s\n", cert->issuer); pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); + pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, cert->valid_from.tm_mday, cert->valid_from.tm_hour, @@ -127,8 +127,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->valid_to.tm_mday, cert->valid_to.tm_hour, cert->valid_to.tm_min, cert->valid_to.tm_sec); pr_devel("Cert Signature: %s + %s\n", - pkey_algo[cert->sig_pkey_algo], - pkey_hash_algo[cert->sig_hash_algo]); + pkey_algo_name[cert->sig_pkey_algo], + pkey_hash_algo_name[cert->sig_hash_algo]); if (!cert->fingerprint || !cert->authority) { pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index f5b0224c9967..619d5706d837 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -22,7 +22,7 @@ enum pkey_algo { PKEY_ALGO__LAST }; -extern const char *const pkey_algo[PKEY_ALGO__LAST]; +extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; enum pkey_hash_algo { PKEY_HASH_MD4, @@ -36,7 +36,7 @@ enum pkey_hash_algo { PKEY_HASH__LAST }; -extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; +extern const char *const pkey_hash_algo_name[PKEY_HASH__LAST]; enum pkey_id_type { PKEY_ID_PGP, /* OpenPGP generated key ID */ @@ -44,7 +44,7 @@ enum pkey_id_type { PKEY_ID_TYPE__LAST }; -extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; +extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; /* * Cryptographic data for the public-key subtype of the asymmetric key type. diff --git a/kernel/module_signing.c b/kernel/module_signing.c index f2970bddc5ea..ee476404167b 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -54,7 +54,7 @@ static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); + tfm = crypto_alloc_shash(pkey_hash_algo_name[hash], 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); @@ -217,7 +217,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) return -ENOPKG; if (ms.hash >= PKEY_HASH__LAST || - !pkey_hash_algo[ms.hash]) + !pkey_hash_algo_name[ms.hash]) return -ENOPKG; key = request_asymmetric_key(sig, ms.signer_len, -- cgit From 206ce59a109f3b4bb352845bcd04f3cf504ae592 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:15:18 +0100 Subject: KEYS: Move the algorithm pointer array from x509 to public_key.c Move the public-key algorithm pointer array from x509_public_key.c to public_key.c as it isn't X.509 specific. Note that to make this configure correctly, the public key part must be dependent on the RSA module rather than the other way round. This needs a further patch to make use of the crypto module loading stuff rather than using a fixed table. Signed-off-by: David Howells Reviewed-by: Kees Cook Reviewed-by: Josh Boyer --- crypto/asymmetric_keys/Kconfig | 2 +- crypto/asymmetric_keys/public_key.c | 8 ++++++++ crypto/asymmetric_keys/x509_public_key.c | 11 +---------- include/crypto/public_key.h | 1 + 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 6d2c2ea12559..862b01fe6172 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -12,6 +12,7 @@ if ASYMMETRIC_KEY_TYPE config ASYMMETRIC_PUBLIC_KEY_SUBTYPE tristate "Asymmetric public-key crypto algorithm subtype" select MPILIB + select PUBLIC_KEY_ALGO_RSA help This option provides support for asymmetric public key type handling. If signature generation and/or verification are to be used, @@ -20,7 +21,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate "RSA public-key algorithm" - depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE select MPILIB_EXTRA help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index b313df1bd253..796ce0802aa0 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -28,6 +28,14 @@ const char *const pkey_algo_name[PKEY_ALGO__LAST] = { }; EXPORT_SYMBOL_GPL(pkey_algo_name); +const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { +#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ + defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) + [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, +#endif +}; +EXPORT_SYMBOL_GPL(pkey_algo); + const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { [PKEY_HASH_MD4] = "md4", [PKEY_HASH_MD5] = "md5", diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index afbbc362f85a..fe38628adae9 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -23,15 +23,6 @@ #include "public_key.h" #include "x509_parser.h" -static const -struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = NULL, -#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ - defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) - [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -#endif -}; - /* * Check the signature on a certificate using the provided public key */ @@ -174,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) goto error_free_cert; } - cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; + cert->pub->algo = pkey_algo[cert->pkey_algo]; cert->pub->id_type = PKEY_ID_X509; /* Check the signature on the key */ diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 619d5706d837..46bde250bfae 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -23,6 +23,7 @@ enum pkey_algo { }; extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; +extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST]; enum pkey_hash_algo { PKEY_HASH_MD4, -- cgit From 67f7d60b3a08a3e3ec51c29c25767a9d9d0bd2b1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:15:24 +0100 Subject: KEYS: Store public key algo ID in public_key struct Store public key algo ID in public_key struct for reference purposes. This allows it to be removed from the x509_certificate struct and used to find a default in public_key_verify_signature(). Signed-off-by: David Howells Reviewed-by: Kees Cook Reviewed-by: Josh Boyer --- crypto/asymmetric_keys/x509_cert_parser.c | 5 +++-- crypto/asymmetric_keys/x509_parser.h | 1 - crypto/asymmetric_keys/x509_public_key.c | 4 ++-- include/crypto/public_key.h | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index facbf26bc6bb..8cc253d2dc92 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -343,8 +343,9 @@ int x509_extract_key_data(void *context, size_t hdrlen, if (ctx->last_oid != OID_rsaEncryption) return -ENOPKG; - /* There seems to be an extraneous 0 byte on the front of the data */ - ctx->cert->pkey_algo = PKEY_ALGO_RSA; + ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; + + /* Discard the BIT STRING metadata */ ctx->key = value + 1; ctx->key_size = vlen - 1; return 0; diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index f86dc5fcc4ad..e583ad09e5a1 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -20,7 +20,6 @@ struct x509_certificate { char *authority; /* Authority key fingerprint as hex */ struct tm valid_from; struct tm valid_to; - enum pkey_algo pkey_algo : 8; /* Public key algorithm */ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ const void *tbs; /* Signed data */ diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index fe38628adae9..fac574c457b3 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -108,7 +108,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Issuer: %s\n", cert->issuer); pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); + pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, cert->valid_from.tm_mday, cert->valid_from.tm_hour, @@ -165,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) goto error_free_cert; } - cert->pub->algo = pkey_algo[cert->pkey_algo]; + cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; cert->pub->id_type = PKEY_ID_X509; /* Check the signature on the key */ diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 46bde250bfae..05778df0e3b4 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -60,6 +60,7 @@ struct public_key { #define PKEY_CAN_DECRYPT 0x02 #define PKEY_CAN_SIGN 0x04 #define PKEY_CAN_VERIFY 0x08 + enum pkey_algo pkey_algo : 8; enum pkey_id_type id_type : 8; union { MPI mpi[5]; -- cgit From 1573801fa89d022b9f5bd1b189d23221335f9f56 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:15:37 +0100 Subject: KEYS: Store public key algo ID in public_key_signature struct Store public key algorithm ID in public_key_signature struct for reference purposes. This allows a public_key_signature struct to be embedded in struct x509_certificate and other places more easily. Signed-off-by: David Howells Reviewed-by: Kees Cook Reviewed-by: Josh Boyer --- include/crypto/public_key.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 05778df0e3b4..b34fda4dcabf 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -90,6 +90,7 @@ struct public_key_signature { u8 *digest; u8 digest_size; /* Number of bytes in digest */ u8 nr_mpi; /* Occupancy of mpi[] */ + enum pkey_algo pkey_algo : 8; enum pkey_hash_algo pkey_hash_algo : 8; union { MPI mpi[2]; -- cgit From b56e5a17b6b9acd16997960504b9940d0d7984e7 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:07:30 +0100 Subject: KEYS: Separate the kernel signature checking keyring from module signing Separate the kernel signature checking keyring from module signing so that it can be used by code other than the module-signing code. Signed-off-by: David Howells --- include/keys/system_keyring.h | 23 ++++++++++ init/Kconfig | 13 ++++++ kernel/Makefile | 15 ++++-- kernel/modsign_certificate.S | 11 ----- kernel/modsign_pubkey.c | 104 ------------------------------------------ kernel/module-internal.h | 2 - kernel/module_signing.c | 3 +- kernel/system_certificates.S | 12 +++++ kernel/system_keyring.c | 103 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 163 insertions(+), 123 deletions(-) create mode 100644 include/keys/system_keyring.h delete mode 100644 kernel/modsign_certificate.S delete mode 100644 kernel/modsign_pubkey.c create mode 100644 kernel/system_certificates.S create mode 100644 kernel/system_keyring.c (limited to 'include') diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h new file mode 100644 index 000000000000..8dabc399bd1d --- /dev/null +++ b/include/keys/system_keyring.h @@ -0,0 +1,23 @@ +/* System keyring containing trusted public keys. + * + * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _KEYS_SYSTEM_KEYRING_H +#define _KEYS_SYSTEM_KEYRING_H + +#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING + +#include + +extern struct key *system_trusted_keyring; + +#endif + +#endif /* _KEYS_SYSTEM_KEYRING_H */ diff --git a/init/Kconfig b/init/Kconfig index 3ecd8a1178f1..0ff5407a8378 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1668,6 +1668,18 @@ config BASE_SMALL default 0 if BASE_FULL default 1 if !BASE_FULL +config SYSTEM_TRUSTED_KEYRING + bool "Provide system-wide ring of trusted keys" + depends on KEYS + help + Provide a system keyring to which trusted keys can be added. Keys in + the keyring are considered to be trusted. Keys may be added at will + by the kernel from compiled-in data and from hardware key stores, but + userspace may only add extra keys if those keys can be verified by + keys already in the keyring. + + Keys in this keyring are used by module signature checking. + menuconfig MODULES bool "Enable loadable module support" option modules @@ -1741,6 +1753,7 @@ config MODULE_SRCVERSION_ALL config MODULE_SIG bool "Module signature verification" depends on MODULES + select SYSTEM_TRUSTED_KEYRING select KEYS select CRYPTO select ASYMMETRIC_KEY_TYPE diff --git a/kernel/Makefile b/kernel/Makefile index 2c24195249d5..63136989c132 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -54,8 +54,9 @@ obj-$(CONFIG_SMP) += spinlock.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o +obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o +obj-$(CONFIG_MODULE_SIG) += module_signing.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o @@ -141,11 +142,11 @@ targets += timeconst.h $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE $(call if_changed,bc) -ifeq ($(CONFIG_MODULE_SIG),y) ############################################################################### # # Roll all the X.509 certificates that we can find together and pull them into -# the kernel. +# the kernel so that they get loaded into the system trusted keyring during +# boot. # # We look in the source root and the build root for all files whose name ends # in ".x509". Unfortunately, this will generate duplicate filenames, so we @@ -153,6 +154,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) # duplicates. # ############################################################################### +ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ @@ -169,10 +171,11 @@ $(shell rm $(obj)/.x509.list) endif endif -kernel/modsign_certificate.o: $(obj)/x509_certificate_list +kernel/system_certificates.o: $(obj)/x509_certificate_list quiet_cmd_x509certs = CERTS $@ - cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ + cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") + targets += $(obj)/x509_certificate_list $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list $(call if_changed,x509certs) @@ -182,7 +185,9 @@ $(obj)/.x509.list: @echo $(X509_CERTIFICATES) >$@ clean-files := x509_certificate_list .x509.list +endif +ifeq ($(CONFIG_MODULE_SIG),y) ############################################################################### # # If module signing is requested, say by allyesconfig, but a key has not been diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S deleted file mode 100644 index 6fe03c7ffe72..000000000000 --- a/kernel/modsign_certificate.S +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#define GLOBAL(name) \ - .globl VMLINUX_SYMBOL(name); \ - VMLINUX_SYMBOL(name): - - .section ".init.data","aw" - -GLOBAL(modsign_certificate_list) - .incbin "kernel/x509_certificate_list" -GLOBAL(modsign_certificate_list_end) diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c deleted file mode 100644 index 7cbd4507a7e6..000000000000 --- a/kernel/modsign_pubkey.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Public keys for module signature verification - * - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include "module-internal.h" - -struct key *modsign_keyring; - -extern __initconst const u8 modsign_certificate_list[]; -extern __initconst const u8 modsign_certificate_list_end[]; - -/* - * We need to make sure ccache doesn't cache the .o file as it doesn't notice - * if modsign.pub changes. - */ -static __initconst const char annoy_ccache[] = __TIME__ "foo"; - -/* - * Load the compiled-in keys - */ -static __init int module_verify_init(void) -{ - pr_notice("Initialise module verification\n"); - - modsign_keyring = keyring_alloc(".module_sign", - KUIDT_INIT(0), KGIDT_INIT(0), - current_cred(), - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA, NULL); - if (IS_ERR(modsign_keyring)) - panic("Can't allocate module signing keyring\n"); - - return 0; -} - -/* - * Must be initialised before we try and load the keys into the keyring. - */ -device_initcall(module_verify_init); - -/* - * Load the compiled-in keys - */ -static __init int load_module_signing_keys(void) -{ - key_ref_t key; - const u8 *p, *end; - size_t plen; - - pr_notice("Loading module verification certificates\n"); - - end = modsign_certificate_list_end; - p = modsign_certificate_list; - while (p < end) { - /* Each cert begins with an ASN.1 SEQUENCE tag and must be more - * than 256 bytes in size. - */ - if (end - p < 4) - goto dodgy_cert; - if (p[0] != 0x30 && - p[1] != 0x82) - goto dodgy_cert; - plen = (p[2] << 8) | p[3]; - plen += 4; - if (plen > end - p) - goto dodgy_cert; - - key = key_create_or_update(make_key_ref(modsign_keyring, 1), - "asymmetric", - NULL, - p, - plen, - (KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW, - KEY_ALLOC_NOT_IN_QUOTA); - if (IS_ERR(key)) - pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", - PTR_ERR(key)); - else - pr_notice("MODSIGN: Loaded cert '%s'\n", - key_ref_to_ptr(key)->description); - p += plen; - } - - return 0; - -dodgy_cert: - pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); - return 0; -} -late_initcall(load_module_signing_keys); diff --git a/kernel/module-internal.h b/kernel/module-internal.h index 24f9247b7d02..915e123a430f 100644 --- a/kernel/module-internal.h +++ b/kernel/module-internal.h @@ -9,6 +9,4 @@ * 2 of the Licence, or (at your option) any later version. */ -extern struct key *modsign_keyring; - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module_signing.c b/kernel/module_signing.c index ee476404167b..0b6b870dc5e4 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "module-internal.h" /* @@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, pr_debug("Look up: \"%s\"\n", id); - key = keyring_search(make_key_ref(modsign_keyring, 1), + key = keyring_search(make_key_ref(system_trusted_keyring, 1), &key_type_asymmetric, id); if (IS_ERR(key)) pr_warn("Request for unknown module key '%s' err %ld\n", diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S new file mode 100644 index 000000000000..552d47b2d463 --- /dev/null +++ b/kernel/system_certificates.S @@ -0,0 +1,12 @@ +#include +#include + +#define GLOBAL(name) \ + .globl VMLINUX_SYMBOL(name); \ + VMLINUX_SYMBOL(name): + + __INITRODATA + +GLOBAL(system_certificate_list) + .incbin "kernel/x509_certificate_list" +GLOBAL(system_certificate_list_end) diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c new file mode 100644 index 000000000000..51c35141a13a --- /dev/null +++ b/kernel/system_keyring.c @@ -0,0 +1,103 @@ +/* System trusted keyring for trusted public keys + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "module-internal.h" + +struct key *system_trusted_keyring; +EXPORT_SYMBOL_GPL(system_trusted_keyring); + +extern __initconst const u8 system_certificate_list[]; +extern __initconst const u8 system_certificate_list_end[]; + +/* + * Load the compiled-in keys + */ +static __init int system_trusted_keyring_init(void) +{ + pr_notice("Initialise system trusted keyring\n"); + + system_trusted_keyring = + keyring_alloc(".system_keyring", + KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (IS_ERR(system_trusted_keyring)) + panic("Can't allocate system trusted keyring\n"); + + return 0; +} + +/* + * Must be initialised before we try and load the keys into the keyring. + */ +device_initcall(system_trusted_keyring_init); + +/* + * Load the compiled-in list of X.509 certificates. + */ +static __init int load_system_certificate_list(void) +{ + key_ref_t key; + const u8 *p, *end; + size_t plen; + + pr_notice("Loading compiled-in X.509 certificates\n"); + + end = system_certificate_list_end; + p = system_certificate_list; + while (p < end) { + /* Each cert begins with an ASN.1 SEQUENCE tag and must be more + * than 256 bytes in size. + */ + if (end - p < 4) + goto dodgy_cert; + if (p[0] != 0x30 && + p[1] != 0x82) + goto dodgy_cert; + plen = (p[2] << 8) | p[3]; + plen += 4; + if (plen > end - p) + goto dodgy_cert; + + key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), + "asymmetric", + NULL, + p, + plen, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA); + if (IS_ERR(key)) { + pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", + PTR_ERR(key)); + } else { + pr_notice("Loaded X.509 cert '%s'\n", + key_ref_to_ptr(key)->description); + key_ref_put(key); + } + p += plen; + } + + return 0; + +dodgy_cert: + pr_err("Problem parsing in-kernel X.509 certificate list\n"); + return 0; +} +late_initcall(load_system_certificate_list); -- cgit From 008643b86c5f33c115c84ccdda1725cac3ad50ad Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Aug 2013 16:07:37 +0100 Subject: KEYS: Add a 'trusted' flag and a 'trusted only' flag Add KEY_FLAG_TRUSTED to indicate that a key either comes from a trusted source or had a cryptographic signature chain that led back to a trusted key the kernel already possessed. Add KEY_FLAGS_TRUSTED_ONLY to indicate that a keyring will only accept links to keys marked with KEY_FLAGS_TRUSTED. Signed-off-by: David Howells Reviewed-by: Kees Cook --- include/linux/key-type.h | 1 + include/linux/key.h | 3 +++ kernel/system_keyring.c | 4 +++- security/keys/key.c | 8 ++++++++ security/keys/keyring.c | 4 ++++ 5 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/key-type.h b/include/linux/key-type.h index f58737bcb050..a74c3a84dfdd 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -45,6 +45,7 @@ struct key_preparsed_payload { const void *data; /* Raw data */ size_t datalen; /* Raw datalen */ size_t quotalen; /* Quota length for proposed payload */ + bool trusted; /* True if key is trusted */ }; typedef int (*request_key_actor_t)(struct key_construction *key, diff --git a/include/linux/key.h b/include/linux/key.h index 010dbb618aca..80d677483e31 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -168,6 +168,8 @@ struct key { #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ +#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ +#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ /* the key type and key description string * - the desc is used to match a key against search criteria @@ -218,6 +220,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ +#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c index 51c35141a13a..5296721eca5b 100644 --- a/kernel/system_keyring.c +++ b/kernel/system_keyring.c @@ -40,6 +40,7 @@ static __init int system_trusted_keyring_init(void) if (IS_ERR(system_trusted_keyring)) panic("Can't allocate system trusted keyring\n"); + set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); return 0; } @@ -82,7 +83,8 @@ static __init int load_system_certificate_list(void) plen, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW, - KEY_ALLOC_NOT_IN_QUOTA); + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_TRUSTED); if (IS_ERR(key)) { pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", PTR_ERR(key)); diff --git a/security/keys/key.c b/security/keys/key.c index a819b5c7d4ec..d331ea9ef380 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -300,6 +300,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; + if (flags & KEY_ALLOC_TRUSTED) + key->flags |= 1 << KEY_FLAG_TRUSTED; memset(&key->type_data, 0, sizeof(key->type_data)); @@ -813,6 +815,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, prep.data = payload; prep.datalen = plen; prep.quotalen = index_key.type->def_datalen; + prep.trusted = flags & KEY_ALLOC_TRUSTED; if (index_key.type->preparse) { ret = index_key.type->preparse(&prep); if (ret < 0) { @@ -827,6 +830,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } index_key.desc_len = strlen(index_key.description); + key_ref = ERR_PTR(-EPERM); + if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) + goto error_free_prep; + flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; + ret = __key_link_begin(keyring, &index_key, &edit); if (ret < 0) { key_ref = ERR_PTR(ret); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f7cdea22214f..9b6f6e09b50c 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1183,6 +1183,10 @@ int key_link(struct key *keyring, struct key *key) key_check(keyring); key_check(key); + if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && + !test_bit(KEY_FLAG_TRUSTED, &key->flags)) + return -EPERM; + ret = __key_link_begin(keyring, &key->index_key, &edit); if (ret == 0) { kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); -- cgit From 416a4ae56b7a37407ca1155805c05b638f845778 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 25 Sep 2013 13:26:08 +0300 Subject: Bluetooth: Use async request for LE enable/disable This patch updates the code to use an asynchronous request for handling the enabling and disabling of LE support. This refactoring is necessary as a preparation for adding advertising support, since when LE is disabled we should also disable advertising, and the cleanest way to do this is to perform the two respective HCI commands in the same asynchronous request. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_event.c | 11 +++---- net/bluetooth/mgmt.c | 67 ++++++++++++++++------------------------ 3 files changed, 32 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3ede820d328f..26cc9f7858cd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1168,7 +1168,6 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, u8 *randomizer, u8 status); -int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 ssp, u8 *eir, u16 eir_len); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 94aab73f89d4..48db81f8a337 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -994,20 +994,19 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, return; if (!status) { - if (sent->le) + if (sent->le) { hdev->features[1][0] |= LMP_HOST_LE; - else + set_bit(HCI_LE_ENABLED, &hdev->dev_flags); + } else { hdev->features[1][0] &= ~LMP_HOST_LE; + clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); + } if (sent->simul) hdev->features[1][0] |= LMP_HOST_LE_BREDR; else hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; } - - if (test_bit(HCI_MGMT, &hdev->dev_flags) && - !test_bit(HCI_INIT, &hdev->flags)) - mgmt_le_enable_complete(hdev, sent->le, status); } static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 61d4b190eebf..4c3984ee1114 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1354,11 +1354,32 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev); } +static void le_enable_complete(struct hci_dev *hdev, u8 status) +{ + struct cmd_lookup match = { NULL, hdev }; + + if (status) { + u8 mgmt_err = mgmt_status(status); + + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, + &mgmt_err); + return; + } + + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); + + new_settings(hdev, match.sk); + + if (match.sk) + sock_put(match.sk); +} + static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_mode *cp = data; struct hci_cp_write_le_host_supported hci_cp; struct pending_cmd *cmd; + struct hci_request req; int err; u8 val, enabled; @@ -1419,8 +1440,12 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_cp.simul = lmp_le_br_capable(hdev); } - err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), - &hci_cp); + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), + &hci_cp); + + err = hci_req_run(&req, le_enable_complete); if (err < 0) mgmt_pending_remove(cmd); @@ -4141,44 +4166,6 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, return err; } -int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) -{ - struct cmd_lookup match = { NULL, hdev }; - bool changed = false; - int err = 0; - - if (status) { - u8 mgmt_err = mgmt_status(status); - - if (enable && test_and_clear_bit(HCI_LE_ENABLED, - &hdev->dev_flags)) - err = new_settings(hdev, NULL); - - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, - &mgmt_err); - - return err; - } - - if (enable) { - if (!test_and_set_bit(HCI_LE_ENABLED, &hdev->dev_flags)) - changed = true; - } else { - if (test_and_clear_bit(HCI_LE_ENABLED, &hdev->dev_flags)) - changed = true; - } - - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); - - if (changed) - err = new_settings(hdev, match.sk); - - if (match.sk) - sock_put(match.sk); - - return err; -} - int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 ssp, u8 *eir, u16 eir_len) -- cgit From eeca6f891305a80378da978f803821c2a0b648b6 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 25 Sep 2013 13:26:09 +0300 Subject: Bluetooth: Add new mgmt setting for LE advertising This patch adds a new mgmt setting for LE advertising and hooks up the necessary places in the mgmt code to operate on the HCI_LE_PERIPHERAL flag (which corresponds to this setting). This patch does not yet add any new command for enabling the setting - that is left for a subsequent patch. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/mgmt.h | 1 + net/bluetooth/hci_event.c | 1 + net/bluetooth/mgmt.c | 21 ++++++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 9944c3e68c5d..6cc72b69e014 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -93,6 +93,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_BREDR 0x00000080 #define MGMT_SETTING_HS 0x00000100 #define MGMT_SETTING_LE 0x00000200 +#define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_OP_READ_INFO 0x0004 #define MGMT_READ_INFO_SIZE 0 diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 48db81f8a337..917c7c833f69 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1000,6 +1000,7 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, } else { hdev->features[1][0] &= ~LMP_HOST_LE; clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); + clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); } if (sent->simul) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4c3984ee1114..9a2faa310b7c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -384,8 +384,10 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (enable_hs) settings |= MGMT_SETTING_HS; - if (lmp_le_capable(hdev)) + if (lmp_le_capable(hdev)) { settings |= MGMT_SETTING_LE; + settings |= MGMT_SETTING_ADVERTISING; + } return settings; } @@ -424,6 +426,9 @@ static u32 get_current_settings(struct hci_dev *hdev) if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags)) settings |= MGMT_SETTING_HS; + if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) + settings |= MGMT_SETTING_ADVERTISING; + return settings; } @@ -1411,6 +1416,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) changed = true; } + if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + changed = true; + } + err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev); if (err < 0) goto unlock; @@ -1442,6 +1452,9 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_req_init(&req, hdev); + if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val) + hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); + hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), &hci_cp); @@ -3517,6 +3530,12 @@ static int powered_update_hci(struct hci_dev *hdev) sizeof(cp), &cp); } + if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + u8 adv = 0x01; + + hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); + } + link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, -- cgit From 4375f1037d52602413142e290608d0d84671ad36 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 25 Sep 2013 13:26:10 +0300 Subject: Bluetooth: Add new mgmt_set_advertising command This patch adds a new mgmt command for enabling and disabling LE advertising. The command depends on the LE setting being enabled first and will return a "rejected" response otherwise. The patch also adds safeguards so that there will ever only be one set_le or set_advertising command pending per adapter. The response handling and new_settings event sending is done in an asynchronous request callback, meaning raw HCI access from user space to enable advertising (e.g. hciconfig leadv) will not trigger the new_settings event. This is intentional since trying to support mixed raw HCI and mgmt access would mean adding extra state tracking or new helper functions, essentially negating the benefit of using the asynchronous request framework. The HCI_LE_ENABLED and HCI_LE_PERIPHERAL flags however are updated correctly even with raw HCI access so this will not completely break subsequent access over mgmt. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/mgmt.h | 2 + net/bluetooth/mgmt.c | 97 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 6cc72b69e014..421d7633a91f 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -352,6 +352,8 @@ struct mgmt_cp_set_device_id { } __packed; #define MGMT_SET_DEVICE_ID_SIZE 8 +#define MGMT_OP_SET_ADVERTISING 0x0029 + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9a2faa310b7c..1b5b10fab545 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -76,6 +76,7 @@ static const u16 mgmt_commands[] = { MGMT_OP_BLOCK_DEVICE, MGMT_OP_UNBLOCK_DEVICE, MGMT_OP_SET_DEVICE_ID, + MGMT_OP_SET_ADVERTISING, }; static const u16 mgmt_events[] = { @@ -1431,7 +1432,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) goto unlock; } - if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) { + if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) || + mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, MGMT_STATUS_BUSY); goto unlock; @@ -3136,6 +3138,98 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, return err; } +static void set_advertising_complete(struct hci_dev *hdev, u8 status) +{ + struct cmd_lookup match = { NULL, hdev }; + + if (status) { + u8 mgmt_err = mgmt_status(status); + + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, + cmd_status_rsp, &mgmt_err); + return; + } + + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, + &match); + + new_settings(hdev, match.sk); + + if (match.sk) + sock_put(match.sk); +} + +static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) +{ + struct mgmt_mode *cp = data; + struct pending_cmd *cmd; + struct hci_request req; + u8 val, enabled; + int err; + + BT_DBG("request for %s", hdev->name); + + if (!lmp_le_capable(hdev)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, + MGMT_STATUS_NOT_SUPPORTED); + + if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, + MGMT_STATUS_REJECTED); + + if (cp->val != 0x00 && cp->val != 0x01) + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, + MGMT_STATUS_INVALID_PARAMS); + + hci_dev_lock(hdev); + + val = !!cp->val; + enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + + if (!hdev_is_powered(hdev) || val == enabled) { + bool changed = false; + + if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + changed = true; + } + + err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev); + if (err < 0) + goto unlock; + + if (changed) + err = new_settings(hdev, sk); + + goto unlock; + } + + if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) || + mgmt_pending_find(MGMT_OP_SET_LE, hdev)) { + err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, + MGMT_STATUS_BUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); + + err = hci_req_run(&req, set_advertising_complete); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); + return err; +} + static void fast_connectable_complete(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; @@ -3347,6 +3441,7 @@ static const struct mgmt_handler { { block_device, false, MGMT_BLOCK_DEVICE_SIZE }, { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE }, { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE }, + { set_advertising, false, MGMT_SETTING_SIZE }, }; -- cgit From a895c28a1f5d761679cb229b19fb08ca2067211e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 3 Sep 2013 13:31:05 -0700 Subject: PCI: Fix comment typo, remove unnecessary !! in pci_is_pcie() Use normal kernel-doc "Returns:" instead of "retrun" Assignment to bool is always 1 or 0 so the !! isn't necessary. Signed-off-by: Joe Perches Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/pci.h b/include/linux/pci.h index da172f956ad6..ee0f3b60af22 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1749,11 +1749,11 @@ static inline int pci_pcie_cap(struct pci_dev *dev) * pci_is_pcie - check if the PCI device is PCI Express capable * @dev: PCI device * - * Retrun true if the PCI device is PCI Express capable, false otherwise. + * Returns: true if the PCI device is PCI Express capable, false otherwise. */ static inline bool pci_is_pcie(struct pci_dev *dev) { - return !!pci_pcie_cap(dev); + return pci_pcie_cap(dev); } /** -- cgit From 115e3bc5e23e7ec3c85a2014bfa96c0ddd036083 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 3 Sep 2013 10:02:09 +0800 Subject: PCI: Remove unused "is_pcie" from pci_dev structure No one uses "is_pcie" now; remove this obsolete member. Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 1 - include/linux/pci.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'include') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7ef0f868b3e0..2372babe2fc5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -984,7 +984,6 @@ void set_pcie_port_type(struct pci_dev *pdev) pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!pos) return; - pdev->is_pcie = 1; pdev->pcie_cap = pos; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); pdev->pcie_flags_reg = reg16; diff --git a/include/linux/pci.h b/include/linux/pci.h index ee0f3b60af22..197e2d21f2cb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -330,8 +330,6 @@ struct pci_dev { unsigned int msix_enabled:1; unsigned int ari_enabled:1; /* ARI forwarding */ unsigned int is_managed:1; - unsigned int is_pcie:1; /* Obsolete. Will be removed. - Use pci_is_pcie() instead */ unsigned int needs_freset:1; /* Dev requires fundamental reset */ unsigned int state_saved:1; unsigned int is_physfn:1; -- cgit From 77a0dfcd8a4d9a93a21c8be56eaeb65cd69b351d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Sep 2013 15:14:57 -0600 Subject: PCI: Document reason for using pci_is_root_bus() Some code assumes "bus->self == NULL" means the bus is a root bus. This adds a comment explaining why this is incorrect ("virtual" buses added for SR-IOV have "bus->self == NULL" but are not root buses). No functional change. Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/pci.h b/include/linux/pci.h index 197e2d21f2cb..d3a888ae4b2e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -470,6 +470,10 @@ struct pci_bus { /* * Returns true if the pci bus is root (behind host-pci bridge), * false otherwise + * + * Some code assumes that "bus->self == NULL" means that bus is a root bus. + * This is incorrect because "virtual" buses added for SR-IOV (via + * virtfn_add_bus()) have "bus->self == NULL" but are not root buses. */ static inline bool pci_is_root_bus(struct pci_bus *pbus) { -- cgit From 7868943db1668fba898cf71bed1506c19d6958aa Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 16 Sep 2013 23:47:28 +0800 Subject: usb: core: implement AMD remote wakeup quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following patch is required to resolve remote wake issues with certain devices. Issue description: If the remote wake is issued from the device in a specific timing condition while the system is entering sleep state then it may cause system to auto wake on subsequent sleep cycle. Root cause: Host controller rebroadcasts the Resume signal > 100 µseconds after receiving the original resume event from the device. For proper function, some devices may require the rebroadcast of resume event within the USB spec of 100µS. Workaroud: 1. Filter the AMD platforms with Yangtze chipset, then judge of all the usb devices are mouse or not. And get out the port id which attached a mouse with Pixart controller. 2. Then reset the port which attached issue device during system resume from S3. [Q] Why the special devices are only mice? Would high speed devices such as 3G modem or USB Bluetooth adapter trigger this issue? - Current this sensitivity is only confined to devices that use Pixart controllers. This controller is designed for use with LS mouse devices only. We have not observed any other devices failing. There may be a small risk for other devices also but this patch (reset device in resume phase) will cover the cases if required. [Q] Shouldn’t the resume signal be sent within 100 us for every device? - The Host controller may not send the resume signal within 100us, this our host controller specification change. This is why we require the patch to prevent side effects on certain known devices. [Q] Why would clicking mouse INTENSELY to wake the system up trigger this issue? - This behavior is specific to the devices that use Pixart controller. It is timing dependent on when the resume event is triggered during the sleep state. [Q] Is it a host controller issue or mouse? - It is the host controller behavior during resume that triggers the device incorrect behavior on the next resume. This patch sets USB_QUIRK_RESET_RESUME flag for these Pixart-based mice when they attached to platforms with AMD Yangtze chipset. Signed-off-by: Huang Rui Suggested-by: Alan Stern Acked-by: Alan Stern Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 3 +++ drivers/usb/core/quirks.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/usb/host/pci-quirks.c | 12 ++++++++++++ include/linux/usb/hcd.h | 3 +++ 4 files changed, 55 insertions(+) (limited to 'include') diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index b9d3c43e3859..dfe9d0f22978 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -215,6 +215,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) goto disable_pci; } + hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) && + driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0; + if (driver->flags & HCD_MEMORY) { /* EHCI, OHCI */ hcd->rsrc_start = pci_resource_start(dev, 0); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5b44cd47da5b..74d18c8b7a88 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -13,6 +13,7 @@ #include #include +#include #include "usb.h" /* Lists of quirky USB devices, split in device quirks and interface quirks. @@ -155,6 +156,21 @@ static const struct usb_device_id usb_interface_quirk_list[] = { { } /* terminating entry must be last */ }; +static const struct usb_device_id usb_amd_resume_quirk_list[] = { + /* Lenovo Mouse with Pixart controller */ + { USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* Pixart Mouse */ + { USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* Logitech Optical Mouse M90/M100 */ + { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, + + { } /* terminating entry must be last */ +}; + static bool usb_match_any_interface(struct usb_device *udev, const struct usb_device_id *id) { @@ -181,6 +197,18 @@ static bool usb_match_any_interface(struct usb_device *udev, return false; } +int usb_amd_resume_quirk(struct usb_device *udev) +{ + struct usb_hcd *hcd; + + hcd = bus_to_hcd(udev->bus); + /* The device should be attached directly to root hub */ + if (udev->level == 1 && hcd->amd_resume_bug == 1) + return 1; + + return 0; +} + static u32 __usb_detect_quirks(struct usb_device *udev, const struct usb_device_id *id) { @@ -206,6 +234,15 @@ static u32 __usb_detect_quirks(struct usb_device *udev, void usb_detect_quirks(struct usb_device *udev) { udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); + + /* + * Pixart-based mice would trigger remote wakeup issue on AMD + * Yangtze chipset, so set them as RESET_RESUME flag. + */ + if (usb_amd_resume_quirk(udev)) + udev->quirks |= __usb_detect_quirks(udev, + usb_amd_resume_quirk_list); + if (udev->quirks) dev_dbg(&udev->dev, "USB quirks for this device: %x\n", udev->quirks); diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index d1e68d887f6e..17eb1916e65e 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -250,6 +250,18 @@ commit: } EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); +int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev) +{ + /* Make sure amd chipset type has already been initialized */ + usb_amd_find_chipset_info(); + if (amd_chipset.sb_type.gen != AMD_CHIPSET_YANGTZE) + return 0; + + dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n"); + return 1; +} +EXPORT_SYMBOL_GPL(usb_hcd_amd_remote_wakeup_quirk); + /* * The hardware normally enables the A-link power management feature, which * lets the system lower the power consumption in idle states. diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 8c865134c881..fc64b6825f5e 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -141,6 +141,7 @@ struct usb_hcd { unsigned wireless:1; /* Wireless USB HCD */ unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ + unsigned amd_resume_bug:1; /* AMD remote wakeup quirk */ unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ @@ -435,6 +436,8 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev, extern void usb_hcd_pci_remove(struct pci_dev *dev); extern void usb_hcd_pci_shutdown(struct pci_dev *dev); +extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); + #ifdef CONFIG_PM extern const struct dev_pm_ops usb_hcd_pci_pm_ops; #endif -- cgit From 469d6d0631386e6865a30c9ded87a5cc0fdf8e2e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 18 Sep 2013 20:47:06 -0400 Subject: tty: Remove unused drop() method from tty_port interface Although originally conceived as a hook for port drivers to know when a port reference is dropped, no driver uses this method. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 6 +----- include/linux/tty.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 7efbca474689..c94d2349dd06 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -484,8 +484,6 @@ int tty_port_close_start(struct tty_port *port, if (port->count) { spin_unlock_irqrestore(&port->lock, flags); - if (port->ops->drop) - port->ops->drop(port); return 0; } set_bit(ASYNCB_CLOSING, &port->flags); @@ -504,9 +502,7 @@ int tty_port_close_start(struct tty_port *port, /* Flush the ldisc buffering */ tty_ldisc_flush(tty); - /* Don't call port->drop for the last reference. Callers will want - to drop the last active reference in ->shutdown() or the tty - shutdown path */ + /* Report to caller this is the last port reference */ return 1; } EXPORT_SYMBOL(tty_port_close_start); diff --git a/include/linux/tty.h b/include/linux/tty.h index 64f864651d86..2f47989d8288 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -180,7 +180,6 @@ struct tty_port_operations { IFF the port was initialized. Do not use to free resources. Called under the port mutex to serialize against activate/shutdowns */ void (*shutdown)(struct tty_port *port); - void (*drop)(struct tty_port *port); /* Called under the port mutex from tty_port_open, serialized using the port mutex */ /* FIXME: long term getting the tty argument *out* of this would be -- cgit From b83e867026caedd6d67fccfbe6e9a621edd79b21 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Thu, 19 Sep 2013 18:21:36 -0700 Subject: mmc: core: remove dead function mmc_try_claim_host cscope says there are no callers for mmc_try_claim_host in the kernel. No reason to keep it. Signed-off-by: Grant Grundler Acked-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 25 ------------------------- include/linux/mmc/core.h | 1 - 2 files changed, 26 deletions(-) (limited to 'include') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bf18b6bfce48..006ead2fb701 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -917,31 +917,6 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) EXPORT_SYMBOL(__mmc_claim_host); -/** - * mmc_try_claim_host - try exclusively to claim a host - * @host: mmc host to claim - * - * Returns %1 if the host is claimed, %0 otherwise. - */ -int mmc_try_claim_host(struct mmc_host *host) -{ - int claimed_host = 0; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - if (!host->claimed || host->claimer == current) { - host->claimed = 1; - host->claimer = current; - host->claim_cnt += 1; - claimed_host = 1; - } - spin_unlock_irqrestore(&host->lock, flags); - if (host->ops->enable && claimed_host && host->claim_cnt == 1) - host->ops->enable(host); - return claimed_host; -} -EXPORT_SYMBOL(mmc_try_claim_host); - /** * mmc_release_host - release a host * @host: mmc host to release diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index da51bec578c3..a00fc49c8434 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -188,7 +188,6 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); -extern int mmc_try_claim_host(struct mmc_host *host); extern void mmc_get_card(struct mmc_card *card); extern void mmc_put_card(struct mmc_card *card); -- cgit From 524268990e54dab9bd71a984b70c13ce0eb1c525 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Sat, 31 Aug 2013 00:13:42 +0900 Subject: mmc: dw_mmc: adjust the fifoth with block size This change helps to choose msize, rx_watermark and tx_watermark depending on block size for IDMAC mode. For SDIO block size can be variable, so if these values are set incorrectly, card clock may stop. Signed-off-by: Seungwon Jeon Tested-by: Alim Akhtar Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++-- drivers/mmc/host/dw_mmc.h | 4 +++ include/linux/mmc/dw_mmc.h | 1 + 3 files changed, 76 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 50da6e330a15..acefdeb2465b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -529,6 +529,47 @@ static void dw_mci_post_req(struct mmc_host *mmc, data->host_cookie = 0; } +static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) +{ +#ifdef CONFIG_MMC_DW_IDMAC + unsigned int blksz = data->blksz; + const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; + u32 fifo_width = 1 << host->data_shift; + u32 blksz_depth = blksz / fifo_width, fifoth_val; + u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; + int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; + + tx_wmark = (host->fifo_depth) / 2; + tx_wmark_invers = host->fifo_depth - tx_wmark; + + /* + * MSIZE is '1', + * if blksz is not a multiple of the FIFO width + */ + if (blksz % fifo_width) { + msize = 0; + rx_wmark = 1; + goto done; + } + + do { + if (!((blksz_depth % mszs[idx]) || + (tx_wmark_invers % mszs[idx]))) { + msize = idx; + rx_wmark = mszs[idx] - 1; + break; + } + } while (--idx > 0); + /* + * If idx is '0', it won't be tried + * Thus, initial values are uesed + */ +done: + fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); + mci_writel(host, FIFOTH, fifoth_val); +#endif +} + static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) { int sg_len; @@ -553,6 +594,14 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, sg_len); + /* + * Decide the MSIZE and RX/TX Watermark. + * If current block size is same with previous size, + * no need to update fifoth. + */ + if (host->prev_blksz != data->blksz) + dw_mci_adjust_fifoth(host, data); + /* Enable the DMA interface */ temp = mci_readl(host, CTRL); temp |= SDMMC_CTRL_DMA_ENABLE; @@ -603,6 +652,21 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) temp = mci_readl(host, CTRL); temp &= ~SDMMC_CTRL_DMA_ENABLE; mci_writel(host, CTRL, temp); + + /* + * Use the initial fifoth_val for PIO mode. + * If next issued data may be transfered by DMA mode, + * prev_blksz should be invalidated. + */ + mci_writel(host, FIFOTH, host->fifoth_val); + host->prev_blksz = 0; + } else { + /* + * Keep the current block size. + * It will be used to decide whether to update + * fifoth register next time. + */ + host->prev_blksz = data->blksz; } } @@ -2368,8 +2432,8 @@ int dw_mci_probe(struct dw_mci *host) fifo_size = host->pdata->fifo_depth; } host->fifo_depth = fifo_size; - host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | - ((fifo_size/2) << 0)); + host->fifoth_val = + SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); mci_writel(host, FIFOTH, host->fifoth_val); /* disable clock to CIU */ @@ -2552,8 +2616,12 @@ int dw_mci_resume(struct dw_mci *host) if (host->use_dma && host->dma_ops->init) host->dma_ops->init(host); - /* Restore the old value at FIFOTH register */ + /* + * Restore the initial value at FIFOTH register + * And Invalidate the prev_blksz with zero + */ mci_writel(host, FIFOTH, host->fifoth_val); + host->prev_blksz = 0; /* Put in max timeout */ mci_writel(host, TMOUT, 0xFFFFFFFF); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index b281fdc6835f..a0f2f8d35f5d 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -128,6 +128,10 @@ #define SDMMC_CMD_INDX(n) ((n) & 0x1F) /* Status register defines */ #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) +/* FIFOTH register defines */ +#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ + ((r) & 0xFFF) << 16 | \ + ((t) & 0xFFF)) /* Internal DMAC interrupt defines */ #define SDMMC_IDMAC_INT_AI BIT(9) #define SDMMC_IDMAC_INT_NI BIT(8) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 198f0fa44e9f..4ec9dcc9460e 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -129,6 +129,7 @@ struct dw_mci { struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; + unsigned int prev_blksz; struct workqueue_struct *card_workqueue; /* DMA interface members*/ -- cgit From f1d2736c815629f3b43d8eebf73a81b581438e65 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Sat, 31 Aug 2013 00:13:55 +0900 Subject: mmc: dw_mmc: control card read threshold Card Read Threshold should be ensured that the card clock does not stop in the middle of a block of data being transferred from the card to the Host. Specially, clock stop is allowed in fast transfer such as HS200 or SDR104 mode. And so, it should be enabled. Signed-off-by: Seungwon Jeon Tested-by: Alim Akhtar Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 38 ++++++++++++++++++++++++++++++++++++-- drivers/mmc/host/dw_mmc.h | 3 +++ include/linux/mmc/dw_mmc.h | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index acefdeb2465b..8eb37983a72a 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -570,6 +570,37 @@ done: #endif } +static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) +{ + unsigned int blksz = data->blksz; + u32 blksz_depth, fifo_depth; + u16 thld_size; + + WARN_ON(!(data->flags & MMC_DATA_READ)); + + if (host->timing != MMC_TIMING_MMC_HS200 && + host->timing != MMC_TIMING_UHS_SDR104) + goto disable; + + blksz_depth = blksz / (1 << host->data_shift); + fifo_depth = host->fifo_depth; + + if (blksz_depth > fifo_depth) + goto disable; + + /* + * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz' + * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz + * Currently just choose blksz. + */ + thld_size = blksz; + mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1)); + return; + +disable: + mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0)); +} + static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) { int sg_len; @@ -627,10 +658,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) host->sg = NULL; host->data = data; - if (data->flags & MMC_DATA_READ) + if (data->flags & MMC_DATA_READ) { host->dir_status = DW_MCI_RECV_STATUS; - else + dw_mci_ctrl_rd_thld(host, data); + } else { host->dir_status = DW_MCI_SEND_STATUS; + } if (dw_mci_submit_data_dma(host, data)) { int flags = SG_MITER_ATOMIC; @@ -877,6 +910,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) regs &= ~((0x1 << slot->id) << 16); mci_writel(slot->host, UHS_REG, regs); + slot->host->timing = ios->timing; /* * Use mirror of ios->clock to prevent race with mmc diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index a0f2f8d35f5d..6bf24ab917e6 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -53,6 +53,7 @@ #define SDMMC_IDINTEN 0x090 #define SDMMC_DSCADDR 0x094 #define SDMMC_BUFADDR 0x098 +#define SDMMC_CDTHRCTL 0x100 #define SDMMC_DATA(x) (x) /* @@ -146,6 +147,8 @@ #define SDMMC_IDMAC_SWRESET BIT(0) /* Version ID register define */ #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) +/* Card read threshold */ +#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x)) /* Register access macros */ #define mci_readl(dev, reg) \ diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 4ec9dcc9460e..a829f7ee28c8 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -130,6 +130,7 @@ struct dw_mci { struct mmc_command *cmd; struct mmc_data *data; unsigned int prev_blksz; + unsigned char timing; struct workqueue_struct *card_workqueue; /* DMA interface members*/ -- cgit From 90c2143a8f6d0cd1dbae1ea32fcd1befb81e4b0d Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Sat, 31 Aug 2013 00:14:05 +0900 Subject: mmc: dw_mmc: guarantee stop-abort cmd in data errors In error cases, DTO interrupt may or may not be generated depending on remained data. Stop/Abort command ensures DTO generation for that situation. Currently if 'stop' field of data is empty, there is no stop/abort command. So, it could hang waiting DTO. This change reinforces these cases. Signed-off-by: Seungwon Jeon Tested-by: Alim Akhtar Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 84 +++++++++++++++++++++++++++++++++++----------- include/linux/mmc/dw_mmc.h | 2 ++ 2 files changed, 66 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 649127e71894..b4328ad59cf0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -246,10 +247,15 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr = cmd->opcode; - if (cmdr == MMC_STOP_TRANSMISSION) + if (cmd->opcode == MMC_STOP_TRANSMISSION || + cmd->opcode == MMC_GO_IDLE_STATE || + cmd->opcode == MMC_GO_INACTIVE_STATE || + (cmd->opcode == SD_IO_RW_DIRECT && + ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) cmdr |= SDMMC_CMD_STOP; else - cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd->opcode != MMC_SEND_STATUS && cmd->data) + cmdr |= SDMMC_CMD_PRV_DAT_WAIT; if (cmd->flags & MMC_RSP_PRESENT) { /* We expect a response, so set this bit */ @@ -276,6 +282,40 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) return cmdr; } +static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) +{ + struct mmc_command *stop; + u32 cmdr; + + if (!cmd->data) + return 0; + + stop = &host->stop_abort; + cmdr = cmd->opcode; + memset(stop, 0, sizeof(struct mmc_command)); + + if (cmdr == MMC_READ_SINGLE_BLOCK || + cmdr == MMC_READ_MULTIPLE_BLOCK || + cmdr == MMC_WRITE_BLOCK || + cmdr == MMC_WRITE_MULTIPLE_BLOCK) { + stop->opcode = MMC_STOP_TRANSMISSION; + stop->arg = 0; + stop->flags = MMC_RSP_R1B | MMC_CMD_AC; + } else if (cmdr == SD_IO_RW_EXTENDED) { + stop->opcode = SD_IO_RW_DIRECT; + stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | + ((cmd->arg >> 28) & 0x7); + stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; + } else { + return 0; + } + + cmdr = stop->opcode | SDMMC_CMD_STOP | + SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP; + + return cmdr; +} + static void dw_mci_start_command(struct dw_mci *host, struct mmc_command *cmd, u32 cmd_flags) { @@ -290,9 +330,10 @@ static void dw_mci_start_command(struct dw_mci *host, mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); } -static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) +static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data) { - dw_mci_start_command(host, data->stop, host->stop_cmdr); + struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; + dw_mci_start_command(host, stop, host->stop_cmdr); } /* DMA interface functions */ @@ -828,6 +869,8 @@ static void __dw_mci_start_request(struct dw_mci *host, if (mrq->stop) host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); + else + host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd); } static void dw_mci_start_request(struct dw_mci *host, @@ -1190,13 +1233,9 @@ static void dw_mci_tasklet_func(unsigned long priv) if (cmd->data && cmd->error) { dw_mci_stop_dma(host); - if (data->stop) { - send_stop_cmd(host, data); - state = STATE_SENDING_STOP; - break; - } else { - host->data = NULL; - } + send_stop_abort(host, data); + state = STATE_SENDING_STOP; + break; } if (!host->mrq->data || cmd->error) { @@ -1211,8 +1250,7 @@ static void dw_mci_tasklet_func(unsigned long priv) if (test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events)) { dw_mci_stop_dma(host); - if (data->stop) - send_stop_cmd(host, data); + send_stop_abort(host, data); state = STATE_DATA_ERROR; break; } @@ -1272,7 +1310,7 @@ static void dw_mci_tasklet_func(unsigned long priv) data->error = 0; } - if (!data->stop) { + if (!data->stop && !data->error) { dw_mci_request_end(host, host->mrq); goto unlock; } @@ -1284,8 +1322,10 @@ static void dw_mci_tasklet_func(unsigned long priv) } prev_state = state = STATE_SENDING_STOP; - if (!data->error) - send_stop_cmd(host, data); + if (data->stop && !data->error) { + /* stop command for open-ended transfer*/ + send_stop_abort(host, data); + } /* fall through */ case STATE_SENDING_STOP: @@ -1304,7 +1344,12 @@ static void dw_mci_tasklet_func(unsigned long priv) host->cmd = NULL; host->data = NULL; - dw_mci_command_complete(host, host->mrq->stop); + + if (host->mrq->stop) + dw_mci_command_complete(host, host->mrq->stop); + else + host->cmd_status = 0; + dw_mci_request_end(host, host->mrq); goto unlock; @@ -1888,11 +1933,10 @@ static void dw_mci_work_routine_card(struct work_struct *work) case STATE_DATA_ERROR: if (mrq->data->error == -EINPROGRESS) mrq->data->error = -ENOMEDIUM; - if (!mrq->stop) - break; /* fall through */ case STATE_SENDING_STOP: - mrq->stop->error = -ENOMEDIUM; + if (mrq->stop) + mrq->stop->error = -ENOMEDIUM; break; } diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index a829f7ee28c8..6ce7d2cd3c7a 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -15,6 +15,7 @@ #define LINUX_MMC_DW_MMC_H #include +#include #define MAX_MCI_SLOTS 2 @@ -129,6 +130,7 @@ struct dw_mci { struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; + struct mmc_command stop_abort; unsigned int prev_blksz; unsigned char timing; struct workqueue_struct *card_workqueue; -- cgit From 71ef1ea418ee45a4f939d53a02410627b394c336 Mon Sep 17 00:00:00 2001 From: Jackey Shen Date: Fri, 17 May 2013 17:17:43 +0800 Subject: mmc: core: clean up duplicate macros Clean up the duplicate macros: mmc_sd_card_uhs -> mmc_card_uhs mmc_sd_card_set_uhs -> mmc_card_set_uhs Signed-off-by: Jackey Shen Signed-off-by: Chris Ball --- drivers/mmc/core/bus.c | 2 +- drivers/mmc/host/rtsx_pci_sdmmc.c | 2 +- include/linux/mmc/card.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 704bf66f5873..cdca8a70da38 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -340,7 +340,7 @@ int mmc_add_card(struct mmc_card *card) break; } - if (mmc_sd_card_uhs(card) && + if (mmc_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 375a880e0c5f..e2ab12473f97 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -364,7 +364,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) struct mmc_host *mmc = host->mmc; struct mmc_card *card = mmc->card; struct mmc_data *data = mrq->data; - int uhs = mmc_sd_card_uhs(card); + int uhs = mmc_card_uhs(card); int read = (data->flags & MMC_DATA_READ) ? 1 : 0; u8 cfg2, trans_mode; int err; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 842de3e21e70..f42cdbd8ac21 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -420,7 +420,6 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) #define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) -#define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) @@ -432,7 +431,6 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) #define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) -#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) -- cgit From 28061758dc83df445a05af347b5ce55ccd968c03 Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 13 Aug 2013 13:43:26 +0100 Subject: ARM/ARM64: arch_timer: add macros for bits in control register Add macros to describe the bitfields in the ARM architected timer control register to make code easy to understand. Reviewed-by: Lorenzo Pieralisi Reviewed-by: Will Deacon Acked-by: Catalin Marinas Acked-by: Olof Johansson Signed-off-by: Sudeep KarkadaNagesha --- arch/arm/include/asm/arch_timer.h | 9 +++++++-- arch/arm64/include/asm/arch_timer.h | 12 ++++++++---- include/clocksource/arm_arch_timer.h | 8 ++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 5665134bfa3e..d57e04de8e8c 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -93,8 +93,13 @@ static inline void arch_counter_set_user_access(void) asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); - /* disable user access to everything */ - cntkctl &= ~((3 << 8) | (7 << 0)); + /* Disable user access to both physical/virtual counters/timers */ + /* Also disable virtual event stream */ + cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN + | ARCH_TIMER_USR_VT_ACCESS_EN + | ARCH_TIMER_VIRT_EVT_EN + | ARCH_TIMER_USR_VCT_ACCESS_EN + | ARCH_TIMER_USR_PCT_ACCESS_EN); asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); } diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index c9f1d2816c2b..2b9722f42729 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -96,12 +96,16 @@ static inline void arch_counter_set_user_access(void) { u32 cntkctl; - /* Disable user access to the timers and the physical counter. */ asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); - cntkctl &= ~((3 << 8) | (1 << 0)); - /* Enable user access to the virtual counter and frequency. */ - cntkctl |= (1 << 1); + /* Disable user access to the timers and the physical counter */ + cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN + | ARCH_TIMER_USR_VT_ACCESS_EN + | ARCH_TIMER_USR_PCT_ACCESS_EN); + + /* Enable user access to the virtual counter */ + cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); } diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index 93b7f96f9c59..8707dae4cee2 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -33,6 +33,14 @@ enum arch_timer_reg { #define ARCH_TIMER_MEM_PHYS_ACCESS 2 #define ARCH_TIMER_MEM_VIRT_ACCESS 3 +#define ARCH_TIMER_USR_PCT_ACCESS_EN (1 << 0) /* physical counter */ +#define ARCH_TIMER_USR_VCT_ACCESS_EN (1 << 1) /* virtual counter */ +#define ARCH_TIMER_VIRT_EVT_EN (1 << 2) +#define ARCH_TIMER_EVT_TRIGGER_SHIFT (4) +#define ARCH_TIMER_EVT_TRIGGER_MASK (0xF << ARCH_TIMER_EVT_TRIGGER_SHIFT) +#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */ +#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */ + #ifdef CONFIG_ARM_ARCH_TIMER extern u32 arch_timer_get_rate(void); -- cgit From 037f637767a82907efedda78d3ff405c34020075 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 23 Aug 2013 15:32:29 +0100 Subject: drivers: clocksource: add support for ARM architected timer event stream The ARM architected timer can generate events (used for waking up CPUs executing the wfe instruction) at a frequency represented as a power-of-2 divisor of the clock rate. An event stream might be used: - To implement wfe-based timeouts for userspace locking implementations. - To impose a timeout on a wfe for safeguarding against any programming error in case an expected event is not generated. This patch computes the event stream frequency aiming for a period of 100us between events. It uses ARM/ARM64 specific backends to configure and enable the event stream. Cc: Lorenzo Pieralisi Reviewed-by: Catalin Marinas Acked-by: Olof Johansson Signed-off-by: Will Deacon [sudeep: moving ARM/ARM64 changes into separate patches and adding Kconfig option] Signed-off-by: Sudeep KarkadaNagesha --- drivers/clocksource/Kconfig | 15 +++++++++++++++ drivers/clocksource/arm_arch_timer.c | 15 +++++++++++++++ include/clocksource/arm_arch_timer.h | 2 ++ 3 files changed, 32 insertions(+) (limited to 'include') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 41c69469ce20..559d80335446 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -74,6 +74,21 @@ config ARM_ARCH_TIMER bool select CLKSRC_OF if OF +config ARM_ARCH_TIMER_EVTSTREAM + bool "Support for ARM architected timer event stream generation" + default y if ARM_ARCH_TIMER + help + This option enables support for event stream generation based on + the ARM architected timer. It is used for waking up CPUs executing + the wfe instruction at a frequency represented as a power-of-2 + divisor of the clock rate. + The main use of the event stream is wfe-based timeouts of userspace + locking implementations. It might also be useful for imposing timeout + on wfe to safeguard against any programming errors in case an expected + event is not generated. + This must be disabled for hardware validation purposes to detect any + hardware anomalies of missing events. + config ARM_GLOBAL_TIMER bool select CLKSRC_OF if OF diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index fbd9ccd5e114..105f8ffa66a8 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -294,6 +294,19 @@ static void __arch_timer_setup(unsigned type, clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); } +static void arch_timer_configure_evtstream(void) +{ + int evt_stream_div, pos; + + /* Find the closest power of two to the divisor */ + evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ; + pos = fls(evt_stream_div); + if (pos > 1 && !(evt_stream_div & (1 << (pos - 2)))) + pos--; + /* enable event stream */ + arch_timer_evtstrm_enable(min(pos, 15)); +} + static int arch_timer_setup(struct clock_event_device *clk) { __arch_timer_setup(ARCH_CP15_TIMER, clk); @@ -307,6 +320,8 @@ static int arch_timer_setup(struct clock_event_device *clk) } arch_counter_set_user_access(); + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM)) + arch_timer_configure_evtstream(); return 0; } diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index 8707dae4cee2..6d26b40cbf5d 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -41,6 +41,8 @@ enum arch_timer_reg { #define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */ #define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */ +#define ARCH_TIMER_EVT_STREAM_FREQ 10000 /* 100us */ + #ifdef CONFIG_ARM_ARCH_TIMER extern u32 arch_timer_get_rate(void); -- cgit From b0f4fe1edf6abbc81500d661f730cebd653a838c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 6 Jun 2013 11:57:27 +0100 Subject: mfd: dbx500-prcmu: Correctly reorder PRCMU clock identifiers ... as stipulated by the Hardware Specification document. Acked-by: Samuel Ortiz Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- include/linux/mfd/dbx500-prcmu.h | 135 ++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index ca0790fba2f5..87667d48602b 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -97,70 +97,77 @@ enum prcmu_wakeup_index { /* * Clock identifiers. */ -enum prcmu_clock { - PRCMU_SGACLK, - PRCMU_UARTCLK, - PRCMU_MSP02CLK, - PRCMU_MSP1CLK, - PRCMU_I2CCLK, - PRCMU_SDMMCCLK, - PRCMU_SPARE1CLK, - PRCMU_SLIMCLK, - PRCMU_PER1CLK, - PRCMU_PER2CLK, - PRCMU_PER3CLK, - PRCMU_PER5CLK, - PRCMU_PER6CLK, - PRCMU_PER7CLK, - PRCMU_LCDCLK, - PRCMU_BMLCLK, - PRCMU_HSITXCLK, - PRCMU_HSIRXCLK, - PRCMU_HDMICLK, - PRCMU_APEATCLK, - PRCMU_APETRACECLK, - PRCMU_MCDECLK, - PRCMU_IPI2CCLK, - PRCMU_DSIALTCLK, - PRCMU_DMACLK, - PRCMU_B2R2CLK, - PRCMU_TVCLK, - PRCMU_SSPCLK, - PRCMU_RNGCLK, - PRCMU_UICCCLK, - PRCMU_PWMCLK, - PRCMU_IRDACLK, - PRCMU_IRRCCLK, - PRCMU_SIACLK, - PRCMU_SVACLK, - PRCMU_ACLK, - PRCMU_HVACLK, /* Ux540 only */ - PRCMU_G1CLK, /* Ux540 only */ - PRCMU_SDMMCHCLK, - PRCMU_CAMCLK, - PRCMU_BML8580CLK, - PRCMU_NUM_REG_CLOCKS, - PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, - PRCMU_CDCLK, - PRCMU_TIMCLK, - PRCMU_PLLSOC0, - PRCMU_PLLSOC1, - PRCMU_ARMSS, - PRCMU_PLLDDR, - PRCMU_PLLDSI, - PRCMU_DSI0CLK, - PRCMU_DSI1CLK, - PRCMU_DSI0ESCCLK, - PRCMU_DSI1ESCCLK, - PRCMU_DSI2ESCCLK, - /* LCD DSI PLL - Ux540 only */ - PRCMU_PLLDSI_LCD, - PRCMU_DSI0CLK_LCD, - PRCMU_DSI1CLK_LCD, - PRCMU_DSI0ESCCLK_LCD, - PRCMU_DSI1ESCCLK_LCD, - PRCMU_DSI2ESCCLK_LCD, -}; +#define ARMCLK 0 +#define PRCMU_ACLK 1 +#define PRCMU_SVAMMCSPCLK 2 +#define PRCMU_SDMMCHCLK 2 /* DBx540 only. */ +#define PRCMU_SIACLK 3 +#define PRCMU_SIAMMDSPCLK 3 /* DBx540 only. */ +#define PRCMU_SGACLK 4 +#define PRCMU_UARTCLK 5 +#define PRCMU_MSP02CLK 6 +#define PRCMU_MSP1CLK 7 +#define PRCMU_I2CCLK 8 +#define PRCMU_SDMMCCLK 9 +#define PRCMU_SLIMCLK 10 +#define PRCMU_CAMCLK 10 /* DBx540 only. */ +#define PRCMU_PER1CLK 11 +#define PRCMU_PER2CLK 12 +#define PRCMU_PER3CLK 13 +#define PRCMU_PER5CLK 14 +#define PRCMU_PER6CLK 15 +#define PRCMU_PER7CLK 16 +#define PRCMU_LCDCLK 17 +#define PRCMU_BMLCLK 18 +#define PRCMU_HSITXCLK 19 +#define PRCMU_HSIRXCLK 20 +#define PRCMU_HDMICLK 21 +#define PRCMU_APEATCLK 22 +#define PRCMU_APETRACECLK 23 +#define PRCMU_MCDECLK 24 +#define PRCMU_IPI2CCLK 25 +#define PRCMU_DSIALTCLK 26 +#define PRCMU_DMACLK 27 +#define PRCMU_B2R2CLK 28 +#define PRCMU_TVCLK 29 +#define SPARE_UNIPROCLK 30 +#define PRCMU_SSPCLK 31 +#define PRCMU_RNGCLK 32 +#define PRCMU_UICCCLK 33 +#define PRCMU_G1CLK 34 /* DBx540 only. */ +#define PRCMU_HVACLK 35 /* DBx540 only. */ +#define PRCMU_SPARE1CLK 36 +#define PRCMU_SPARE2CLK 37 + +#define PRCMU_NUM_REG_CLOCKS 38 + +#define PRCMU_RTCCLK PRCMU_NUM_REG_CLOCKS +#define PRCMU_SYSCLK 39 +#define PRCMU_CDCLK 40 +#define PRCMU_TIMCLK 41 +#define PRCMU_PLLSOC0 42 +#define PRCMU_PLLSOC1 43 +#define PRCMU_ARMSS 44 +#define PRCMU_PLLDDR 45 +#define PRCMU_BML8580CLK 46 + +/* DSI Clocks */ +#define PRCMU_PLLDSI 47 +#define PRCMU_DSI0CLK 48 +#define PRCMU_DSI1CLK 49 +#define PRCMU_DSI0ESCCLK 50 +#define PRCMU_DSI1ESCCLK 51 +#define PRCMU_DSI2ESCCLK 52 + +/* LCD DSI PLL - Ux540 only */ +#define PRCMU_PLLDSI_LCD 53 +#define PRCMU_DSI0CLK_LCD 54 +#define PRCMU_DSI1CLK_LCD 55 +#define PRCMU_DSI0ESCCLK_LCD 56 +#define PRCMU_DSI1ESCCLK_LCD 57 +#define PRCMU_DSI2ESCCLK_LCD 58 + +#define PRCMU_NUM_CLKS 59 /** * enum prcmu_wdog_id - PRCMU watchdog IDs -- cgit From 67f13daadccebf95c04f73db7b78cead844540bd Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 6 Jun 2013 11:50:47 +0100 Subject: mfd: dbx500-prcmu: Move PRCMU numerical clock identifiers into DT include file These are required to request DBx500 PRCMU clocks from Device Tree. The numbers used are taken directly from the Hardware Specification document. We're moving them from the DBx500 PRCMU include file into the DT include directory and referencing them from the former via a #include. Acked-by: Samuel Ortiz Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- include/dt-bindings/mfd/dbx500-prcmu.h | 84 ++++++++++++++++++++++++++++++++++ include/linux/mfd/dbx500-prcmu.h | 77 +------------------------------ 2 files changed, 86 insertions(+), 75 deletions(-) create mode 100644 include/dt-bindings/mfd/dbx500-prcmu.h (limited to 'include') diff --git a/include/dt-bindings/mfd/dbx500-prcmu.h b/include/dt-bindings/mfd/dbx500-prcmu.h new file mode 100644 index 000000000000..b7ee8c909908 --- /dev/null +++ b/include/dt-bindings/mfd/dbx500-prcmu.h @@ -0,0 +1,84 @@ +/* + * This header provides constants for the PRCMU bindings. + * + */ + +#ifndef _DT_BINDINGS_MFD_PRCMU_H +#define _DT_BINDINGS_MFD_PRCMU_H + +/* + * Clock identifiers. + */ +#define ARMCLK 0 +#define PRCMU_ACLK 1 +#define PRCMU_SVAMMCSPCLK 2 +#define PRCMU_SDMMCHCLK 2 /* DBx540 only. */ +#define PRCMU_SIACLK 3 +#define PRCMU_SIAMMDSPCLK 3 /* DBx540 only. */ +#define PRCMU_SGACLK 4 +#define PRCMU_UARTCLK 5 +#define PRCMU_MSP02CLK 6 +#define PRCMU_MSP1CLK 7 +#define PRCMU_I2CCLK 8 +#define PRCMU_SDMMCCLK 9 +#define PRCMU_SLIMCLK 10 +#define PRCMU_CAMCLK 10 /* DBx540 only. */ +#define PRCMU_PER1CLK 11 +#define PRCMU_PER2CLK 12 +#define PRCMU_PER3CLK 13 +#define PRCMU_PER5CLK 14 +#define PRCMU_PER6CLK 15 +#define PRCMU_PER7CLK 16 +#define PRCMU_LCDCLK 17 +#define PRCMU_BMLCLK 18 +#define PRCMU_HSITXCLK 19 +#define PRCMU_HSIRXCLK 20 +#define PRCMU_HDMICLK 21 +#define PRCMU_APEATCLK 22 +#define PRCMU_APETRACECLK 23 +#define PRCMU_MCDECLK 24 +#define PRCMU_IPI2CCLK 25 +#define PRCMU_DSIALTCLK 26 +#define PRCMU_DMACLK 27 +#define PRCMU_B2R2CLK 28 +#define PRCMU_TVCLK 29 +#define SPARE_UNIPROCLK 30 +#define PRCMU_SSPCLK 31 +#define PRCMU_RNGCLK 32 +#define PRCMU_UICCCLK 33 +#define PRCMU_G1CLK 34 /* DBx540 only. */ +#define PRCMU_HVACLK 35 /* DBx540 only. */ +#define PRCMU_SPARE1CLK 36 +#define PRCMU_SPARE2CLK 37 + +#define PRCMU_NUM_REG_CLOCKS 38 + +#define PRCMU_RTCCLK PRCMU_NUM_REG_CLOCKS +#define PRCMU_SYSCLK 39 +#define PRCMU_CDCLK 40 +#define PRCMU_TIMCLK 41 +#define PRCMU_PLLSOC0 42 +#define PRCMU_PLLSOC1 43 +#define PRCMU_ARMSS 44 +#define PRCMU_PLLDDR 45 +#define PRCMU_BML8580CLK 46 + +/* DSI Clocks */ +#define PRCMU_PLLDSI 47 +#define PRCMU_DSI0CLK 48 +#define PRCMU_DSI1CLK 49 +#define PRCMU_DSI0ESCCLK 50 +#define PRCMU_DSI1ESCCLK 51 +#define PRCMU_DSI2ESCCLK 52 + +/* LCD DSI PLL - Ux540 only */ +#define PRCMU_PLLDSI_LCD 53 +#define PRCMU_DSI0CLK_LCD 54 +#define PRCMU_DSI1CLK_LCD 55 +#define PRCMU_DSI0ESCCLK_LCD 56 +#define PRCMU_DSI1ESCCLK_LCD 57 +#define PRCMU_DSI2ESCCLK_LCD 58 + +#define PRCMU_NUM_CLKS 59 + +#endif diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 87667d48602b..060e11256fbc 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -12,6 +12,8 @@ #include #include +#include /* For clock identifiers */ + /* Offset for the firmware version within the TCPM */ #define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4 #define DBX540_PRCMU_FW_VERSION_OFFSET 0xA8 @@ -94,81 +96,6 @@ enum prcmu_wakeup_index { #define PRCMU_CLKSRC_ARMCLKFIX 0x46 #define PRCMU_CLKSRC_HDMICLK 0x47 -/* - * Clock identifiers. - */ -#define ARMCLK 0 -#define PRCMU_ACLK 1 -#define PRCMU_SVAMMCSPCLK 2 -#define PRCMU_SDMMCHCLK 2 /* DBx540 only. */ -#define PRCMU_SIACLK 3 -#define PRCMU_SIAMMDSPCLK 3 /* DBx540 only. */ -#define PRCMU_SGACLK 4 -#define PRCMU_UARTCLK 5 -#define PRCMU_MSP02CLK 6 -#define PRCMU_MSP1CLK 7 -#define PRCMU_I2CCLK 8 -#define PRCMU_SDMMCCLK 9 -#define PRCMU_SLIMCLK 10 -#define PRCMU_CAMCLK 10 /* DBx540 only. */ -#define PRCMU_PER1CLK 11 -#define PRCMU_PER2CLK 12 -#define PRCMU_PER3CLK 13 -#define PRCMU_PER5CLK 14 -#define PRCMU_PER6CLK 15 -#define PRCMU_PER7CLK 16 -#define PRCMU_LCDCLK 17 -#define PRCMU_BMLCLK 18 -#define PRCMU_HSITXCLK 19 -#define PRCMU_HSIRXCLK 20 -#define PRCMU_HDMICLK 21 -#define PRCMU_APEATCLK 22 -#define PRCMU_APETRACECLK 23 -#define PRCMU_MCDECLK 24 -#define PRCMU_IPI2CCLK 25 -#define PRCMU_DSIALTCLK 26 -#define PRCMU_DMACLK 27 -#define PRCMU_B2R2CLK 28 -#define PRCMU_TVCLK 29 -#define SPARE_UNIPROCLK 30 -#define PRCMU_SSPCLK 31 -#define PRCMU_RNGCLK 32 -#define PRCMU_UICCCLK 33 -#define PRCMU_G1CLK 34 /* DBx540 only. */ -#define PRCMU_HVACLK 35 /* DBx540 only. */ -#define PRCMU_SPARE1CLK 36 -#define PRCMU_SPARE2CLK 37 - -#define PRCMU_NUM_REG_CLOCKS 38 - -#define PRCMU_RTCCLK PRCMU_NUM_REG_CLOCKS -#define PRCMU_SYSCLK 39 -#define PRCMU_CDCLK 40 -#define PRCMU_TIMCLK 41 -#define PRCMU_PLLSOC0 42 -#define PRCMU_PLLSOC1 43 -#define PRCMU_ARMSS 44 -#define PRCMU_PLLDDR 45 -#define PRCMU_BML8580CLK 46 - -/* DSI Clocks */ -#define PRCMU_PLLDSI 47 -#define PRCMU_DSI0CLK 48 -#define PRCMU_DSI1CLK 49 -#define PRCMU_DSI0ESCCLK 50 -#define PRCMU_DSI1ESCCLK 51 -#define PRCMU_DSI2ESCCLK 52 - -/* LCD DSI PLL - Ux540 only */ -#define PRCMU_PLLDSI_LCD 53 -#define PRCMU_DSI0CLK_LCD 54 -#define PRCMU_DSI1CLK_LCD 55 -#define PRCMU_DSI0ESCCLK_LCD 56 -#define PRCMU_DSI1ESCCLK_LCD 57 -#define PRCMU_DSI2ESCCLK_LCD 58 - -#define PRCMU_NUM_CLKS 59 - /** * enum prcmu_wdog_id - PRCMU watchdog IDs * @PRCMU_WDOG_ALL: use all timers -- cgit From 58092dc4dfde55d5824211e5aa1be47212a57f1f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 19 Aug 2013 12:23:05 +0100 Subject: mfd: dbx500: Remove any mention of the BML8580CLK The platform which it pertains to is no longer supported and is actually causing some confusion in the new common clock implementation. A recent patch removed its use in the clock driver, let's take out the definitions too. Acked-by: Samuel Ortiz Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- drivers/mfd/db8500-prcmu.c | 1 - drivers/mfd/dbx500-prcmu-regs.h | 1 - include/dt-bindings/mfd/dbx500-prcmu.h | 27 +++++++++++++-------------- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 53f371dcbb6e..b9ce60c301de 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -480,7 +480,6 @@ static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true), CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true), CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true), - CLK_MGT_ENTRY(BML8580CLK, PLL_DIV, true), CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true), CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true), CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true), diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index 4f6f0fa5d3b7..7cc32a8ff01c 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -32,7 +32,6 @@ #define PRCM_PER7CLK_MGT (0x040) #define PRCM_LCDCLK_MGT (0x044) #define PRCM_BMLCLK_MGT (0x04C) -#define PRCM_BML8580CLK_MGT (0x108) #define PRCM_HSITXCLK_MGT (0x050) #define PRCM_HSIRXCLK_MGT (0x054) #define PRCM_HDMICLK_MGT (0x058) diff --git a/include/dt-bindings/mfd/dbx500-prcmu.h b/include/dt-bindings/mfd/dbx500-prcmu.h index b7ee8c909908..552a2d174f01 100644 --- a/include/dt-bindings/mfd/dbx500-prcmu.h +++ b/include/dt-bindings/mfd/dbx500-prcmu.h @@ -61,24 +61,23 @@ #define PRCMU_PLLSOC1 43 #define PRCMU_ARMSS 44 #define PRCMU_PLLDDR 45 -#define PRCMU_BML8580CLK 46 /* DSI Clocks */ -#define PRCMU_PLLDSI 47 -#define PRCMU_DSI0CLK 48 -#define PRCMU_DSI1CLK 49 -#define PRCMU_DSI0ESCCLK 50 -#define PRCMU_DSI1ESCCLK 51 -#define PRCMU_DSI2ESCCLK 52 +#define PRCMU_PLLDSI 46 +#define PRCMU_DSI0CLK 47 +#define PRCMU_DSI1CLK 48 +#define PRCMU_DSI0ESCCLK 49 +#define PRCMU_DSI1ESCCLK 50 +#define PRCMU_DSI2ESCCLK 51 /* LCD DSI PLL - Ux540 only */ -#define PRCMU_PLLDSI_LCD 53 -#define PRCMU_DSI0CLK_LCD 54 -#define PRCMU_DSI1CLK_LCD 55 -#define PRCMU_DSI0ESCCLK_LCD 56 -#define PRCMU_DSI1ESCCLK_LCD 57 -#define PRCMU_DSI2ESCCLK_LCD 58 +#define PRCMU_PLLDSI_LCD 52 +#define PRCMU_DSI0CLK_LCD 53 +#define PRCMU_DSI1CLK_LCD 54 +#define PRCMU_DSI0ESCCLK_LCD 55 +#define PRCMU_DSI1ESCCLK_LCD 56 +#define PRCMU_DSI2ESCCLK_LCD 57 -#define PRCMU_NUM_CLKS 59 +#define PRCMU_NUM_CLKS 58 #endif -- cgit From 82b0f4b7c576d22c764239662cedc63c21f02d8d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 17 Sep 2013 10:11:53 +0100 Subject: clk: ux500: Copy u8500_clk_init() ready for DT enablement Here we're using the old clock initialisation function as a template. It's necessary to remove all of the clk_register_clkdev() calls as they don't make sense when booting with Device Tree. Cc: Mike Turquette Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- drivers/clk/ux500/Makefile | 1 + drivers/clk/ux500/u8500_of_clk.c | 381 ++++++++++++++++++++++++++++++++ include/linux/platform_data/clk-ux500.h | 3 + 3 files changed, 385 insertions(+) create mode 100644 drivers/clk/ux500/u8500_of_clk.c (limited to 'include') diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile index c6a806ed0e8c..521483f0ba33 100644 --- a/drivers/clk/ux500/Makefile +++ b/drivers/clk/ux500/Makefile @@ -8,6 +8,7 @@ obj-y += clk-prcmu.o obj-y += clk-sysctrl.o # Clock definitions +obj-y += u8500_of_clk.o obj-y += u8500_clk.o obj-y += u9540_clk.o obj-y += u8540_clk.o diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c new file mode 100644 index 000000000000..ceebce6a624f --- /dev/null +++ b/drivers/clk/ux500/u8500_of_clk.c @@ -0,0 +1,381 @@ +/* + * Clock definitions for u8500 platform. + * + * Copyright (C) 2012 ST-Ericsson SA + * Author: Ulf Hansson + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include "clk.h" + +void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, + u32 clkrst5_base, u32 clkrst6_base) +{ + struct prcmu_fw_version *fw_version; + const char *sgaclk_parent = NULL; + struct clk *clk; + + /* Clock sources */ + clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, + CLK_IS_ROOT|CLK_IGNORE_UNUSED); + + clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1, + CLK_IS_ROOT|CLK_IGNORE_UNUSED); + + clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR, + CLK_IS_ROOT|CLK_IGNORE_UNUSED); + + /* FIXME: Add sys, ulp and int clocks here. */ + + clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL", + CLK_IS_ROOT|CLK_IGNORE_UNUSED, + 32768); + + /* PRCMU clocks */ + fw_version = prcmu_get_fw_version(); + if (fw_version != NULL) { + switch (fw_version->project) { + case PRCMU_FW_PROJECT_U8500_C2: + case PRCMU_FW_PROJECT_U8520: + case PRCMU_FW_PROJECT_U8420: + sgaclk_parent = "soc0_pll"; + break; + default: + break; + } + } + + if (sgaclk_parent) + clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent, + PRCMU_SGACLK, 0); + else + clk = clk_reg_prcmu_gate("sgclk", NULL, + PRCMU_SGACLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK, + CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, + CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, + CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT); + + clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK, + 100000000, + CLK_IS_ROOT|CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", + PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); + + + clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll", + PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll", + PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk", + PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk", + PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk", + PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE); + + clk = clk_reg_prcmu_scalable_rate("armss", NULL, + PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED); + + clk = clk_register_fixed_factor(NULL, "smp_twd", "armss", + CLK_IGNORE_UNUSED, 1, 2); + + /* + * FIXME: Add special handled PRCMU clocks here: + * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl. + * 2. ab9540_clkout1yuv, see clkout0yuv + */ + + /* PRCC P-clocks */ + clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base, + BIT(0), 0); + + clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base, + BIT(1), 0); + + clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base, + BIT(2), 0); + + clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base, + BIT(3), 0); + + clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base, + BIT(4), 0); + + clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base, + BIT(5), 0); + + clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base, + BIT(6), 0); + + clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base, + BIT(7), 0); + + clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base, + BIT(8), 0); + + clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base, + BIT(9), 0); + + clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base, + BIT(10), 0); + + clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base, + BIT(11), 0); + + clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base, + BIT(0), 0); + + clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base, + BIT(1), 0); + + clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base, + BIT(2), 0); + + clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base, + BIT(3), 0); + + clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base, + BIT(4), 0); + + clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base, + BIT(5), 0); + + clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base, + BIT(6), 0); + + clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base, + BIT(7), 0); + + clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base, + BIT(8), 0); + + clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base, + BIT(9), 0); + + clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base, + BIT(10), 0); + + clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base, + BIT(11), 0); + + clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base, + BIT(12), 0); + + clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base, + BIT(0), 0); + + clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base, + BIT(1), 0); + + clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base, + BIT(2), 0); + + clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base, + BIT(3), 0); + + clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base, + BIT(4), 0); + + clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base, + BIT(5), 0); + + clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base, + BIT(6), 0); + + clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base, + BIT(7), 0); + + clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base, + BIT(8), 0); + + clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base, + BIT(0), 0); + + clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base, + BIT(1), 0); + + clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base, + BIT(0), 0); + + clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base, + BIT(1), 0); + + clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base, + BIT(2), 0); + + clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base, + BIT(3), 0); + + clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base, + BIT(4), 0); + + clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base, + BIT(5), 0); + + clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base, + BIT(6), 0); + + clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base, + BIT(7), 0); + + /* PRCC K-clocks + * + * FIXME: Some drivers requires PERPIH[n| to be automatically enabled + * by enabling just the K-clock, even if it is not a valid parent to + * the K-clock. Until drivers get fixed we might need some kind of + * "parent muxed join". + */ + + /* Periph1 */ + clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk", + clkrst1_base, BIT(0), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk", + clkrst1_base, BIT(1), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", + clkrst1_base, BIT(2), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", + clkrst1_base, BIT(3), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", + clkrst1_base, BIT(4), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", + clkrst1_base, BIT(5), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", + clkrst1_base, BIT(6), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", + clkrst1_base, BIT(8), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", + clkrst1_base, BIT(9), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", + clkrst1_base, BIT(10), CLK_SET_RATE_GATE); + + /* Periph2 */ + clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", + clkrst2_base, BIT(0), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", + clkrst2_base, BIT(2), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", + clkrst2_base, BIT(3), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", + clkrst2_base, BIT(4), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk", + clkrst2_base, BIT(5), CLK_SET_RATE_GATE); + + /* Note that rate is received from parent. */ + clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk", + clkrst2_base, BIT(6), + CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); + clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk", + clkrst2_base, BIT(7), + CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); + + /* Periph3 */ + clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", + clkrst3_base, BIT(1), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", + clkrst3_base, BIT(2), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", + clkrst3_base, BIT(3), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", + clkrst3_base, BIT(4), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k", + clkrst3_base, BIT(5), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk", + clkrst3_base, BIT(6), CLK_SET_RATE_GATE); + + clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk", + clkrst3_base, BIT(7), CLK_SET_RATE_GATE); + + /* Periph6 */ + clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk", + clkrst6_base, BIT(0), CLK_SET_RATE_GATE); +} diff --git a/include/linux/platform_data/clk-ux500.h b/include/linux/platform_data/clk-ux500.h index 9d98f3aaa16c..97baf831e071 100644 --- a/include/linux/platform_data/clk-ux500.h +++ b/include/linux/platform_data/clk-ux500.h @@ -10,6 +10,9 @@ #ifndef __CLK_UX500_H #define __CLK_UX500_H +void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, + u32 clkrst5_base, u32 clkrst6_base); + void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, u32 clkrst5_base, u32 clkrst6_base); void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, -- cgit From 819585bc4811bc54e316dfe521ce163816fa0ad1 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 28 Aug 2013 04:39:29 -0300 Subject: [media] videobuf2: Fix vb2_write prototype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct v4_file_operations defines the data param as const char __user *data but on vb2 is defined as char __user *data. This patch fixes the warnings produced by this. ie: drivers/qtec/qtec_xform.c:817:2: warning: initialization from incompatible pointer type [enabled by default] drivers/qtec/qtec_xform.c:817:2: warning: (near initialization for ‘qtec_xform_v4l_fops.write’) [enabled by default] Signed-off-by: Ricardo Ribalda Delgado Acked-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 7 ++++--- include/media/videobuf2-core.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 594c75eab5a5..67ddadd5ea38 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2467,10 +2467,11 @@ size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, } EXPORT_SYMBOL_GPL(vb2_read); -size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count, loff_t *ppos, int nonblocking) { - return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0); + return __vb2_perform_fileio(q, (char __user *) data, count, + ppos, nonblocking, 0); } EXPORT_SYMBOL_GPL(vb2_write); @@ -2631,7 +2632,7 @@ int vb2_fop_release(struct file *file) } EXPORT_SYMBOL_GPL(vb2_fop_release); -ssize_t vb2_fop_write(struct file *file, char __user *buf, +ssize_t vb2_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 6781258d0b67..bd8218b15009 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -391,7 +391,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q, unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait); size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblock); -size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count, loff_t *ppos, int nonblock); /** @@ -491,7 +491,7 @@ int vb2_ioctl_expbuf(struct file *file, void *priv, int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma); int vb2_fop_release(struct file *file); -ssize_t vb2_fop_write(struct file *file, char __user *buf, +ssize_t vb2_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); ssize_t vb2_fop_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); -- cgit From 223012475968fb8dac866bff5b278e9311a36894 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Fri, 2 Aug 2013 10:20:00 -0300 Subject: [media] videobuf2-dma-sg: Replace vb2_dma_sg_desc with sg_table Replace the private struct vb2_dma_sg_desc with the struct sg_table so we can benefit from all the helping functions in lib/scatterlist.c for things like allocating the sg or compacting the descriptor. marvel-ccic and solo6x10 drivers, that use this API have been updated. Acked-by: Marek Szyprowski Reviewed-by: Andre Heider Signed-off-by: Ricardo Ribalda Delgado [s.nawrocki@samsung.com: minor corrections of the changelog] Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mcam-core.c | 14 +-- drivers/media/v4l2-core/videobuf2-dma-sg.c | 103 +++++++++------------ drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c | 20 ++-- include/media/videobuf2-dma-sg.h | 10 +- 4 files changed, 63 insertions(+), 84 deletions(-) (limited to 'include') diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 5184887b155c..32fab30a9105 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -1221,16 +1221,16 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb) { struct mcam_vb_buffer *mvb = vb_to_mvb(vb); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0); struct mcam_dma_desc *desc = mvb->dma_desc; struct scatterlist *sg; int i; - mvb->dma_desc_nent = dma_map_sg(cam->dev, sgd->sglist, sgd->num_pages, - DMA_FROM_DEVICE); + mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl, + sg_table->nents, DMA_FROM_DEVICE); if (mvb->dma_desc_nent <= 0) return -EIO; /* Not sure what's right here */ - for_each_sg(sgd->sglist, sg, mvb->dma_desc_nent, i) { + for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) { desc->dma_addr = sg_dma_address(sg); desc->segment_len = sg_dma_len(sg); desc++; @@ -1241,9 +1241,11 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb) static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb) { struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0); - dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE); + if (sg_table) + dma_unmap_sg(cam->dev, sg_table->sgl, + sg_table->nents, DMA_FROM_DEVICE); return 0; } diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index 4999c4886898..2f860543912c 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -35,7 +35,9 @@ struct vb2_dma_sg_buf { struct page **pages; int write; int offset; - struct vb2_dma_sg_desc sg_desc; + struct sg_table sg_table; + size_t size; + unsigned int num_pages; atomic_t refcount; struct vb2_vmarea_handler handler; }; @@ -46,7 +48,7 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf, gfp_t gfp_flags) { unsigned int last_page = 0; - int size = buf->sg_desc.size; + int size = buf->size; while (size > 0) { struct page *pages; @@ -74,12 +76,8 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf, } split_page(pages, order); - for (i = 0; i < (1 << order); i++) { - buf->pages[last_page] = &pages[i]; - sg_set_page(&buf->sg_desc.sglist[last_page], - buf->pages[last_page], PAGE_SIZE, 0); - last_page++; - } + for (i = 0; i < (1 << order); i++) + buf->pages[last_page++] = &pages[i]; size -= PAGE_SIZE << order; } @@ -91,6 +89,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla { struct vb2_dma_sg_buf *buf; int ret; + int num_pages; buf = kzalloc(sizeof *buf, GFP_KERNEL); if (!buf) @@ -99,17 +98,11 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla buf->vaddr = NULL; buf->write = 0; buf->offset = 0; - buf->sg_desc.size = size; + buf->size = size; /* size is already page aligned */ - buf->sg_desc.num_pages = size >> PAGE_SHIFT; - - buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages * - sizeof(*buf->sg_desc.sglist)); - if (!buf->sg_desc.sglist) - goto fail_sglist_alloc; - sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages); + buf->num_pages = size >> PAGE_SHIFT; - buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *), + buf->pages = kzalloc(buf->num_pages * sizeof(struct page *), GFP_KERNEL); if (!buf->pages) goto fail_pages_array_alloc; @@ -118,6 +111,11 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla if (ret) goto fail_pages_alloc; + ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages, + buf->num_pages, 0, size, gfp_flags); + if (ret) + goto fail_table_alloc; + buf->handler.refcount = &buf->refcount; buf->handler.put = vb2_dma_sg_put; buf->handler.arg = buf; @@ -125,16 +123,16 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla atomic_inc(&buf->refcount); dprintk(1, "%s: Allocated buffer of %d pages\n", - __func__, buf->sg_desc.num_pages); + __func__, buf->num_pages); return buf; +fail_table_alloc: + num_pages = buf->num_pages; + while (num_pages--) + __free_page(buf->pages[num_pages]); fail_pages_alloc: kfree(buf->pages); - fail_pages_array_alloc: - vfree(buf->sg_desc.sglist); - -fail_sglist_alloc: kfree(buf); return NULL; } @@ -142,14 +140,14 @@ fail_sglist_alloc: static void vb2_dma_sg_put(void *buf_priv) { struct vb2_dma_sg_buf *buf = buf_priv; - int i = buf->sg_desc.num_pages; + int i = buf->num_pages; if (atomic_dec_and_test(&buf->refcount)) { dprintk(1, "%s: Freeing buffer of %d pages\n", __func__, - buf->sg_desc.num_pages); + buf->num_pages); if (buf->vaddr) - vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages); - vfree(buf->sg_desc.sglist); + vm_unmap_ram(buf->vaddr, buf->num_pages); + sg_free_table(&buf->sg_table); while (--i >= 0) __free_page(buf->pages[i]); kfree(buf->pages); @@ -162,7 +160,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, { struct vb2_dma_sg_buf *buf; unsigned long first, last; - int num_pages_from_user, i; + int num_pages_from_user; buf = kzalloc(sizeof *buf, GFP_KERNEL); if (!buf) @@ -171,56 +169,41 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, buf->vaddr = NULL; buf->write = write; buf->offset = vaddr & ~PAGE_MASK; - buf->sg_desc.size = size; + buf->size = size; first = (vaddr & PAGE_MASK) >> PAGE_SHIFT; last = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT; - buf->sg_desc.num_pages = last - first + 1; - - buf->sg_desc.sglist = vzalloc( - buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist)); - if (!buf->sg_desc.sglist) - goto userptr_fail_sglist_alloc; + buf->num_pages = last - first + 1; - sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages); - - buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *), + buf->pages = kzalloc(buf->num_pages * sizeof(struct page *), GFP_KERNEL); if (!buf->pages) - goto userptr_fail_pages_array_alloc; + return NULL; num_pages_from_user = get_user_pages(current, current->mm, vaddr & PAGE_MASK, - buf->sg_desc.num_pages, + buf->num_pages, write, 1, /* force */ buf->pages, NULL); - if (num_pages_from_user != buf->sg_desc.num_pages) + if (num_pages_from_user != buf->num_pages) goto userptr_fail_get_user_pages; - sg_set_page(&buf->sg_desc.sglist[0], buf->pages[0], - PAGE_SIZE - buf->offset, buf->offset); - size -= PAGE_SIZE - buf->offset; - for (i = 1; i < buf->sg_desc.num_pages; ++i) { - sg_set_page(&buf->sg_desc.sglist[i], buf->pages[i], - min_t(size_t, PAGE_SIZE, size), 0); - size -= min_t(size_t, PAGE_SIZE, size); - } + if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages, + buf->num_pages, buf->offset, size, 0)) + goto userptr_fail_alloc_table_from_pages; + return buf; +userptr_fail_alloc_table_from_pages: userptr_fail_get_user_pages: dprintk(1, "get_user_pages requested/got: %d/%d]\n", - num_pages_from_user, buf->sg_desc.num_pages); + num_pages_from_user, buf->num_pages); while (--num_pages_from_user >= 0) put_page(buf->pages[num_pages_from_user]); kfree(buf->pages); - -userptr_fail_pages_array_alloc: - vfree(buf->sg_desc.sglist); - -userptr_fail_sglist_alloc: kfree(buf); return NULL; } @@ -232,18 +215,18 @@ userptr_fail_sglist_alloc: static void vb2_dma_sg_put_userptr(void *buf_priv) { struct vb2_dma_sg_buf *buf = buf_priv; - int i = buf->sg_desc.num_pages; + int i = buf->num_pages; dprintk(1, "%s: Releasing userspace buffer of %d pages\n", - __func__, buf->sg_desc.num_pages); + __func__, buf->num_pages); if (buf->vaddr) - vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages); + vm_unmap_ram(buf->vaddr, buf->num_pages); + sg_free_table(&buf->sg_table); while (--i >= 0) { if (buf->write) set_page_dirty_lock(buf->pages[i]); put_page(buf->pages[i]); } - vfree(buf->sg_desc.sglist); kfree(buf->pages); kfree(buf); } @@ -256,7 +239,7 @@ static void *vb2_dma_sg_vaddr(void *buf_priv) if (!buf->vaddr) buf->vaddr = vm_map_ram(buf->pages, - buf->sg_desc.num_pages, + buf->num_pages, -1, PAGE_KERNEL); @@ -312,7 +295,7 @@ static void *vb2_dma_sg_cookie(void *buf_priv) { struct vb2_dma_sg_buf *buf = buf_priv; - return &buf->sg_desc; + return &buf->sg_table; } const struct vb2_mem_ops vb2_dma_sg_memops = { diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c index a4c589604b02..9a6d5c0b1339 100644 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c @@ -346,7 +346,7 @@ static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma, /* Build a descriptor queue out of an SG list and send it to the P2M for * processing. */ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, - struct vb2_dma_sg_desc *vbuf, int off, int size, + struct sg_table *vbuf, int off, int size, unsigned int base, unsigned int base_size) { struct solo_dev *solo_dev = solo_enc->solo_dev; @@ -359,7 +359,7 @@ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, solo_enc->desc_count = 1; - for_each_sg(vbuf->sglist, sg, vbuf->num_pages, i) { + for_each_sg(vbuf->sgl, sg, vbuf->nents, i) { struct solo_p2m_desc *desc; dma_addr_t dma; int len; @@ -434,7 +434,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct vb2_buffer *vb, struct vop_header *vh) { struct solo_dev *solo_dev = solo_enc->solo_dev; - struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); int frame_size; int ret; @@ -443,7 +443,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, if (vb2_plane_size(vb, 0) < vh->jpeg_size + solo_enc->jpeg_len) return -EIO; - sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages, + sg_copy_from_buffer(vbuf->sgl, vbuf->nents, solo_enc->jpeg_header, solo_enc->jpeg_len); @@ -451,12 +451,12 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, & ~(DMA_ALIGN - 1); vb2_set_plane_payload(vb, 0, vh->jpeg_size + solo_enc->jpeg_len); - dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages, + dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, DMA_FROM_DEVICE); ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off, frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), SOLO_JPEG_EXT_SIZE(solo_dev)); - dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages, + dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, DMA_FROM_DEVICE); return ret; } @@ -465,7 +465,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct vb2_buffer *vb, struct vop_header *vh) { struct solo_dev *solo_dev = solo_enc->solo_dev; - struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); int frame_off, frame_size; int skip = 0; int ret; @@ -475,7 +475,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, /* If this is a key frame, add extra header */ if (!vh->vop_type) { - sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages, + sg_copy_from_buffer(vbuf->sgl, vbuf->nents, solo_enc->vop, solo_enc->vop_len); @@ -494,12 +494,12 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1)) & ~(DMA_ALIGN - 1); - dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages, + dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, DMA_FROM_DEVICE); ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size, SOLO_MP4E_EXT_ADDR(solo_dev), SOLO_MP4E_EXT_SIZE(solo_dev)); - dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages, + dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, DMA_FROM_DEVICE); return ret; } diff --git a/include/media/videobuf2-dma-sg.h b/include/media/videobuf2-dma-sg.h index 0038526b8ef7..7b89852779af 100644 --- a/include/media/videobuf2-dma-sg.h +++ b/include/media/videobuf2-dma-sg.h @@ -15,16 +15,10 @@ #include -struct vb2_dma_sg_desc { - unsigned long size; - unsigned int num_pages; - struct scatterlist *sglist; -}; - -static inline struct vb2_dma_sg_desc *vb2_dma_sg_plane_desc( +static inline struct sg_table *vb2_dma_sg_plane_desc( struct vb2_buffer *vb, unsigned int plane_no) { - return (struct vb2_dma_sg_desc *)vb2_plane_cookie(vb, plane_no); + return (struct sg_table *)vb2_plane_cookie(vb, plane_no); } extern const struct vb2_mem_ops vb2_dma_sg_memops; -- cgit From c7c71066c27f2bafb2ce3b10c407c0285f56acfa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Aug 2013 22:07:20 +0200 Subject: mac80211: add ieee80211_iterate_active_interfaces_rtnl() If it is needed to disconnect multiple virtual interfaces after (WoWLAN-) suspend, the most obvious approach would be to iterate all interfaces by calling ieee80211_iterate_active_interfaces() and then call ieee80211_resume_disconnect() for each one. This is what the iwlmvm driver does. Unfortunately, this causes a locking dependency from mac80211's iflist_mtx to the key_mtx. This is problematic as the former is intentionally never held while calling any driver operation to allow drivers to iterate with their own locks held. The key_mtx is held while installing a key into the driver though, so this new lock dependency means drivers implementing the logic above can no longer hold their own lock while iterating. To fix this, add a new ieee80211_iterate_active_interfaces_rtnl() function that iterates while the RTNL is already held. This is true during suspend/resume, so that then the locking dependency isn't introduced. While at it, also refactor the various interface iterators and keep only a single implementation called by the various cases. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 19 ++++++++++++++ net/mac80211/util.c | 71 ++++++++++++++++++++++++-------------------------- 2 files changed, 53 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cc6035f1a2f1..3411c59b636b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3919,6 +3919,25 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, struct ieee80211_vif *vif), void *data); +/** + * ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces + * + * This function iterates over the interfaces associated with a given + * hardware that are currently active and calls the callback for them. + * This version can only be used while holding the RTNL. + * + * @hw: the hardware struct of which the interfaces should be iterated over + * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags + * @iterator: the iterator function to call, cannot sleep + * @data: first argument of the iterator function + */ +void ieee80211_iterate_active_interfaces_rtnl(struct ieee80211_hw *hw, + u32 iter_flags, + void (*iterator)(void *data, + u8 *mac, + struct ieee80211_vif *vif), + void *data); + /** * ieee80211_queue_work - add work onto the mac80211 workqueue * diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e1b34a18b243..75a16853fb45 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -567,18 +567,15 @@ void ieee80211_flush_queues(struct ieee80211_local *local, IEEE80211_QUEUE_STOP_REASON_FLUSH); } -void ieee80211_iterate_active_interfaces( - struct ieee80211_hw *hw, u32 iter_flags, - void (*iterator)(void *data, u8 *mac, - struct ieee80211_vif *vif), - void *data) +static void __iterate_active_interfaces(struct ieee80211_local *local, + u32 iter_flags, + void (*iterator)(void *data, u8 *mac, + struct ieee80211_vif *vif), + void *data) { - struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - mutex_lock(&local->iflist_mtx); - - list_for_each_entry(sdata, &local->interfaces, list) { + list_for_each_entry_rcu(sdata, &local->interfaces, list) { switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) @@ -597,13 +594,25 @@ void ieee80211_iterate_active_interfaces( &sdata->vif); } - sdata = rcu_dereference_protected(local->monitor_sdata, - lockdep_is_held(&local->iflist_mtx)); + sdata = rcu_dereference_check(local->monitor_sdata, + lockdep_is_held(&local->iflist_mtx) || + lockdep_rtnl_is_held()); if (sdata && (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || sdata->flags & IEEE80211_SDATA_IN_DRIVER)) iterator(data, sdata->vif.addr, &sdata->vif); +} +void ieee80211_iterate_active_interfaces( + struct ieee80211_hw *hw, u32 iter_flags, + void (*iterator)(void *data, u8 *mac, + struct ieee80211_vif *vif), + void *data) +{ + struct ieee80211_local *local = hw_to_local(hw); + + mutex_lock(&local->iflist_mtx); + __iterate_active_interfaces(local, iter_flags, iterator, data); mutex_unlock(&local->iflist_mtx); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); @@ -615,38 +624,26 @@ void ieee80211_iterate_active_interfaces_atomic( void *data) { struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; rcu_read_lock(); + __iterate_active_interfaces(local, iter_flags, iterator, data); + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - switch (sdata->vif.type) { - case NL80211_IFTYPE_MONITOR: - if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) - continue; - break; - case NL80211_IFTYPE_AP_VLAN: - continue; - default: - break; - } - if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && - !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) - continue; - if (ieee80211_sdata_running(sdata)) - iterator(data, sdata->vif.addr, - &sdata->vif); - } +void ieee80211_iterate_active_interfaces_rtnl( + struct ieee80211_hw *hw, u32 iter_flags, + void (*iterator)(void *data, u8 *mac, + struct ieee80211_vif *vif), + void *data) +{ + struct ieee80211_local *local = hw_to_local(hw); - sdata = rcu_dereference(local->monitor_sdata); - if (sdata && - (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || - sdata->flags & IEEE80211_SDATA_IN_DRIVER)) - iterator(data, sdata->vif.addr, &sdata->vif); + ASSERT_RTNL(); - rcu_read_unlock(); + __iterate_active_interfaces(local, iter_flags, iterator, data); } -EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); +EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); /* * Nothing should have been stuffed into the workqueue during -- cgit From 774f073461dbee0decee7524d9b930a98a3dc30c Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 28 Aug 2013 13:41:28 +0200 Subject: cfg80211: export cfg80211_chandef_dfs_required It will be used later by the IBSS CSA implementation of mac80211. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 9 +++++++++ net/wireless/chan.c | 1 + net/wireless/core.h | 9 --------- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index cb710913d5c8..45f6bf591104 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -436,6 +436,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef, u32 prohibited_flags); +/** + * cfg80211_chandef_dfs_required - checks if radar detection is required + * @wiphy: the wiphy to validate against + * @chandef: the channel definition to check + * Return: 1 if radar detection is required, 0 if it is not, < 0 on error + */ +int cfg80211_chandef_dfs_required(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef); + /** * ieee80211_chandef_rate_flags - returns rate flags for a channel * diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 50f6195c8b70..16f3c3a7b2c1 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2, width); } +EXPORT_SYMBOL(cfg80211_chandef_dfs_required); static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, diff --git a/net/wireless/core.h b/net/wireless/core.h index 9ad43c619c54..b43efac4efca 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -382,15 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, enum cfg80211_chan_mode chanmode, u8 radar_detect); -/** - * cfg80211_chandef_dfs_required - checks if radar detection is required - * @wiphy: the wiphy to validate against - * @chandef: the channel definition to check - * Return: 1 if radar detection is required, 0 if it is not, < 0 on error - */ -int cfg80211_chandef_dfs_required(struct wiphy *wiphy, - const struct cfg80211_chan_def *c); - void cfg80211_set_dfs_state(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef, enum nl80211_dfs_state dfs_state); -- cgit From ad93220de7da1f5bd8f9e4be1f1eeefba5eed0ad Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 13 Sep 2013 19:11:35 +0800 Subject: mmc: sdhci-esdhc-imx: change pinctrl state according to uhs mode Without proper pinctrl state, the card may not be able to work on high speed stablely. e.g. SDR104. This patch add pinctrl state switch code according to different uhs mode include 100mhz sate, 200mhz sate and normal state (50Mhz and below). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 96 ++++++++++++++++++++++++++++- include/linux/platform_data/mmc-esdhc-imx.h | 4 ++ 2 files changed, 99 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index f906c206901d..ed00d6ddd5fd 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -53,6 +53,10 @@ #define ESDHC_TUNING_BLOCK_PATTERN_LEN 64 +/* pinctrl state */ +#define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz" +#define ESDHC_PINCTRL_STATE_200MHZ "state_200mhz" + /* * Our interpretation of the SDHCI_HOST_CONTROL register */ @@ -94,6 +98,9 @@ struct pltfm_imx_data { u32 scratchpad; enum imx_esdhc_type devtype; struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_100mhz; + struct pinctrl_state *pins_200mhz; struct esdhc_platform_data boarddata; struct clk *clk_ipg; struct clk *clk_ahb; @@ -693,6 +700,62 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) return ret; } +static int esdhc_change_pinstate(struct sdhci_host *host, + unsigned int uhs) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + struct pinctrl_state *pinctrl; + + dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); + + if (IS_ERR(imx_data->pinctrl) || + IS_ERR(imx_data->pins_default) || + IS_ERR(imx_data->pins_100mhz) || + IS_ERR(imx_data->pins_200mhz)) + return -EINVAL; + + switch (uhs) { + case MMC_TIMING_UHS_SDR50: + pinctrl = imx_data->pins_100mhz; + break; + case MMC_TIMING_UHS_SDR104: + pinctrl = imx_data->pins_200mhz; + break; + default: + /* back to default state for other legacy timing */ + pinctrl = imx_data->pins_default; + } + + return pinctrl_select_state(imx_data->pinctrl, pinctrl); +} + +static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + + switch (uhs) { + case MMC_TIMING_UHS_SDR12: + imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR25: + imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25; + break; + case MMC_TIMING_UHS_SDR50: + imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; + break; + case MMC_TIMING_UHS_SDR104: + imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; + break; + case MMC_TIMING_UHS_DDR50: + imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50; + break; + } + + return esdhc_change_pinstate(host, uhs); +} + static const struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le, @@ -704,6 +767,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .get_min_clock = esdhc_pltfm_get_min_clock, .get_ro = esdhc_pltfm_get_ro, .platform_bus_width = esdhc_pltfm_bus_width, + .set_uhs_signaling = esdhc_set_uhs_signaling, .platform_execute_tuning = esdhc_executing_tuning, }; @@ -746,6 +810,11 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, of_property_read_u32(np, "max-frequency", &boarddata->f_max); + if (of_find_property(np, "no-1-8-v", NULL)) + boarddata->support_vsel = false; + else + boarddata->support_vsel = true; + return 0; } #else @@ -808,12 +877,20 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) clk_prepare_enable(imx_data->clk_ipg); clk_prepare_enable(imx_data->clk_ahb); - imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(imx_data->pinctrl)) { err = PTR_ERR(imx_data->pinctrl); goto disable_clk; } + imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(imx_data->pins_default)) { + err = PTR_ERR(imx_data->pins_default); + dev_err(mmc_dev(host->mmc), "could not get default state\n"); + goto disable_clk; + } + host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) @@ -890,6 +967,23 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) break; } + /* sdr50 and sdr104 needs work on 1.8v signal voltage */ + if ((boarddata->support_vsel) && is_imx6q_usdhc(imx_data)) { + imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_100MHZ); + imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_200MHZ); + if (IS_ERR(imx_data->pins_100mhz) || + IS_ERR(imx_data->pins_200mhz)) { + dev_warn(mmc_dev(host->mmc), + "could not get ultra high speed state, work on normal mode\n"); + /* fall back to not support uhs by specify no 1.8v quirk */ + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + } else { + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + err = sdhci_add_host(host); if (err) goto disable_clk; diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index d44912d81578..a0f5a8f9b3bc 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -10,6 +10,8 @@ #ifndef __ASM_ARCH_IMX_ESDHC_H #define __ASM_ARCH_IMX_ESDHC_H +#include + enum wp_types { ESDHC_WP_NONE, /* no WP, neither controller nor gpio */ ESDHC_WP_CONTROLLER, /* mmc controller internal WP */ @@ -32,6 +34,7 @@ enum cd_types { * @cd_gpio: gpio for card_detect interrupt * @wp_type: type of write_protect method (see wp_types enum above) * @cd_type: type of card_detect method (see cd_types enum above) + * @support_vsel: indicate it supports 1.8v switching */ struct esdhc_platform_data { @@ -41,5 +44,6 @@ struct esdhc_platform_data { enum cd_types cd_type; int max_bus_width; unsigned int f_max; + bool support_vsel; }; #endif /* __ASM_ARCH_IMX_ESDHC_H */ -- cgit From 03f3a9107f5e848a42f25e3ab133db9f3b6546c7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:49 -0700 Subject: hv: use dev_groups for device attributes This patch is the first in a series that moves the hv bus code to use the dev_groups field instead of dev_attrs, as dev_attrs is going away in future kernel releases. It moves the id sysfs file to the dev_groups structure, and creates the needed show/store functions, instead of relying on one "universal" function for this. By doing this, it removes the need for this to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 1 - drivers/hv/vmbus_drv.c | 23 ++++++++++++++++++----- include/linux/hyperv.h | 1 - 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 6de6c98ce6eb..b58a1785d038 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -69,7 +69,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_group = (u8)channel->offermsg.monitorid / 32; u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - debuginfo->relid = channel->offermsg.child_relid; debuginfo->state = channel->state; memcpy(&debuginfo->interfacetype, &channel->offermsg.offer.if_type, sizeof(uuid_le)); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index f9fe46f52cfa..5c21b22860af 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,7 +47,6 @@ static struct completion probe_event; static int irq; struct hv_device_info { - u32 chn_id; u32 chn_state; uuid_le chn_type; uuid_le chn_instance; @@ -83,7 +82,6 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - info->chn_id = debug_info.relid; info->chn_state = debug_info.state; memcpy(&info->chn_type, &debug_info.interfacetype, sizeof(uuid_le)); @@ -156,8 +154,6 @@ static ssize_t vmbus_show_device_attr(struct device *dev, ret = sprintf(buf, "vmbus:%s\n", alias_name); } else if (!strcmp(dev_attr->attr.name, "state")) { ret = sprintf(buf, "%d\n", device_info->chn_state); - } else if (!strcmp(dev_attr->attr.name, "id")) { - ret = sprintf(buf, "%d\n", device_info->chn_id); } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { @@ -204,9 +200,25 @@ static ssize_t vmbus_show_device_attr(struct device *dev, return ret; } +static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid); +} +static DEVICE_ATTR_RO(id); + +static struct attribute *vmbus_attrs[] = { + &dev_attr_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vmbus); + /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), @@ -384,6 +396,7 @@ static struct bus_type hv_bus = { .probe = vmbus_probe, .uevent = vmbus_uevent, .dev_attrs = vmbus_device_attrs, + .dev_groups = vmbus_groups, }; static const char *driver_name = "hyperv"; diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index a3b8b2e2d244..45e9b65e6ab6 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,7 +900,6 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - u32 relid; enum vmbus_channel_state state; uuid_le interfacetype; uuid_le interface_instance; -- cgit From a8fb5f3d582d3b4997d9449ceb82a0223d169486 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:50 -0700 Subject: hv: move "state" bus attribute to dev_groups This moves the "state" bus attribute to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 1 - drivers/hv/vmbus_drv.c | 17 ++++++++++++----- include/linux/hyperv.h | 1 - 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index b58a1785d038..64f19f226c4e 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -69,7 +69,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_group = (u8)channel->offermsg.monitorid / 32; u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - debuginfo->state = channel->state; memcpy(&debuginfo->interfacetype, &channel->offermsg.offer.if_type, sizeof(uuid_le)); memcpy(&debuginfo->interface_instance, diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 5c21b22860af..1e5bc9c49c63 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,7 +47,6 @@ static struct completion probe_event; static int irq; struct hv_device_info { - u32 chn_state; uuid_le chn_type; uuid_le chn_instance; @@ -82,7 +81,6 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - info->chn_state = debug_info.state; memcpy(&info->chn_type, &debug_info.interfacetype, sizeof(uuid_le)); memcpy(&info->chn_instance, &debug_info.interface_instance, @@ -152,8 +150,6 @@ static ssize_t vmbus_show_device_attr(struct device *dev, } else if (!strcmp(dev_attr->attr.name, "modalias")) { print_alias_name(hv_dev, alias_name); ret = sprintf(buf, "vmbus:%s\n", alias_name); - } else if (!strcmp(dev_attr->attr.name, "state")) { - ret = sprintf(buf, "%d\n", device_info->chn_state); } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { @@ -211,15 +207,26 @@ static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, } static DEVICE_ATTR_RO(id); +static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", hv_dev->channel->state); +} +static DEVICE_ATTR_RO(state); + static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, + &dev_attr_state.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 45e9b65e6ab6..b350a8cfcff6 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,7 +900,6 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - enum vmbus_channel_state state; uuid_le interfacetype; uuid_le interface_instance; u32 monitorid; -- cgit From 5ffd00e241ea30fdd907d56419170a1e1338664c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:51 -0700 Subject: hv: move "monitor_id" bus attribute to dev_groups This moves the "state" bus attribute to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 2 -- drivers/hv/vmbus_drv.c | 18 ++++++++++++------ include/linux/hyperv.h | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 64f19f226c4e..f26a5d252547 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -77,8 +77,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; - debuginfo->monitorid = channel->offermsg.monitorid; - debuginfo->servermonitor_pending = monitorpage->trigger_group[monitor_group].pending; debuginfo->servermonitor_latency = diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1e5bc9c49c63..2114ecb83c93 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -50,7 +50,6 @@ struct hv_device_info { uuid_le chn_type; uuid_le chn_instance; - u32 monitor_id; u32 server_monitor_pending; u32 server_monitor_latency; u32 server_monitor_conn_id; @@ -86,8 +85,6 @@ static void get_channel_info(struct hv_device *device, memcpy(&info->chn_instance, &debug_info.interface_instance, sizeof(uuid_le)); - info->monitor_id = debug_info.monitorid; - info->server_monitor_pending = debug_info.servermonitor_pending; info->server_monitor_latency = debug_info.servermonitor_latency; info->server_monitor_conn_id = debug_info.servermonitor_connectionid; @@ -174,8 +171,6 @@ static ssize_t vmbus_show_device_attr(struct device *dev, } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { - ret = sprintf(buf, "%d\n", device_info->monitor_id); } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { @@ -218,9 +213,21 @@ static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr, } static DEVICE_ATTR_RO(state); +static ssize_t monitor_id_show(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid); +} +static DEVICE_ATTR_RO(monitor_id); + static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, &dev_attr_state.attr, + &dev_attr_monitor_id.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus); @@ -229,7 +236,6 @@ ATTRIBUTE_GROUPS(vmbus); static struct device_attribute vmbus_device_attrs[] = { __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index b350a8cfcff6..888a8e533d61 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -902,7 +902,6 @@ enum vmbus_channel_state { struct vmbus_channel_debug_info { uuid_le interfacetype; uuid_le interface_instance; - u32 monitorid; u32 servermonitor_pending; u32 servermonitor_latency; u32 servermonitor_connectionid; -- cgit From 68234c049cc1637a8898ebb3743c8587560929b7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:53 -0700 Subject: hv: move "class_id" bus attribute to dev_groups This moves the "class_id" bus attribute to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 2 -- drivers/hv/vmbus_drv.c | 22 +++++++++++++++------- include/linux/hyperv.h | 1 - 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index f26a5d252547..df9499c1ef32 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -69,8 +69,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_group = (u8)channel->offermsg.monitorid / 32; u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - memcpy(&debuginfo->interfacetype, - &channel->offermsg.offer.if_type, sizeof(uuid_le)); memcpy(&debuginfo->interface_instance, &channel->offermsg.offer.if_instance, sizeof(uuid_le)); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e3f4370036ab..48258ae3467d 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,7 +47,6 @@ static struct completion probe_event; static int irq; struct hv_device_info { - uuid_le chn_type; uuid_le chn_instance; u32 server_monitor_pending; @@ -80,8 +79,6 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - memcpy(&info->chn_type, &debug_info.interfacetype, - sizeof(uuid_le)); memcpy(&info->chn_instance, &debug_info.interface_instance, sizeof(uuid_le)); @@ -139,9 +136,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev, get_channel_info(hv_dev, device_info); - if (!strcmp(dev_attr->attr.name, "class_id")) { - ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b); - } else if (!strcmp(dev_attr->attr.name, "device_id")) { + if (!strcmp(dev_attr->attr.name, "device_id")) { ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b); } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); @@ -220,6 +215,18 @@ static ssize_t monitor_id_show(struct device *dev, } static DEVICE_ATTR_RO(monitor_id); +static ssize_t class_id_show(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "{%pUl}\n", + hv_dev->channel->offermsg.offer.if_type.b); +} +static DEVICE_ATTR_RO(class_id); + static ssize_t modalias_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -231,10 +238,12 @@ static ssize_t modalias_show(struct device *dev, } static DEVICE_ATTR_RO(modalias); + static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, &dev_attr_state.attr, &dev_attr_monitor_id.attr, + &dev_attr_class_id.attr, &dev_attr_modalias.attr, NULL, }; @@ -242,7 +251,6 @@ ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 888a8e533d61..8ccf6f686272 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,7 +900,6 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - uuid_le interfacetype; uuid_le interface_instance; u32 servermonitor_pending; u32 servermonitor_latency; -- cgit From 7c55e1d0e64cf5acd8cf4a25927e2c7c322063aa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:54 -0700 Subject: hv: move "device_id" bus attribute to dev_groups This moves the "device_id" bus attribute to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 4 ---- drivers/hv/vmbus_drv.c | 24 ++++++++++++++---------- include/linux/hyperv.h | 1 - 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index df9499c1ef32..dde30b48c56c 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -69,10 +69,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_group = (u8)channel->offermsg.monitorid / 32; u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - memcpy(&debuginfo->interface_instance, - &channel->offermsg.offer.if_instance, - sizeof(uuid_le)); - monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; debuginfo->servermonitor_pending = diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 48258ae3467d..944dc4b0b54d 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,8 +47,6 @@ static struct completion probe_event; static int irq; struct hv_device_info { - uuid_le chn_instance; - u32 server_monitor_pending; u32 server_monitor_latency; u32 server_monitor_conn_id; @@ -79,9 +77,6 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - memcpy(&info->chn_instance, &debug_info.interface_instance, - sizeof(uuid_le)); - info->server_monitor_pending = debug_info.servermonitor_pending; info->server_monitor_latency = debug_info.servermonitor_latency; info->server_monitor_conn_id = debug_info.servermonitor_connectionid; @@ -136,9 +131,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev, get_channel_info(hv_dev, device_info); - if (!strcmp(dev_attr->attr.name, "device_id")) { - ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b); - } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { + if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); @@ -227,6 +220,18 @@ static ssize_t class_id_show(struct device *dev, } static DEVICE_ATTR_RO(class_id); +static ssize_t device_id_show(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "{%pUl}\n", + hv_dev->channel->offermsg.offer.if_instance.b); +} +static DEVICE_ATTR_RO(device_id); + static ssize_t modalias_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -244,6 +249,7 @@ static struct attribute *vmbus_attrs[] = { &dev_attr_state.attr, &dev_attr_monitor_id.attr, &dev_attr_class_id.attr, + &dev_attr_device_id.attr, &dev_attr_modalias.attr, NULL, }; @@ -251,8 +257,6 @@ ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 8ccf6f686272..687c01b85037 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,7 +900,6 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - uuid_le interface_instance; u32 servermonitor_pending; u32 servermonitor_latency; u32 servermonitor_connectionid; -- cgit From 76c52bbe5e5ffc6812dcd49729c09f5a207b4a9a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:56 -0700 Subject: hv: move "client/server_monitor_pending" bus attributes to dev_groups This moves the "client_monitor_pending" and "server_monitor_pending" bus attributes to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 4 ---- drivers/hv/vmbus_drv.c | 56 +++++++++++++++++++++++++++++++++++++++++--------- include/linux/hyperv.h | 2 -- 3 files changed, 46 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 04bf06560085..d600360ee788 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -70,8 +70,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; monitorpage = vmbus_connection.monitor_pages[0]; - debuginfo->servermonitor_pending = - monitorpage->trigger_group[monitor_group].pending; debuginfo->servermonitor_latency = monitorpage->latency[monitor_group][monitor_offset]; debuginfo->servermonitor_connectionid = @@ -79,8 +77,6 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, [monitor_offset].connectionid.u.id; monitorpage = vmbus_connection.monitor_pages[1]; - debuginfo->clientmonitor_pending = - monitorpage->trigger_group[monitor_group].pending; debuginfo->clientmonitor_latency = monitorpage->latency[monitor_group][monitor_offset]; debuginfo->clientmonitor_connectionid = diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 944dc4b0b54d..5a44957b7064 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,10 +47,8 @@ static struct completion probe_event; static int irq; struct hv_device_info { - u32 server_monitor_pending; u32 server_monitor_latency; u32 server_monitor_conn_id; - u32 client_monitor_pending; u32 client_monitor_latency; u32 client_monitor_conn_id; @@ -77,11 +75,9 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - info->server_monitor_pending = debug_info.servermonitor_pending; info->server_monitor_latency = debug_info.servermonitor_latency; info->server_monitor_conn_id = debug_info.servermonitor_connectionid; - info->client_monitor_pending = debug_info.clientmonitor_pending; info->client_monitor_latency = debug_info.clientmonitor_latency; info->client_monitor_conn_id = debug_info.clientmonitor_connectionid; @@ -155,15 +151,11 @@ static ssize_t vmbus_show_device_attr(struct device *dev, } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { - ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_conn_id); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { - ret = sprintf(buf, "%d\n", device_info->client_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { @@ -175,6 +167,23 @@ static ssize_t vmbus_show_device_attr(struct device *dev, return ret; } +static u8 channel_monitor_group(struct vmbus_channel *channel) +{ + return (u8)channel->offermsg.monitorid / 32; +} + +static u8 channel_monitor_offset(struct vmbus_channel *channel) +{ + return (u8)channel->offermsg.monitorid % 32; +} + +static u32 channel_pending(struct vmbus_channel *channel, + struct hv_monitor_page *monitor_page) +{ + u8 monitor_group = channel_monitor_group(channel); + return monitor_page->trigger_group[monitor_group].pending; +} + static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -243,6 +252,33 @@ static ssize_t modalias_show(struct device *dev, } static DEVICE_ATTR_RO(modalias); +static ssize_t server_monitor_pending_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_pending(hv_dev->channel, + vmbus_connection.monitor_pages[1])); +} +static DEVICE_ATTR_RO(server_monitor_pending); + +static ssize_t client_monitor_pending_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_pending(hv_dev->channel, + vmbus_connection.monitor_pages[1])); +} +static DEVICE_ATTR_RO(client_monitor_pending); static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, @@ -251,17 +287,17 @@ static struct attribute *vmbus_attrs[] = { &dev_attr_class_id.attr, &dev_attr_device_id.attr, &dev_attr_modalias.attr, + &dev_attr_server_monitor_pending.attr, + &dev_attr_client_monitor_pending.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 687c01b85037..f0a7d27ffb21 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,10 +900,8 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - u32 servermonitor_pending; u32 servermonitor_latency; u32 servermonitor_connectionid; - u32 clientmonitor_pending; u32 clientmonitor_latency; u32 clientmonitor_connectionid; -- cgit From 1cee272b0249c5007391da6cf42903b8f30dbc5a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:57 -0700 Subject: hv: move "client/server_monitor_latency" bus attributes to dev_groups This moves the "client_monitor_latency" and "server_monitor_latency" bus attributes to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 4 ---- drivers/hv/vmbus_drv.c | 48 ++++++++++++++++++++++++++++++++++++++---------- include/linux/hyperv.h | 2 -- 3 files changed, 38 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index d600360ee788..ff61464f57ca 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -70,15 +70,11 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; monitorpage = vmbus_connection.monitor_pages[0]; - debuginfo->servermonitor_latency = - monitorpage->latency[monitor_group][monitor_offset]; debuginfo->servermonitor_connectionid = monitorpage->parameter[monitor_group] [monitor_offset].connectionid.u.id; monitorpage = vmbus_connection.monitor_pages[1]; - debuginfo->clientmonitor_latency = - monitorpage->latency[monitor_group][monitor_offset]; debuginfo->clientmonitor_connectionid = monitorpage->parameter[monitor_group] [monitor_offset].connectionid.u.id; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 5a44957b7064..461b989835b6 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,9 +47,7 @@ static struct completion probe_event; static int irq; struct hv_device_info { - u32 server_monitor_latency; u32 server_monitor_conn_id; - u32 client_monitor_latency; u32 client_monitor_conn_id; struct hv_dev_port_info inbound; @@ -75,10 +73,8 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - info->server_monitor_latency = debug_info.servermonitor_latency; info->server_monitor_conn_id = debug_info.servermonitor_connectionid; - info->client_monitor_latency = debug_info.clientmonitor_latency; info->client_monitor_conn_id = debug_info.clientmonitor_connectionid; info->inbound.int_mask = debug_info.inbound.current_interrupt_mask; @@ -151,13 +147,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev, } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { - ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_conn_id); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { - ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { ret = sprintf(buf, "%d\n", device_info->client_monitor_conn_id); @@ -184,6 +176,14 @@ static u32 channel_pending(struct vmbus_channel *channel, return monitor_page->trigger_group[monitor_group].pending; } +static u32 channel_latency(struct vmbus_channel *channel, + struct hv_monitor_page *monitor_page) +{ + u8 monitor_group = channel_monitor_group(channel); + u8 monitor_offset = channel_monitor_offset(channel); + return monitor_page->latency[monitor_group][monitor_offset]; +} + static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -280,6 +280,34 @@ static ssize_t client_monitor_pending_show(struct device *dev, } static DEVICE_ATTR_RO(client_monitor_pending); +static ssize_t server_monitor_latency_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_latency(hv_dev->channel, + vmbus_connection.monitor_pages[0])); +} +static DEVICE_ATTR_RO(server_monitor_latency); + +static ssize_t client_monitor_latency_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_latency(hv_dev->channel, + vmbus_connection.monitor_pages[1])); +} +static DEVICE_ATTR_RO(client_monitor_latency); + static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, &dev_attr_state.attr, @@ -289,16 +317,16 @@ static struct attribute *vmbus_attrs[] = { &dev_attr_modalias.attr, &dev_attr_server_monitor_pending.attr, &dev_attr_client_monitor_pending.attr, + &dev_attr_server_monitor_latency.attr, + &dev_attr_client_monitor_latency.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index f0a7d27ffb21..ec1e5033bb99 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,9 +900,7 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - u32 servermonitor_latency; u32 servermonitor_connectionid; - u32 clientmonitor_latency; u32 clientmonitor_connectionid; struct hv_ring_buffer_debug_info inbound; -- cgit From 4947c7453b184bc33a0056cf95af61c3cad11ef6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:58 -0700 Subject: hv: move "client/server_monitor_conn_id" bus attributes to dev_groups This moves the "client_monitor_conn_id" and "server_monitor_conn_id" bus attributes to the dev_groups structure, removing the need for it to be in a temporary structure. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 14 ------------- drivers/hv/vmbus_drv.c | 55 ++++++++++++++++++++++++++++++++++---------------- include/linux/hyperv.h | 3 --- 3 files changed, 38 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index ff61464f57ca..75c26da3e011 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -65,20 +65,6 @@ static void vmbus_setevent(struct vmbus_channel *channel) void vmbus_get_debug_info(struct vmbus_channel *channel, struct vmbus_channel_debug_info *debuginfo) { - struct hv_monitor_page *monitorpage; - u8 monitor_group = (u8)channel->offermsg.monitorid / 32; - u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - - monitorpage = vmbus_connection.monitor_pages[0]; - debuginfo->servermonitor_connectionid = - monitorpage->parameter[monitor_group] - [monitor_offset].connectionid.u.id; - - monitorpage = vmbus_connection.monitor_pages[1]; - debuginfo->clientmonitor_connectionid = - monitorpage->parameter[monitor_group] - [monitor_offset].connectionid.u.id; - hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound); hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound); } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 461b989835b6..73cb456e256b 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,9 +47,6 @@ static struct completion probe_event; static int irq; struct hv_device_info { - u32 server_monitor_conn_id; - u32 client_monitor_conn_id; - struct hv_dev_port_info inbound; struct hv_dev_port_info outbound; }; @@ -73,10 +70,6 @@ static void get_channel_info(struct hv_device *device, vmbus_get_debug_info(device->channel, &debug_info); - info->server_monitor_conn_id = debug_info.servermonitor_connectionid; - - info->client_monitor_conn_id = debug_info.clientmonitor_connectionid; - info->inbound.int_mask = debug_info.inbound.current_interrupt_mask; info->inbound.read_idx = debug_info.inbound.current_read_index; info->inbound.write_idx = debug_info.inbound.current_write_index; @@ -147,12 +140,6 @@ static ssize_t vmbus_show_device_attr(struct device *dev, } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_towrite); - } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { - ret = sprintf(buf, "%d\n", - device_info->server_monitor_conn_id); - } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { - ret = sprintf(buf, "%d\n", - device_info->client_monitor_conn_id); } kfree(device_info); @@ -184,6 +171,14 @@ static u32 channel_latency(struct vmbus_channel *channel, return monitor_page->latency[monitor_group][monitor_offset]; } +static u32 channel_conn_id(struct vmbus_channel *channel, + struct hv_monitor_page *monitor_page) +{ + u8 monitor_group = channel_monitor_group(channel); + u8 monitor_offset = channel_monitor_offset(channel); + return monitor_page->parameter[monitor_group][monitor_offset].connectionid.u.id; +} + static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -308,6 +303,34 @@ static ssize_t client_monitor_latency_show(struct device *dev, } static DEVICE_ATTR_RO(client_monitor_latency); +static ssize_t server_monitor_conn_id_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_conn_id(hv_dev->channel, + vmbus_connection.monitor_pages[0])); +} +static DEVICE_ATTR_RO(server_monitor_conn_id); + +static ssize_t client_monitor_conn_id_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + return sprintf(buf, "%d\n", + channel_conn_id(hv_dev->channel, + vmbus_connection.monitor_pages[1])); +} +static DEVICE_ATTR_RO(client_monitor_conn_id); + static struct attribute *vmbus_attrs[] = { &dev_attr_id.attr, &dev_attr_state.attr, @@ -319,16 +342,14 @@ static struct attribute *vmbus_attrs[] = { &dev_attr_client_monitor_pending.attr, &dev_attr_server_monitor_latency.attr, &dev_attr_client_monitor_latency.attr, + &dev_attr_server_monitor_conn_id.attr, + &dev_attr_client_monitor_conn_id.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus); /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct device_attribute vmbus_device_attrs[] = { - __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - - __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL), - __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL), __ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL), diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index ec1e5033bb99..332e80ce9b8a 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -900,9 +900,6 @@ enum vmbus_channel_state { }; struct vmbus_channel_debug_info { - u32 servermonitor_connectionid; - u32 clientmonitor_connectionid; - struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info outbound; }; -- cgit From 2c9be3eacc39948af2341595322c014833699ac5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:32:59 -0700 Subject: hv: delete vmbus_get_debug_info() It's only used once, only contains 2 function calls, so just make those calls directly, deleting the function, and the now unneeded structure entirely. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 10 ---------- drivers/hv/vmbus_drv.c | 35 ++++++++++++++++------------------- include/linux/hyperv.h | 8 -------- 3 files changed, 16 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 75c26da3e011..94d54591b226 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -59,16 +59,6 @@ static void vmbus_setevent(struct vmbus_channel *channel) } } -/* - * vmbus_get_debug_info -Retrieve various channel debug info - */ -void vmbus_get_debug_info(struct vmbus_channel *channel, - struct vmbus_channel_debug_info *debuginfo) -{ - hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound); - hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound); -} - /* * vmbus_open - Open the specified channel. */ diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 73cb456e256b..62d9311b0541 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -63,29 +63,26 @@ static int vmbus_exists(void) static void get_channel_info(struct hv_device *device, struct hv_device_info *info) { - struct vmbus_channel_debug_info debug_info; + struct hv_ring_buffer_debug_info inbound; + struct hv_ring_buffer_debug_info outbound; if (!device->channel) return; - vmbus_get_debug_info(device->channel, &debug_info); - - info->inbound.int_mask = debug_info.inbound.current_interrupt_mask; - info->inbound.read_idx = debug_info.inbound.current_read_index; - info->inbound.write_idx = debug_info.inbound.current_write_index; - info->inbound.bytes_avail_toread = - debug_info.inbound.bytes_avail_toread; - info->inbound.bytes_avail_towrite = - debug_info.inbound.bytes_avail_towrite; - - info->outbound.int_mask = - debug_info.outbound.current_interrupt_mask; - info->outbound.read_idx = debug_info.outbound.current_read_index; - info->outbound.write_idx = debug_info.outbound.current_write_index; - info->outbound.bytes_avail_toread = - debug_info.outbound.bytes_avail_toread; - info->outbound.bytes_avail_towrite = - debug_info.outbound.bytes_avail_towrite; + hv_ringbuffer_get_debuginfo(&device->channel->inbound, &inbound); + hv_ringbuffer_get_debuginfo(&device->channel->outbound, &outbound); + + info->inbound.int_mask = inbound.current_interrupt_mask; + info->inbound.read_idx = inbound.current_read_index; + info->inbound.write_idx = inbound.current_write_index; + info->inbound.bytes_avail_toread = inbound.bytes_avail_toread; + info->inbound.bytes_avail_towrite = inbound.bytes_avail_towrite; + + info->outbound.int_mask = outbound.current_interrupt_mask; + info->outbound.read_idx = outbound.current_read_index; + info->outbound.write_idx = outbound.current_write_index; + info->outbound.bytes_avail_toread = outbound.bytes_avail_toread; + info->outbound.bytes_avail_towrite = outbound.bytes_avail_towrite; } #define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 332e80ce9b8a..c0e8faf40b35 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -899,11 +899,6 @@ enum vmbus_channel_state { CHANNEL_OPENED_STATE, }; -struct vmbus_channel_debug_info { - struct hv_ring_buffer_debug_info inbound; - struct hv_ring_buffer_debug_info outbound; -}; - /* * Represents each channel msg on the vmbus connection This is a * variable-size data structure depending on the msg type itself @@ -1169,9 +1164,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, u64 *requestid); -extern void vmbus_get_debug_info(struct vmbus_channel *channel, - struct vmbus_channel_debug_info *debug); - extern void vmbus_ontimer(unsigned long data); struct hv_dev_port_info { -- cgit From 1fdde16d1f93376ad2a2df769f756572c2e84cbd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Sep 2013 11:33:00 -0700 Subject: hv: delete struct hv_dev_port_info It's no longer needed, and the struct hv_ring_buffer_debug_info structure shouldn't be "global" so move it to the local .h file instead. Tested-by: "K. Y. Srinivasan" Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hyperv_vmbus.h | 7 +++++++ drivers/hv/vmbus_drv.c | 35 ++++++++++------------------------- include/linux/hyperv.h | 17 ----------------- 3 files changed, 17 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index d58c22ffb29a..e05517616a06 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -514,6 +514,13 @@ struct hv_context { extern struct hv_context hv_context; +struct hv_ring_buffer_debug_info { + u32 current_interrupt_mask; + u32 current_read_index; + u32 current_write_index; + u32 bytes_avail_toread; + u32 bytes_avail_towrite; +}; /* Hv Interface */ diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 62d9311b0541..cf3220e8a3a6 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -47,8 +47,8 @@ static struct completion probe_event; static int irq; struct hv_device_info { - struct hv_dev_port_info inbound; - struct hv_dev_port_info outbound; + struct hv_ring_buffer_debug_info inbound; + struct hv_ring_buffer_debug_info outbound; }; static int vmbus_exists(void) @@ -63,26 +63,11 @@ static int vmbus_exists(void) static void get_channel_info(struct hv_device *device, struct hv_device_info *info) { - struct hv_ring_buffer_debug_info inbound; - struct hv_ring_buffer_debug_info outbound; - if (!device->channel) return; - hv_ringbuffer_get_debuginfo(&device->channel->inbound, &inbound); - hv_ringbuffer_get_debuginfo(&device->channel->outbound, &outbound); - - info->inbound.int_mask = inbound.current_interrupt_mask; - info->inbound.read_idx = inbound.current_read_index; - info->inbound.write_idx = inbound.current_write_index; - info->inbound.bytes_avail_toread = inbound.bytes_avail_toread; - info->inbound.bytes_avail_towrite = inbound.bytes_avail_towrite; - - info->outbound.int_mask = outbound.current_interrupt_mask; - info->outbound.read_idx = outbound.current_read_index; - info->outbound.write_idx = outbound.current_write_index; - info->outbound.bytes_avail_toread = outbound.bytes_avail_toread; - info->outbound.bytes_avail_towrite = outbound.bytes_avail_towrite; + hv_ringbuffer_get_debuginfo(&device->channel->inbound, &info->inbound); + hv_ringbuffer_get_debuginfo(&device->channel->outbound, &info->outbound); } #define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2) @@ -114,11 +99,11 @@ static ssize_t vmbus_show_device_attr(struct device *dev, get_channel_info(hv_dev, device_info); if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { - ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); + ret = sprintf(buf, "%d\n", device_info->outbound.current_interrupt_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { - ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); + ret = sprintf(buf, "%d\n", device_info->outbound.current_read_index); } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { - ret = sprintf(buf, "%d\n", device_info->outbound.write_idx); + ret = sprintf(buf, "%d\n", device_info->outbound.current_write_index); } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->outbound.bytes_avail_toread); @@ -126,11 +111,11 @@ static ssize_t vmbus_show_device_attr(struct device *dev, ret = sprintf(buf, "%d\n", device_info->outbound.bytes_avail_towrite); } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { - ret = sprintf(buf, "%d\n", device_info->inbound.int_mask); + ret = sprintf(buf, "%d\n", device_info->inbound.current_interrupt_mask); } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { - ret = sprintf(buf, "%d\n", device_info->inbound.read_idx); + ret = sprintf(buf, "%d\n", device_info->inbound.current_read_index); } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { - ret = sprintf(buf, "%d\n", device_info->inbound.write_idx); + ret = sprintf(buf, "%d\n", device_info->inbound.current_write_index); } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_toread); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c0e8faf40b35..c68ecfe29441 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -429,15 +429,6 @@ struct hv_ring_buffer_info { u32 ring_data_startoffset; }; -struct hv_ring_buffer_debug_info { - u32 current_interrupt_mask; - u32 current_read_index; - u32 current_write_index; - u32 bytes_avail_toread; - u32 bytes_avail_towrite; -}; - - /* * * hv_get_ringbuffer_availbytes() @@ -1166,14 +1157,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, extern void vmbus_ontimer(unsigned long data); -struct hv_dev_port_info { - u32 int_mask; - u32 read_idx; - u32 write_idx; - u32 bytes_avail_toread; - u32 bytes_avail_towrite; -}; - /* Base driver object */ struct hv_driver { const char *name; -- cgit From 2f268f129c2d1a05d297fe3ee34d393f862d2b22 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Wed, 25 Sep 2013 09:20:07 +0200 Subject: net: add adj_list to save only neighbours Currently, we distinguish neighbours (first-level linked devices) from non-neighbours by the neighbour bool in the netdev_adjacent. This could be quite time-consuming in case we would like to traverse *only* through neighbours - cause we'd have to traverse through all devices and check for this flag, and in a (quite common) scenario where we have lots of vlans on top of bridge, which is on top of a bond - the bonding would have to go through all those vlans to get its upper neighbour linked devices. This situation is really unpleasant, cause there are already a lot of cases when a device with slaves needs to go through them in hot path. To fix this, introduce a new upper/lower device lists structure - adj_list, which contains only the neighbours. It works always in pair with the all_adj_list structure (renamed from upper/lower_dev_list), i.e. both of them contain the same links, only that all_adj_list contains also non-neighbour device links. It's really a small change visible, currently, only for __netdev_adjacent_dev_insert/remove(), and doesn't change the main linked logic at all. Also, add some comments a fix a name collision in netdev_for_each_upper_dev_rcu() and rework the naming by the following rules: netdev_(all_)(upper|lower)_* If "all_" is present, then we work with the whole list of upper/lower devices, otherwise - only with direct neighbours. Uninline functions - to get better stack traces. CC: "David S. Miller" CC: Eric Dumazet CC: Jiri Pirko CC: Alexander Duyck CC: Cong Wang Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 2 +- drivers/net/bonding/bond_main.c | 10 +- include/linux/netdevice.h | 28 ++++-- net/core/dev.c | 203 ++++++++++++++++++++-------------------- 4 files changed, 129 insertions(+), 114 deletions(-) (limited to 'include') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f428ef574372..8524e33e6754 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1019,7 +1019,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) /* loop through vlans and send one packet for each */ rcu_read_lock(); - netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { + netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { if (upper->priv_flags & IFF_802_1Q_VLAN) alb_send_lp_vid(slave, mac_addr, vlan_dev_vlan_id(upper)); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 55bbb8b8200c..91c4ab8913b1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2267,7 +2267,7 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip) return true; rcu_read_lock(); - netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { + netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { if (ip == bond_confirm_addr(upper, 0, ip)) { ret = true; break; @@ -2342,10 +2342,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) * * TODO: QinQ? */ - netdev_for_each_upper_dev_rcu(bond->dev, vlan_upper, vlan_iter) { + netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper, + vlan_iter) { if (!is_vlan_dev(vlan_upper)) continue; - netdev_for_each_upper_dev_rcu(vlan_upper, upper, iter) { + netdev_for_each_all_upper_dev_rcu(vlan_upper, upper, + iter) { if (upper == rt->dst.dev) { vlan_id = vlan_dev_vlan_id(vlan_upper); rcu_read_unlock(); @@ -2358,7 +2360,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) * our upper vlans, then just search for any dev that * matches, and in case it's a vlan - save the id */ - netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { + netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { if (upper == rt->dst.dev) { /* if it's a vlan - get its VID */ if (is_vlan_dev(upper)) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3de49aca4519..514045c704a8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1143,8 +1143,18 @@ struct net_device { struct list_head dev_list; struct list_head napi_list; struct list_head unreg_list; - struct list_head upper_dev_list; /* List of upper devices */ - struct list_head lower_dev_list; + + /* directly linked devices, like slaves for bonding */ + struct { + struct list_head upper; + struct list_head lower; + } adj_list; + + /* all linked devices, *including* neighbours */ + struct { + struct list_head upper; + struct list_head lower; + } all_adj_list; /* currently active device features */ @@ -2813,15 +2823,15 @@ extern int bpf_jit_enable; extern bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev); extern bool netdev_has_any_upper_dev(struct net_device *dev); -extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, - struct list_head **iter); +extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, + struct list_head **iter); /* iterate through upper list, must be called under RCU read lock */ -#define netdev_for_each_upper_dev_rcu(dev, upper, iter) \ - for (iter = &(dev)->upper_dev_list, \ - upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \ - upper; \ - upper = netdev_upper_get_next_dev_rcu(dev, &(iter))) +#define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \ + for (iter = &(dev)->all_adj_list.upper, \ + updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \ + updev; \ + updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter))) extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev); extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index 9be79377a0f3..9a395e03da74 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4373,9 +4373,6 @@ struct netdev_adjacent { /* upper master flag, there can only be one master device per list */ bool master; - /* indicates that this dev is our first-level lower/upper device */ - bool neighbour; - /* counter for the number of times this device was added to us */ u16 ref_nr; @@ -4385,29 +4382,17 @@ struct netdev_adjacent { static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev, struct net_device *adj_dev, - struct list_head *dev_list) + struct list_head *adj_list) { struct netdev_adjacent *adj; - list_for_each_entry(adj, dev_list, list) { + list_for_each_entry(adj, adj_list, list) { if (adj->dev == adj_dev) return adj; } return NULL; } -static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev, - struct net_device *udev) -{ - return __netdev_find_adj(dev, udev, &dev->upper_dev_list); -} - -static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev, - struct net_device *ldev) -{ - return __netdev_find_adj(dev, ldev, &dev->lower_dev_list); -} - /** * netdev_has_upper_dev - Check if device is linked to an upper device * @dev: device @@ -4422,7 +4407,7 @@ bool netdev_has_upper_dev(struct net_device *dev, { ASSERT_RTNL(); - return __netdev_find_upper(dev, upper_dev); + return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper); } EXPORT_SYMBOL(netdev_has_upper_dev); @@ -4437,7 +4422,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev) { ASSERT_RTNL(); - return !list_empty(&dev->upper_dev_list); + return !list_empty(&dev->all_adj_list.upper); } EXPORT_SYMBOL(netdev_has_any_upper_dev); @@ -4454,10 +4439,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) ASSERT_RTNL(); - if (list_empty(&dev->upper_dev_list)) + if (list_empty(&dev->adj_list.upper)) return NULL; - upper = list_first_entry(&dev->upper_dev_list, + upper = list_first_entry(&dev->adj_list.upper, struct netdev_adjacent, list); if (likely(upper->master)) return upper->dev; @@ -4465,15 +4450,15 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) } EXPORT_SYMBOL(netdev_master_upper_dev_get); -/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list +/* netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list * @dev: device * @iter: list_head ** of the current position * * Gets the next device from the dev's upper list, starting from iter * position. The caller must hold RCU read lock. */ -struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, - struct list_head **iter) +struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, + struct list_head **iter) { struct netdev_adjacent *upper; @@ -4481,14 +4466,14 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); - if (&upper->list == &dev->upper_dev_list) + if (&upper->list == &dev->all_adj_list.upper) return NULL; *iter = &upper->list; return upper->dev; } -EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); +EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu); /** * netdev_master_upper_dev_get_rcu - Get master upper device @@ -4501,7 +4486,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev) { struct netdev_adjacent *upper; - upper = list_first_or_null_rcu(&dev->upper_dev_list, + upper = list_first_or_null_rcu(&dev->adj_list.upper, struct netdev_adjacent, list); if (upper && likely(upper->master)) return upper->dev; @@ -4512,14 +4497,13 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); static int __netdev_adjacent_dev_insert(struct net_device *dev, struct net_device *adj_dev, struct list_head *dev_list, - bool neighbour, bool master) + bool master) { struct netdev_adjacent *adj; adj = __netdev_find_adj(dev, adj_dev, dev_list); if (adj) { - BUG_ON(neighbour); adj->ref_nr++; return 0; } @@ -4530,13 +4514,11 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, adj->dev = adj_dev; adj->master = master; - adj->neighbour = neighbour; adj->ref_nr = 1; - dev_hold(adj_dev); - pr_debug("dev_hold for %s, because of %s link added from %s to %s\n", - adj_dev->name, dev_list == &dev->upper_dev_list ? - "upper" : "lower", dev->name, adj_dev->name); + + pr_debug("dev_hold for %s, because of link added from %s to %s\n", + adj_dev->name, dev->name, adj_dev->name); /* Ensure that master link is always the first item in list. */ if (master) @@ -4547,22 +4529,6 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, return 0; } -static inline int __netdev_upper_dev_insert(struct net_device *dev, - struct net_device *udev, - bool master, bool neighbour) -{ - return __netdev_adjacent_dev_insert(dev, udev, &dev->upper_dev_list, - neighbour, master); -} - -static inline int __netdev_lower_dev_insert(struct net_device *dev, - struct net_device *ldev, - bool neighbour) -{ - return __netdev_adjacent_dev_insert(dev, ldev, &dev->lower_dev_list, - neighbour, false); -} - void __netdev_adjacent_dev_remove(struct net_device *dev, struct net_device *adj_dev, struct list_head *dev_list) @@ -4571,73 +4537,102 @@ void __netdev_adjacent_dev_remove(struct net_device *dev, adj = __netdev_find_adj(dev, adj_dev, dev_list); - if (!adj) + if (!adj) { + pr_err("tried to remove device %s from %s\n", + dev->name, adj_dev->name); BUG(); + } if (adj->ref_nr > 1) { + pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name, + adj->ref_nr-1); adj->ref_nr--; return; } list_del_rcu(&adj->list); - pr_debug("dev_put for %s, because of %s link removed from %s to %s\n", - adj_dev->name, dev_list == &dev->upper_dev_list ? - "upper" : "lower", dev->name, adj_dev->name); + pr_debug("dev_put for %s, because link removed from %s to %s\n", + adj_dev->name, dev->name, adj_dev->name); dev_put(adj_dev); kfree_rcu(adj, rcu); } -static inline void __netdev_upper_dev_remove(struct net_device *dev, - struct net_device *udev) -{ - return __netdev_adjacent_dev_remove(dev, udev, &dev->upper_dev_list); -} - -static inline void __netdev_lower_dev_remove(struct net_device *dev, - struct net_device *ldev) -{ - return __netdev_adjacent_dev_remove(dev, ldev, &dev->lower_dev_list); -} - -int __netdev_adjacent_dev_insert_link(struct net_device *dev, - struct net_device *upper_dev, - bool master, bool neighbour) +int __netdev_adjacent_dev_link_lists(struct net_device *dev, + struct net_device *upper_dev, + struct list_head *up_list, + struct list_head *down_list, + bool master) { int ret; - ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour); + ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master); if (ret) return ret; - ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour); + ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false); if (ret) { - __netdev_upper_dev_remove(dev, upper_dev); + __netdev_adjacent_dev_remove(dev, upper_dev, up_list); return ret; } return 0; } -static inline int __netdev_adjacent_dev_link(struct net_device *dev, - struct net_device *udev) +int __netdev_adjacent_dev_link(struct net_device *dev, + struct net_device *upper_dev) { - return __netdev_adjacent_dev_insert_link(dev, udev, false, false); + return __netdev_adjacent_dev_link_lists(dev, upper_dev, + &dev->all_adj_list.upper, + &upper_dev->all_adj_list.lower, + false); } -static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, - struct net_device *udev, - bool master) +void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, + struct net_device *upper_dev, + struct list_head *up_list, + struct list_head *down_list) { - return __netdev_adjacent_dev_insert_link(dev, udev, master, true); + __netdev_adjacent_dev_remove(dev, upper_dev, up_list); + __netdev_adjacent_dev_remove(upper_dev, dev, down_list); } void __netdev_adjacent_dev_unlink(struct net_device *dev, struct net_device *upper_dev) { - __netdev_upper_dev_remove(dev, upper_dev); - __netdev_lower_dev_remove(upper_dev, dev); + __netdev_adjacent_dev_unlink_lists(dev, upper_dev, + &dev->all_adj_list.upper, + &upper_dev->all_adj_list.lower); +} + +int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, + struct net_device *upper_dev, + bool master) +{ + int ret = __netdev_adjacent_dev_link(dev, upper_dev); + + if (ret) + return ret; + + ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, + &dev->adj_list.upper, + &upper_dev->adj_list.lower, + master); + if (ret) { + __netdev_adjacent_dev_unlink(dev, upper_dev); + return ret; + } + + return 0; } +void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, + struct net_device *upper_dev) +{ + __netdev_adjacent_dev_unlink(dev, upper_dev); + __netdev_adjacent_dev_unlink_lists(dev, upper_dev, + &dev->adj_list.upper, + &upper_dev->adj_list.lower); +} static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master) @@ -4651,10 +4646,10 @@ static int __netdev_upper_dev_link(struct net_device *dev, return -EBUSY; /* To prevent loops, check if dev is not upper device to upper_dev. */ - if (__netdev_find_upper(upper_dev, dev)) + if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) return -EBUSY; - if (__netdev_find_upper(dev, upper_dev)) + if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) return -EEXIST; if (master && netdev_master_upper_dev_get(dev)) @@ -4665,12 +4660,14 @@ static int __netdev_upper_dev_link(struct net_device *dev, return ret; /* Now that we linked these devs, make all the upper_dev's - * upper_dev_list visible to every dev's lower_dev_list and vice + * all_adj_list.upper visible to every dev's all_adj_list.lower an * versa, and don't forget the devices itself. All of these * links are non-neighbours. */ - list_for_each_entry(i, &dev->lower_dev_list, list) { - list_for_each_entry(j, &upper_dev->upper_dev_list, list) { + list_for_each_entry(i, &dev->all_adj_list.lower, list) { + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { + pr_debug("Interlinking %s with %s, non-neighbour\n", + i->dev->name, j->dev->name); ret = __netdev_adjacent_dev_link(i->dev, j->dev); if (ret) goto rollback_mesh; @@ -4678,14 +4675,18 @@ static int __netdev_upper_dev_link(struct net_device *dev, } /* add dev to every upper_dev's upper device */ - list_for_each_entry(i, &upper_dev->upper_dev_list, list) { + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { + pr_debug("linking %s's upper device %s with %s\n", + upper_dev->name, i->dev->name, dev->name); ret = __netdev_adjacent_dev_link(dev, i->dev); if (ret) goto rollback_upper_mesh; } /* add upper_dev to every dev's lower device */ - list_for_each_entry(i, &dev->lower_dev_list, list) { + list_for_each_entry(i, &dev->all_adj_list.lower, list) { + pr_debug("linking %s's lower device %s with %s\n", dev->name, + i->dev->name, upper_dev->name); ret = __netdev_adjacent_dev_link(i->dev, upper_dev); if (ret) goto rollback_lower_mesh; @@ -4696,7 +4697,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, rollback_lower_mesh: to_i = i; - list_for_each_entry(i, &dev->lower_dev_list, list) { + list_for_each_entry(i, &dev->all_adj_list.lower, list) { if (i == to_i) break; __netdev_adjacent_dev_unlink(i->dev, upper_dev); @@ -4706,7 +4707,7 @@ rollback_lower_mesh: rollback_upper_mesh: to_i = i; - list_for_each_entry(i, &upper_dev->upper_dev_list, list) { + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { if (i == to_i) break; __netdev_adjacent_dev_unlink(dev, i->dev); @@ -4717,8 +4718,8 @@ rollback_upper_mesh: rollback_mesh: to_i = i; to_j = j; - list_for_each_entry(i, &dev->lower_dev_list, list) { - list_for_each_entry(j, &upper_dev->upper_dev_list, list) { + list_for_each_entry(i, &dev->all_adj_list.lower, list) { + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { if (i == to_i && j == to_j) break; __netdev_adjacent_dev_unlink(i->dev, j->dev); @@ -4727,7 +4728,7 @@ rollback_mesh: break; } - __netdev_adjacent_dev_unlink(dev, upper_dev); + __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); return ret; } @@ -4781,23 +4782,23 @@ void netdev_upper_dev_unlink(struct net_device *dev, struct netdev_adjacent *i, *j; ASSERT_RTNL(); - __netdev_adjacent_dev_unlink(dev, upper_dev); + __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); /* Here is the tricky part. We must remove all dev's lower * devices from all upper_dev's upper devices and vice * versa, to maintain the graph relationship. */ - list_for_each_entry(i, &dev->lower_dev_list, list) - list_for_each_entry(j, &upper_dev->upper_dev_list, list) + list_for_each_entry(i, &dev->all_adj_list.lower, list) + list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) __netdev_adjacent_dev_unlink(i->dev, j->dev); /* remove also the devices itself from lower/upper device * list */ - list_for_each_entry(i, &dev->lower_dev_list, list) + list_for_each_entry(i, &dev->all_adj_list.lower, list) __netdev_adjacent_dev_unlink(i->dev, upper_dev); - list_for_each_entry(i, &upper_dev->upper_dev_list, list) + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) __netdev_adjacent_dev_unlink(dev, i->dev); call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); @@ -6059,8 +6060,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); INIT_LIST_HEAD(&dev->link_watch_list); - INIT_LIST_HEAD(&dev->upper_dev_list); - INIT_LIST_HEAD(&dev->lower_dev_list); + INIT_LIST_HEAD(&dev->adj_list.upper); + INIT_LIST_HEAD(&dev->adj_list.lower); + INIT_LIST_HEAD(&dev->all_adj_list.upper); + INIT_LIST_HEAD(&dev->all_adj_list.lower); dev->priv_flags = IFF_XMIT_DST_RELEASE; setup(dev); -- cgit From 402dae9614557296e84543008a8e582c28fb1db3 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Wed, 25 Sep 2013 09:20:09 +0200 Subject: net: add netdev_adjacent->private and allow to use it Currently, even though we can access any linked device, we can't attach anything to it, which is vital to properly manage them. To fix this, add a new void *private to netdev_adjacent and functions setting/getting it (per link), so that we can save, per example, bonding's slave structures there, per slave device. netdev_master_upper_dev_link_private(dev, upper_dev, private) links dev to upper dev and populates the neighbour link only with private. netdev_lower_dev_get_private{,_rcu}() returns the private, if found. CC: "David S. Miller" CC: Eric Dumazet CC: Jiri Pirko CC: Alexander Duyck Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 +++++ net/core/dev.c | 68 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 514045c704a8..75d5beac463b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2839,8 +2839,15 @@ extern int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); extern int netdev_master_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); +extern int netdev_master_upper_dev_link_private(struct net_device *dev, + struct net_device *upper_dev, + void *private); extern void netdev_upper_dev_unlink(struct net_device *dev, struct net_device *upper_dev); +extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev, + struct net_device *lower_dev); +extern void *netdev_lower_dev_get_private(struct net_device *dev, + struct net_device *lower_dev); extern int skb_checksum_help(struct sk_buff *skb); extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path); diff --git a/net/core/dev.c b/net/core/dev.c index 9290f09cdf26..c69ab74fb201 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4376,6 +4376,9 @@ struct netdev_adjacent { /* counter for the number of times this device was added to us */ u16 ref_nr; + /* private field for the users */ + void *private; + struct list_head list; struct rcu_head rcu; }; @@ -4510,7 +4513,7 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); static int __netdev_adjacent_dev_insert(struct net_device *dev, struct net_device *adj_dev, struct list_head *dev_list, - bool master) + void *private, bool master) { struct netdev_adjacent *adj; @@ -4528,6 +4531,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, adj->dev = adj_dev; adj->master = master; adj->ref_nr = 1; + adj->private = private; dev_hold(adj_dev); pr_debug("dev_hold for %s, because of link added from %s to %s\n", @@ -4574,15 +4578,17 @@ int __netdev_adjacent_dev_link_lists(struct net_device *dev, struct net_device *upper_dev, struct list_head *up_list, struct list_head *down_list, - bool master) + void *private, bool master) { int ret; - ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master); + ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, + master); if (ret) return ret; - ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false); + ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, + false); if (ret) { __netdev_adjacent_dev_remove(dev, upper_dev, up_list); return ret; @@ -4597,7 +4603,7 @@ int __netdev_adjacent_dev_link(struct net_device *dev, return __netdev_adjacent_dev_link_lists(dev, upper_dev, &dev->all_adj_list.upper, &upper_dev->all_adj_list.lower, - false); + NULL, false); } void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, @@ -4619,7 +4625,7 @@ void __netdev_adjacent_dev_unlink(struct net_device *dev, int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, struct net_device *upper_dev, - bool master) + void *private, bool master) { int ret = __netdev_adjacent_dev_link(dev, upper_dev); @@ -4629,7 +4635,7 @@ int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, &dev->adj_list.upper, &upper_dev->adj_list.lower, - master); + private, master); if (ret) { __netdev_adjacent_dev_unlink(dev, upper_dev); return ret; @@ -4648,7 +4654,8 @@ void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, } static int __netdev_upper_dev_link(struct net_device *dev, - struct net_device *upper_dev, bool master) + struct net_device *upper_dev, bool master, + void *private) { struct netdev_adjacent *i, *j, *to_i, *to_j; int ret = 0; @@ -4668,7 +4675,8 @@ static int __netdev_upper_dev_link(struct net_device *dev, if (master && netdev_master_upper_dev_get(dev)) return -EBUSY; - ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master); + ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private, + master); if (ret) return ret; @@ -4759,7 +4767,7 @@ rollback_mesh: int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev) { - return __netdev_upper_dev_link(dev, upper_dev, false); + return __netdev_upper_dev_link(dev, upper_dev, false, NULL); } EXPORT_SYMBOL(netdev_upper_dev_link); @@ -4777,10 +4785,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link); int netdev_master_upper_dev_link(struct net_device *dev, struct net_device *upper_dev) { - return __netdev_upper_dev_link(dev, upper_dev, true); + return __netdev_upper_dev_link(dev, upper_dev, true, NULL); } EXPORT_SYMBOL(netdev_master_upper_dev_link); +int netdev_master_upper_dev_link_private(struct net_device *dev, + struct net_device *upper_dev, + void *private) +{ + return __netdev_upper_dev_link(dev, upper_dev, true, private); +} +EXPORT_SYMBOL(netdev_master_upper_dev_link_private); + /** * netdev_upper_dev_unlink - Removes a link to upper device * @dev: device @@ -4818,6 +4834,36 @@ void netdev_upper_dev_unlink(struct net_device *dev, } EXPORT_SYMBOL(netdev_upper_dev_unlink); +void *netdev_lower_dev_get_private_rcu(struct net_device *dev, + struct net_device *lower_dev) +{ + struct netdev_adjacent *lower; + + if (!lower_dev) + return NULL; + lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower); + if (!lower) + return NULL; + + return lower->private; +} +EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu); + +void *netdev_lower_dev_get_private(struct net_device *dev, + struct net_device *lower_dev) +{ + struct netdev_adjacent *lower; + + if (!lower_dev) + return NULL; + lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower); + if (!lower) + return NULL; + + return lower->private; +} +EXPORT_SYMBOL(netdev_lower_dev_get_private); + static void dev_change_rx_flags(struct net_device *dev, int flags) { const struct net_device_ops *ops = dev->netdev_ops; -- cgit From 31088a113c2a948856ed2047d8c21c217b13e85d Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Wed, 25 Sep 2013 09:20:12 +0200 Subject: net: add for_each iterators through neighbour lower link's private Add a possibility to iterate through netdev_adjacent's private, currently only for lower neighbours. Add both RCU and RTNL/other locking variants of iterators, and make the non-rcu variant to be safe from removal. CC: "David S. Miller" CC: Eric Dumazet CC: Jiri Pirko CC: Alexander Duyck Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- include/linux/netdevice.h | 17 ++++++++++++++ net/core/dev.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 75d5beac463b..168974e40cf5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2833,6 +2833,23 @@ extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *d updev; \ updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter))) +extern void *netdev_lower_get_next_private(struct net_device *dev, + struct list_head **iter); +extern void *netdev_lower_get_next_private_rcu(struct net_device *dev, + struct list_head **iter); + +#define netdev_for_each_lower_private(dev, priv, iter) \ + for (iter = (dev)->adj_list.lower.next, \ + priv = netdev_lower_get_next_private(dev, &(iter)); \ + priv; \ + priv = netdev_lower_get_next_private(dev, &(iter))) + +#define netdev_for_each_lower_private_rcu(dev, priv, iter) \ + for (iter = &(dev)->adj_list.lower, \ + priv = netdev_lower_get_next_private_rcu(dev, &(iter)); \ + priv; \ + priv = netdev_lower_get_next_private_rcu(dev, &(iter))) + extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev); extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); extern int netdev_upper_dev_link(struct net_device *dev, diff --git a/net/core/dev.c b/net/core/dev.c index c69ab74fb201..0aa844aae40b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4466,7 +4466,8 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) } EXPORT_SYMBOL(netdev_master_upper_dev_get); -/* netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list +/** + * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list * @dev: device * @iter: list_head ** of the current position * @@ -4491,6 +4492,63 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, } EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu); +/** + * netdev_lower_get_next_private - Get the next ->private from the + * lower neighbour list + * @dev: device + * @iter: list_head ** of the current position + * + * Gets the next netdev_adjacent->private from the dev's lower neighbour + * list, starting from iter position. The caller must hold either hold the + * RTNL lock or its own locking that guarantees that the neighbour lower + * list will remain unchainged. + */ +void *netdev_lower_get_next_private(struct net_device *dev, + struct list_head **iter) +{ + struct netdev_adjacent *lower; + + lower = list_entry(*iter, struct netdev_adjacent, list); + + if (&lower->list == &dev->adj_list.lower) + return NULL; + + if (iter) + *iter = lower->list.next; + + return lower->private; +} +EXPORT_SYMBOL(netdev_lower_get_next_private); + +/** + * netdev_lower_get_next_private_rcu - Get the next ->private from the + * lower neighbour list, RCU + * variant + * @dev: device + * @iter: list_head ** of the current position + * + * Gets the next netdev_adjacent->private from the dev's lower neighbour + * list, starting from iter position. The caller must hold RCU read lock. + */ +void *netdev_lower_get_next_private_rcu(struct net_device *dev, + struct list_head **iter) +{ + struct netdev_adjacent *lower; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); + + if (&lower->list == &dev->adj_list.lower) + return NULL; + + if (iter) + *iter = &lower->list; + + return lower->private; +} +EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); + /** * netdev_master_upper_dev_get_rcu - Get master upper device * @dev: device -- cgit From b6ccba4c681fdaf0070e580bf951badf7edc860b Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Wed, 25 Sep 2013 09:20:23 +0200 Subject: net: add a possibility to get private from netdev_adjacent->list It will be useful to get first/last element. CC: "David S. Miller" CC: Eric Dumazet CC: Jiri Pirko CC: Alexander Duyck Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + net/core/dev.c | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 168974e40cf5..b4cfb63f264e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2850,6 +2850,7 @@ extern void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv; \ priv = netdev_lower_get_next_private_rcu(dev, &(iter))) +extern void *netdev_adjacent_get_private(struct list_head *adj_list); extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev); extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); extern int netdev_upper_dev_link(struct net_device *dev, diff --git a/net/core/dev.c b/net/core/dev.c index 0aa844aae40b..acc11810805f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4466,6 +4466,16 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) } EXPORT_SYMBOL(netdev_master_upper_dev_get); +void *netdev_adjacent_get_private(struct list_head *adj_list) +{ + struct netdev_adjacent *adj; + + adj = list_entry(adj_list, struct netdev_adjacent, list); + + return adj->private; +} +EXPORT_SYMBOL(netdev_adjacent_get_private); + /** * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list * @dev: device -- cgit From 3a6a9201897c6482573ad07ee880574147761006 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Thu, 5 Sep 2013 16:41:55 -0700 Subject: Intel MIC Host Driver, card OS state management. This patch enables the following features: a) Boots and shuts down the card via sysfs entries. b) Allocates and maps a device page for communication with the card driver and updates the device page address via scratchpad registers. c) Provides sysfs entries for shutdown status, kernel command line, ramdisk and log buffer information. Co-author: Dasaratharaman Chandramouli Signed-off-by: Ashutosh Dixit Signed-off-by: Caz Yokoyama Signed-off-by: Dasaratharaman Chandramouli Signed-off-by: Harshavardhan R Kharche Signed-off-by: Nikhil Rao Signed-off-by: Sudeep Dutt Acked-by: Yaozu (Eddie) Dong Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-mic.txt | 113 ++++++++ drivers/misc/mic/common/mic_device.h | 7 + drivers/misc/mic/host/Makefile | 2 + drivers/misc/mic/host/mic_boot.c | 184 +++++++++++++ drivers/misc/mic/host/mic_debugfs.c | 355 +++++++++++++++++++++++++ drivers/misc/mic/host/mic_device.h | 60 +++++ drivers/misc/mic/host/mic_main.c | 129 ++++++++- drivers/misc/mic/host/mic_sysfs.c | 369 ++++++++++++++++++++++++++ drivers/misc/mic/host/mic_x100.c | 251 ++++++++++++++++++ drivers/misc/mic/host/mic_x100.h | 12 + include/uapi/linux/Kbuild | 1 + include/uapi/linux/mic_common.h | 74 ++++++ 12 files changed, 1553 insertions(+), 4 deletions(-) create mode 100644 drivers/misc/mic/host/mic_boot.c create mode 100644 drivers/misc/mic/host/mic_debugfs.c create mode 100644 include/uapi/linux/mic_common.h (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-class-mic.txt b/Documentation/ABI/testing/sysfs-class-mic.txt index 09eb3c6d0237..82cdad3b614a 100644 --- a/Documentation/ABI/testing/sysfs-class-mic.txt +++ b/Documentation/ABI/testing/sysfs-class-mic.txt @@ -32,3 +32,116 @@ Contact: Sudeep Dutt Description: Provides information about the silicon stepping for an Intel MIC device. For example - "A0" or "B0" + +What: /sys/class/mic/mic(x)/state +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + When read, this entry provides the current state of an Intel + MIC device in the context of the card OS. Possible values that + will be read are: + "offline" - The MIC device is ready to boot the card OS. + "online" - The MIC device has initiated booting a card OS. + "shutting_down" - The card OS is shutting down. + "reset_failed" - The MIC device has failed to reset. + + When written, this sysfs entry triggers different state change + operations depending upon the current state of the card OS. + Acceptable values are: + "boot" - Boot the card OS image specified by the combination + of firmware, ramdisk, cmdline and bootmode + sysfs entries. + "reset" - Initiates device reset. + "shutdown" - Initiates card OS shutdown. + +What: /sys/class/mic/mic(x)/shutdown_status +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + An Intel MIC device runs a Linux OS during its operation. This + OS can shutdown because of various reasons. When read, this + entry provides the status on why the card OS was shutdown. + Possible values are: + "nop" - shutdown status is not applicable, when the card OS is + "online" + "crashed" - Shutdown because of a HW or SW crash. + "halted" - Shutdown because of a halt command. + "poweroff" - Shutdown because of a poweroff command. + "restart" - Shutdown because of a restart command. + +What: /sys/class/mic/mic(x)/cmdline +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + An Intel MIC device runs a Linux OS during its operation. Before + booting this card OS, it is possible to pass kernel command line + options to configure various features in it, similar to + self-bootable machines. When read, this entry provides + information about the current kernel command line options set to + boot the card OS. This entry can be written to change the + existing kernel command line options. Typically, the user would + want to read the current command line options, append new ones + or modify existing ones and then write the whole kernel command + line back to this entry. + +What: /sys/class/mic/mic(x)/firmware +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + When read, this sysfs entry provides the path name under + /lib/firmware/ where the firmware image to be booted on the + card can be found. The entry can be written to change the + firmware image location under /lib/firmware/. + +What: /sys/class/mic/mic(x)/ramdisk +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + When read, this sysfs entry provides the path name under + /lib/firmware/ where the ramdisk image to be used during card + OS boot can be found. The entry can be written to change + the ramdisk image location under /lib/firmware/. + +What: /sys/class/mic/mic(x)/bootmode +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + When read, this sysfs entry provides the current bootmode for + the card. This sysfs entry can be written with the following + valid strings: + a) linux - Boot a Linux image. + b) elf - Boot an elf image for flash updates. + +What: /sys/class/mic/mic(x)/log_buf_addr +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + An Intel MIC device runs a Linux OS during its operation. For + debugging purpose and early kernel boot messages, the user can + access the card OS log buffer via debugfs. When read, this entry + provides the kernel virtual address of the buffer where the card + OS log buffer can be read. This entry is written by the host + configuration daemon to set the log buffer address. The correct + log buffer address to be written can be found in the System.map + file of the card OS. + +What: /sys/class/mic/mic(x)/log_buf_len +Date: August 2013 +KernelVersion: 3.11 +Contact: Sudeep Dutt +Description: + An Intel MIC device runs a Linux OS during its operation. For + debugging purpose and early kernel boot messages, the user can + access the card OS log buffer via debugfs. When read, this entry + provides the kernel virtual address where the card OS log buffer + length can be read. This entry is written by host configuration + daemon to set the log buffer length address. The correct log + buffer length address to be written can be found in the + System.map file of the card OS. diff --git a/drivers/misc/mic/common/mic_device.h b/drivers/misc/mic/common/mic_device.h index f02262e1c9d3..6440e9d58d3a 100644 --- a/drivers/misc/mic/common/mic_device.h +++ b/drivers/misc/mic/common/mic_device.h @@ -34,4 +34,11 @@ struct mic_mw { resource_size_t len; }; +/* + * Scratch pad register offsets used by the host to communicate + * device page DMA address to the card. + */ +#define MIC_DPLO_SPAD 14 +#define MIC_DPHI_SPAD 15 + #endif diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile index 6ff5550f10ac..a375dd32c3e2 100644 --- a/drivers/misc/mic/host/Makefile +++ b/drivers/misc/mic/host/Makefile @@ -8,3 +8,5 @@ mic_host-objs += mic_x100.o mic_host-objs += mic_sysfs.o mic_host-objs += mic_smpt.o mic_host-objs += mic_intr.o +mic_host-objs += mic_boot.o +mic_host-objs += mic_debugfs.o diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c new file mode 100644 index 000000000000..936fc58084f3 --- /dev/null +++ b/drivers/misc/mic/host/mic_boot.c @@ -0,0 +1,184 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#include +#include +#include + +#include +#include "../common/mic_device.h" +#include "mic_device.h" +#include "mic_smpt.h" + +/** + * mic_reset - Reset the MIC device. + * @mdev: pointer to mic_device instance + */ +static void mic_reset(struct mic_device *mdev) +{ + int i; + +#define MIC_RESET_TO (45) + + mdev->ops->reset_fw_ready(mdev); + mdev->ops->reset(mdev); + + for (i = 0; i < MIC_RESET_TO; i++) { + if (mdev->ops->is_fw_ready(mdev)) + return; + /* + * Resets typically take 10s of seconds to complete. + * Since an MMIO read is required to check if the + * firmware is ready or not, a 1 second delay works nicely. + */ + msleep(1000); + } + mic_set_state(mdev, MIC_RESET_FAILED); +} + +/* Initialize the MIC bootparams */ +void mic_bootparam_init(struct mic_device *mdev) +{ + struct mic_bootparam *bootparam = mdev->dp; + + bootparam->magic = MIC_MAGIC; + bootparam->c2h_shutdown_db = mdev->shutdown_db; + bootparam->h2c_shutdown_db = -1; + bootparam->h2c_config_db = -1; + bootparam->shutdown_status = 0; + bootparam->shutdown_card = 0; +} + +/** + * mic_start - Start the MIC. + * @mdev: pointer to mic_device instance + * @buf: buffer containing boot string including firmware/ramdisk path. + * + * This function prepares an MIC for boot and initiates boot. + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +int mic_start(struct mic_device *mdev, const char *buf) +{ + int rc; + mutex_lock(&mdev->mic_mutex); +retry: + if (MIC_OFFLINE != mdev->state) { + rc = -EINVAL; + goto unlock_ret; + } + if (!mdev->ops->is_fw_ready(mdev)) { + mic_reset(mdev); + /* + * The state will either be MIC_OFFLINE if the reset succeeded + * or MIC_RESET_FAILED if the firmware reset failed. + */ + goto retry; + } + rc = mdev->ops->load_mic_fw(mdev, buf); + if (rc) + goto unlock_ret; + mic_smpt_restore(mdev); + mic_intr_restore(mdev); + mdev->intr_ops->enable_interrupts(mdev); + mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr); + mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); + mdev->ops->send_firmware_intr(mdev); + mic_set_state(mdev, MIC_ONLINE); +unlock_ret: + mutex_unlock(&mdev->mic_mutex); + return rc; +} + +/** + * mic_stop - Prepare the MIC for reset and trigger reset. + * @mdev: pointer to mic_device instance + * @force: force a MIC to reset even if it is already offline. + * + * RETURNS: None. + */ +void mic_stop(struct mic_device *mdev, bool force) +{ + mutex_lock(&mdev->mic_mutex); + if (MIC_OFFLINE != mdev->state || force) { + mic_bootparam_init(mdev); + mic_reset(mdev); + if (MIC_RESET_FAILED == mdev->state) + goto unlock; + mic_set_shutdown_status(mdev, MIC_NOP); + mic_set_state(mdev, MIC_OFFLINE); + } +unlock: + mutex_unlock(&mdev->mic_mutex); +} + +/** + * mic_shutdown - Initiate MIC shutdown. + * @mdev: pointer to mic_device instance + * + * RETURNS: None. + */ +void mic_shutdown(struct mic_device *mdev) +{ + struct mic_bootparam *bootparam = mdev->dp; + s8 db = bootparam->h2c_shutdown_db; + + mutex_lock(&mdev->mic_mutex); + if (MIC_ONLINE == mdev->state && db != -1) { + bootparam->shutdown_card = 1; + mdev->ops->send_intr(mdev, db); + mic_set_state(mdev, MIC_SHUTTING_DOWN); + } + mutex_unlock(&mdev->mic_mutex); +} + +/** + * mic_shutdown_work - Handle shutdown interrupt from MIC. + * @work: The work structure. + * + * This work is scheduled whenever the host has received a shutdown + * interrupt from the MIC. + */ +void mic_shutdown_work(struct work_struct *work) +{ + struct mic_device *mdev = container_of(work, struct mic_device, + shutdown_work); + struct mic_bootparam *bootparam = mdev->dp; + + mutex_lock(&mdev->mic_mutex); + mic_set_shutdown_status(mdev, bootparam->shutdown_status); + bootparam->shutdown_status = 0; + if (MIC_SHUTTING_DOWN != mdev->state) + mic_set_state(mdev, MIC_SHUTTING_DOWN); + mutex_unlock(&mdev->mic_mutex); +} + +/** + * mic_reset_trigger_work - Trigger MIC reset. + * @work: The work structure. + * + * This work is scheduled whenever the host wants to reset the MIC. + */ +void mic_reset_trigger_work(struct work_struct *work) +{ + struct mic_device *mdev = container_of(work, struct mic_device, + reset_trigger_work); + + mic_stop(mdev, false); +} diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c new file mode 100644 index 000000000000..78541d42aaf9 --- /dev/null +++ b/drivers/misc/mic/host/mic_debugfs.c @@ -0,0 +1,355 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#include +#include +#include + +#include +#include "../common/mic_device.h" +#include "mic_device.h" +#include "mic_smpt.h" + +/* Debugfs parent dir */ +static struct dentry *mic_dbg; + +/** + * mic_log_buf_show - Display MIC kernel log buffer. + * + * log_buf addr/len is read from System.map by user space + * and populated in sysfs entries. + */ +static int mic_log_buf_show(struct seq_file *s, void *unused) +{ + void __iomem *log_buf_va; + int __iomem *log_buf_len_va; + struct mic_device *mdev = s->private; + void *kva; + int size; + unsigned long aper_offset; + + if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len) + goto done; + /* + * Card kernel will never be relocated and any kernel text/data mapping + * can be translated to phys address by subtracting __START_KERNEL_map. + */ + aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map; + log_buf_len_va = mdev->aper.va + aper_offset; + aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map; + log_buf_va = mdev->aper.va + aper_offset; + size = ioread32(log_buf_len_va); + + kva = kmalloc(size, GFP_KERNEL); + if (!kva) + goto done; + mutex_lock(&mdev->mic_mutex); + memcpy_fromio(kva, log_buf_va, size); + switch (mdev->state) { + case MIC_ONLINE: + /* Fall through */ + case MIC_SHUTTING_DOWN: + seq_write(s, kva, size); + break; + default: + break; + } + mutex_unlock(&mdev->mic_mutex); + kfree(kva); +done: + return 0; +} + +static int mic_log_buf_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_log_buf_show, inode->i_private); +} + +static int mic_log_buf_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations log_buf_ops = { + .owner = THIS_MODULE, + .open = mic_log_buf_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_log_buf_release +}; + +static int mic_smpt_show(struct seq_file *s, void *pos) +{ + int i; + struct mic_device *mdev = s->private; + unsigned long flags; + + seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n", + mdev->id, "SMPT entry", "SW DMA addr", "RefCount"); + seq_puts(s, "====================================================\n"); + + if (mdev->smpt) { + struct mic_smpt_info *smpt_info = mdev->smpt; + spin_lock_irqsave(&smpt_info->smpt_lock, flags); + for (i = 0; i < smpt_info->info.num_reg; i++) { + seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n", + " ", i, smpt_info->entry[i].dma_addr, + smpt_info->entry[i].ref_count); + } + spin_unlock_irqrestore(&smpt_info->smpt_lock, flags); + } + seq_puts(s, "====================================================\n"); + return 0; +} + +static int mic_smpt_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_smpt_show, inode->i_private); +} + +static int mic_smpt_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations smpt_file_ops = { + .owner = THIS_MODULE, + .open = mic_smpt_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_smpt_debug_release +}; + +static int mic_soft_reset_show(struct seq_file *s, void *pos) +{ + struct mic_device *mdev = s->private; + + mic_stop(mdev, true); + return 0; +} + +static int mic_soft_reset_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_soft_reset_show, inode->i_private); +} + +static int mic_soft_reset_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations soft_reset_ops = { + .owner = THIS_MODULE, + .open = mic_soft_reset_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_soft_reset_debug_release +}; + +static int mic_post_code_show(struct seq_file *s, void *pos) +{ + struct mic_device *mdev = s->private; + u32 reg = mdev->ops->get_postcode(mdev); + + seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff); + return 0; +} + +static int mic_post_code_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_post_code_show, inode->i_private); +} + +static int mic_post_code_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations post_code_ops = { + .owner = THIS_MODULE, + .open = mic_post_code_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_post_code_debug_release +}; + +static int mic_dp_show(struct seq_file *s, void *pos) +{ + struct mic_device *mdev = s->private; + struct mic_bootparam *bootparam = mdev->dp; + + seq_printf(s, "Bootparam: magic 0x%x\n", + bootparam->magic); + seq_printf(s, "Bootparam: h2c_shutdown_db %d\n", + bootparam->h2c_shutdown_db); + seq_printf(s, "Bootparam: h2c_config_db %d\n", + bootparam->h2c_config_db); + seq_printf(s, "Bootparam: c2h_shutdown_db %d\n", + bootparam->c2h_shutdown_db); + seq_printf(s, "Bootparam: shutdown_status %d\n", + bootparam->shutdown_status); + seq_printf(s, "Bootparam: shutdown_card %d\n", + bootparam->shutdown_card); + + return 0; +} + +static int mic_dp_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_dp_show, inode->i_private); +} + +static int mic_dp_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations dp_ops = { + .owner = THIS_MODULE, + .open = mic_dp_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_dp_debug_release +}; + +static int mic_msi_irq_info_show(struct seq_file *s, void *pos) +{ + struct mic_device *mdev = s->private; + int reg; + int i, j; + u16 entry; + u16 vector; + struct pci_dev *pdev = container_of(mdev->sdev->parent, + struct pci_dev, dev); + + if (pci_dev_msi_enabled(pdev)) { + for (i = 0; i < mdev->irq_info.num_vectors; i++) { + if (pdev->msix_enabled) { + entry = mdev->irq_info.msix_entries[i].entry; + vector = mdev->irq_info.msix_entries[i].vector; + } else { + entry = 0; + vector = pdev->irq; + } + + reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry); + + seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n", + "IRQ:", vector, "Entry:", entry, i, reg); + + seq_printf(s, "%-10s", "offset:"); + for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--) + seq_printf(s, "%4d ", j); + seq_puts(s, "\n"); + + + seq_printf(s, "%-10s", "count:"); + for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--) + seq_printf(s, "%4d ", + (mdev->irq_info.mic_msi_map[i] & BIT(j)) ? + 1 : 0); + seq_puts(s, "\n\n"); + } + } else { + seq_puts(s, "MSI/MSIx interrupts not enabled\n"); + } + + return 0; + +} + +static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_msi_irq_info_show, inode->i_private); +} + +static int +mic_msi_irq_info_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations msi_irq_info_ops = { + .owner = THIS_MODULE, + .open = mic_msi_irq_info_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_msi_irq_info_debug_release +}; + +/** + * mic_create_debug_dir - Initialize MIC debugfs entries. + */ +void mic_create_debug_dir(struct mic_device *mdev) +{ + if (!mic_dbg) + return; + + mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg); + if (!mdev->dbg_dir) + return; + + debugfs_create_file("log_buf", 0444, mdev->dbg_dir, + mdev, &log_buf_ops); + + debugfs_create_file("smpt", 0444, mdev->dbg_dir, + mdev, &smpt_file_ops); + + debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, + mdev, &soft_reset_ops); + + debugfs_create_file("post_code", 0444, mdev->dbg_dir, + mdev, &post_code_ops); + + debugfs_create_file("dp", 0444, mdev->dbg_dir, + mdev, &dp_ops); + + debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, + mdev, &msi_irq_info_ops); +} + +/** + * mic_delete_debug_dir - Uninitialize MIC debugfs entries. + */ +void mic_delete_debug_dir(struct mic_device *mdev) +{ + if (!mdev->dbg_dir) + return; + + debugfs_remove_recursive(mdev->dbg_dir); +} + +/** + * mic_init_debugfs - Initialize global debugfs entry. + */ +void __init mic_init_debugfs(void) +{ + mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!mic_dbg) + pr_err("can't create debugfs dir\n"); +} + +/** + * mic_exit_debugfs - Uninitialize global debugfs entry + */ +void mic_exit_debugfs(void) +{ + debugfs_remove(mic_dbg); +} diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index dd34b6532a01..50b8b88d70d3 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -63,6 +63,23 @@ enum mic_stepping { * @smpt: MIC SMPT information. * @intr_info: H/W specific interrupt information. * @irq_info: The OS specific irq information + * @dbg_dir: debugfs directory of this MIC device. + * @cmdline: Kernel command line. + * @firmware: Firmware file name. + * @ramdisk: Ramdisk file name. + * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates. + * @bootaddr: MIC boot address. + * @reset_trigger_work: Work for triggering reset requests. + * @shutdown_work: Work for handling shutdown interrupts. + * @state: MIC state. + * @shutdown_status: MIC status reported by card for shutdown/crashes. + * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes. + * @log_buf_addr: Log buffer address for MIC. + * @log_buf_len: Log buffer length address for MIC. + * @dp: virtio device page + * @dp_dma_addr: virtio device page DMA address. + * @shutdown_db: shutdown doorbell. + * @shutdown_cookie: shutdown cookie. */ struct mic_device { struct mic_mw mmio; @@ -79,6 +96,23 @@ struct mic_device { struct mic_smpt_info *smpt; struct mic_intr_info *intr_info; struct mic_irq_info irq_info; + struct dentry *dbg_dir; + char *cmdline; + char *firmware; + char *ramdisk; + char *bootmode; + u32 bootaddr; + struct work_struct reset_trigger_work; + struct work_struct shutdown_work; + u8 state; + u8 shutdown_status; + struct sysfs_dirent *state_sysfs; + void *log_buf_addr; + int *log_buf_len; + void *dp; + dma_addr_t dp_dma_addr; + int shutdown_db; + struct mic_irq *shutdown_cookie; }; /** @@ -90,6 +124,13 @@ struct mic_device { * @send_intr: Send an interrupt for a particular doorbell on the card. * @ack_interrupt: Hardware specific operations to ack the h/w on * receipt of an interrupt. + * @reset: Reset the remote processor. + * @reset_fw_ready: Reset firmware ready field. + * @is_fw_ready: Check if firmware is ready for OS download. + * @send_firmware_intr: Send an interrupt to the card firmware. + * @load_mic_fw: Load firmware segments required to boot the card + * into card memory. This includes the kernel, command line, ramdisk etc. + * @get_postcode: Get post code status from firmware. */ struct mic_hw_ops { u8 aper_bar; @@ -98,6 +139,12 @@ struct mic_hw_ops { void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val); void (*send_intr)(struct mic_device *mdev, int doorbell); u32 (*ack_interrupt)(struct mic_device *mdev); + void (*reset)(struct mic_device *mdev); + void (*reset_fw_ready)(struct mic_device *mdev); + bool (*is_fw_ready)(struct mic_device *mdev); + void (*send_firmware_intr)(struct mic_device *mdev); + int (*load_mic_fw)(struct mic_device *mdev, const char *buf); + u32 (*get_postcode)(struct mic_device *mdev); }; /** @@ -127,4 +174,17 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset) } void mic_sysfs_init(struct mic_device *mdev); +int mic_start(struct mic_device *mdev, const char *buf); +void mic_stop(struct mic_device *mdev, bool force); +void mic_shutdown(struct mic_device *mdev); +void mic_reset_delayed_work(struct work_struct *work); +void mic_reset_trigger_work(struct work_struct *work); +void mic_shutdown_work(struct work_struct *work); +void mic_bootparam_init(struct mic_device *mdev); +void mic_set_state(struct mic_device *mdev, u8 state); +void mic_set_shutdown_status(struct mic_device *mdev, u8 status); +void mic_create_debug_dir(struct mic_device *dev); +void mic_delete_debug_dir(struct mic_device *dev); +void __init mic_init_debugfs(void); +void mic_exit_debugfs(void); #endif diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index 332a15e4215b..998a20ab7e96 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -26,6 +26,7 @@ #include #include +#include #include "../common/mic_device.h" #include "mic_device.h" #include "mic_x100.h" @@ -63,6 +64,60 @@ static struct class *g_mic_class; /* Base device node number for MIC devices */ static dev_t g_mic_devno; +/* Initialize the device page */ +static int mic_dp_init(struct mic_device *mdev) +{ + mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL); + if (!mdev->dp) { + dev_err(mdev->sdev->parent, "%s %d err %d\n", + __func__, __LINE__, -ENOMEM); + return -ENOMEM; + } + + mdev->dp_dma_addr = mic_map_single(mdev, + mdev->dp, MIC_DP_SIZE); + if (mic_map_error(mdev->dp_dma_addr)) { + kfree(mdev->dp); + dev_err(mdev->sdev->parent, "%s %d err %d\n", + __func__, __LINE__, -ENOMEM); + return -ENOMEM; + } + mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr); + mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); + return 0; +} + +/* Uninitialize the device page */ +static void mic_dp_uninit(struct mic_device *mdev) +{ + mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE); + kfree(mdev->dp); +} + +/** + * mic_shutdown_db - Shutdown doorbell interrupt handler. + */ +static irqreturn_t mic_shutdown_db(int irq, void *data) +{ + struct mic_device *mdev = data; + struct mic_bootparam *bootparam = mdev->dp; + + mdev->ops->ack_interrupt(mdev); + + switch (bootparam->shutdown_status) { + case MIC_HALTED: + case MIC_POWER_OFF: + case MIC_RESTART: + /* Fall through */ + case MIC_CRASHED: + schedule_work(&mdev->shutdown_work); + break; + default: + break; + }; + return IRQ_HANDLED; +} + /** * mic_ops_init: Initialize HW specific operation tables. * @@ -136,6 +191,26 @@ mic_device_init(struct mic_device *mdev, struct pci_dev *pdev) mic_sysfs_init(mdev); mutex_init(&mdev->mic_mutex); mdev->irq_info.next_avail_src = 0; + INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work); + INIT_WORK(&mdev->shutdown_work, mic_shutdown_work); +} + +/** + * mic_device_uninit - Frees resources allocated during mic_device_init(..) + * + * @mdev: pointer to mic_device instance + * + * returns none + */ +static void mic_device_uninit(struct mic_device *mdev) +{ + /* The cmdline sysfs entry might have allocated cmdline */ + kfree(mdev->cmdline); + kfree(mdev->firmware); + kfree(mdev->ramdisk); + kfree(mdev->bootmode); + flush_work(&mdev->reset_trigger_work); + flush_work(&mdev->shutdown_work); } /** @@ -170,7 +245,7 @@ static int mic_probe(struct pci_dev *pdev, rc = pci_enable_device(pdev); if (rc) { dev_err(&pdev->dev, "failed to enable pci device.\n"); - goto ida_remove; + goto uninit_device; } pci_set_master(pdev); @@ -228,7 +303,40 @@ static int mic_probe(struct pci_dev *pdev, "device_create_with_groups failed rc %d\n", rc); goto smpt_uninit; } + mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, + NULL, "state"); + if (!mdev->state_sysfs) { + rc = -ENODEV; + dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc); + goto destroy_device; + } + + rc = mic_dp_init(mdev); + if (rc) { + dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc); + goto sysfs_put; + } + mutex_lock(&mdev->mic_mutex); + + mdev->shutdown_db = mic_next_db(mdev); + mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db, + "shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB); + if (IS_ERR(mdev->shutdown_cookie)) { + rc = PTR_ERR(mdev->shutdown_cookie); + mutex_unlock(&mdev->mic_mutex); + goto dp_uninit; + } + mutex_unlock(&mdev->mic_mutex); + mic_bootparam_init(mdev); + + mic_create_debug_dir(mdev); return 0; +dp_uninit: + mic_dp_uninit(mdev); +sysfs_put: + sysfs_put(mdev->state_sysfs); +destroy_device: + device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id)); smpt_uninit: mic_smpt_uninit(mdev); free_interrupts: @@ -241,7 +349,8 @@ release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); -ida_remove: +uninit_device: + mic_device_uninit(mdev); ida_simple_remove(&g_mic_ida, mdev->id); ida_fail: kfree(mdev); @@ -265,11 +374,20 @@ static void mic_remove(struct pci_dev *pdev) if (!mdev) return; + mic_stop(mdev, false); + mic_delete_debug_dir(mdev); + mutex_lock(&mdev->mic_mutex); + mic_free_irq(mdev, mdev->shutdown_cookie, mdev); + mutex_unlock(&mdev->mic_mutex); + flush_work(&mdev->shutdown_work); + mic_dp_uninit(mdev); + sysfs_put(mdev->state_sysfs); device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id)); mic_smpt_uninit(mdev); mic_free_interrupts(mdev, pdev); iounmap(mdev->mmio.va); iounmap(mdev->aper.va); + mic_device_uninit(mdev); pci_release_regions(pdev); pci_disable_device(pdev); ida_simple_remove(&g_mic_ida, mdev->id); @@ -300,14 +418,16 @@ static int __init mic_init(void) goto cleanup_chrdev; } + mic_init_debugfs(); ida_init(&g_mic_ida); ret = pci_register_driver(&mic_driver); if (ret) { pr_err("pci_register_driver failed ret %d\n", ret); - goto class_destroy; + goto cleanup_debugfs; } return ret; -class_destroy: +cleanup_debugfs: + mic_exit_debugfs(); class_destroy(g_mic_class); cleanup_chrdev: unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); @@ -319,6 +439,7 @@ static void __exit mic_exit(void) { pci_unregister_driver(&mic_driver); ida_destroy(&g_mic_ida); + mic_exit_debugfs(); class_destroy(g_mic_class); unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); } diff --git a/drivers/misc/mic/host/mic_sysfs.c b/drivers/misc/mic/host/mic_sysfs.c index 972c18255263..aaf849945111 100644 --- a/drivers/misc/mic/host/mic_sysfs.c +++ b/drivers/misc/mic/host/mic_sysfs.c @@ -20,9 +20,50 @@ */ #include +#include #include "../common/mic_device.h" #include "mic_device.h" +/* + * A state-to-string lookup table, for exposing a human readable state + * via sysfs. Always keep in sync with enum mic_states + */ +static const char * const mic_state_string[] = { + [MIC_OFFLINE] = "offline", + [MIC_ONLINE] = "online", + [MIC_SHUTTING_DOWN] = "shutting_down", + [MIC_RESET_FAILED] = "reset_failed", +}; + +/* + * A shutdown-status-to-string lookup table, for exposing a human + * readable state via sysfs. Always keep in sync with enum mic_shutdown_status + */ +static const char * const mic_shutdown_status_string[] = { + [MIC_NOP] = "nop", + [MIC_CRASHED] = "crashed", + [MIC_HALTED] = "halted", + [MIC_POWER_OFF] = "poweroff", + [MIC_RESTART] = "restart", +}; + +void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status) +{ + dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n", + mic_shutdown_status_string[mdev->shutdown_status], + mic_shutdown_status_string[shutdown_status]); + mdev->shutdown_status = shutdown_status; +} + +void mic_set_state(struct mic_device *mdev, u8 state) +{ + dev_dbg(mdev->sdev->parent, "State %s -> %s\n", + mic_state_string[mdev->state], + mic_state_string[state]); + mdev->state = state; + sysfs_notify_dirent(mdev->state_sysfs); +} + static ssize_t mic_show_family(struct device *dev, struct device_attribute *attr, char *buf) { @@ -75,9 +116,337 @@ mic_show_stepping(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(stepping, S_IRUGO, mic_show_stepping, NULL); +static ssize_t +mic_show_state(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev || mdev->state >= MIC_LAST) + return -EINVAL; + + return scnprintf(buf, PAGE_SIZE, "%s\n", + mic_state_string[mdev->state]); +} + +static ssize_t +mic_store_state(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc = 0; + struct mic_device *mdev = dev_get_drvdata(dev->parent); + if (!mdev) + return -EINVAL; + if (sysfs_streq(buf, "boot")) { + rc = mic_start(mdev, buf); + if (rc) { + dev_err(mdev->sdev->parent, + "mic_boot failed rc %d\n", rc); + count = rc; + } + goto done; + } + + if (sysfs_streq(buf, "reset")) { + schedule_work(&mdev->reset_trigger_work); + goto done; + } + + if (sysfs_streq(buf, "shutdown")) { + mic_shutdown(mdev); + goto done; + } + + count = -EINVAL; +done: + return count; +} +static DEVICE_ATTR(state, S_IRUGO|S_IWUSR, mic_show_state, mic_store_state); + +static ssize_t mic_show_shutdown_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST) + return -EINVAL; + + return scnprintf(buf, PAGE_SIZE, "%s\n", + mic_shutdown_status_string[mdev->shutdown_status]); +} +static DEVICE_ATTR(shutdown_status, S_IRUGO|S_IWUSR, + mic_show_shutdown_status, NULL); + +static ssize_t +mic_show_cmdline(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + char *cmdline; + + if (!mdev) + return -EINVAL; + + cmdline = mdev->cmdline; + + if (cmdline) + return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline); + return 0; +} + +static ssize_t +mic_store_cmdline(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + mutex_lock(&mdev->mic_mutex); + kfree(mdev->cmdline); + + mdev->cmdline = kmalloc(count + 1, GFP_KERNEL); + if (!mdev->cmdline) { + count = -ENOMEM; + goto unlock; + } + + strncpy(mdev->cmdline, buf, count); + + if (mdev->cmdline[count - 1] == '\n') + mdev->cmdline[count - 1] = '\0'; + else + mdev->cmdline[count] = '\0'; +unlock: + mutex_unlock(&mdev->mic_mutex); + return count; +} +static DEVICE_ATTR(cmdline, S_IRUGO | S_IWUSR, + mic_show_cmdline, mic_store_cmdline); + +static ssize_t +mic_show_firmware(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + char *firmware; + + if (!mdev) + return -EINVAL; + + firmware = mdev->firmware; + + if (firmware) + return scnprintf(buf, PAGE_SIZE, "%s\n", firmware); + return 0; +} + +static ssize_t +mic_store_firmware(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + mutex_lock(&mdev->mic_mutex); + kfree(mdev->firmware); + + mdev->firmware = kmalloc(count + 1, GFP_KERNEL); + if (!mdev->firmware) { + count = -ENOMEM; + goto unlock; + } + strncpy(mdev->firmware, buf, count); + + if (mdev->firmware[count - 1] == '\n') + mdev->firmware[count - 1] = '\0'; + else + mdev->firmware[count] = '\0'; +unlock: + mutex_unlock(&mdev->mic_mutex); + return count; +} +static DEVICE_ATTR(firmware, S_IRUGO | S_IWUSR, + mic_show_firmware, mic_store_firmware); + +static ssize_t +mic_show_ramdisk(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + char *ramdisk; + + if (!mdev) + return -EINVAL; + + ramdisk = mdev->ramdisk; + + if (ramdisk) + return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk); + return 0; +} + +static ssize_t +mic_store_ramdisk(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + mutex_lock(&mdev->mic_mutex); + kfree(mdev->ramdisk); + + mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL); + if (!mdev->ramdisk) { + count = -ENOMEM; + goto unlock; + } + + strncpy(mdev->ramdisk, buf, count); + + if (mdev->ramdisk[count - 1] == '\n') + mdev->ramdisk[count - 1] = '\0'; + else + mdev->ramdisk[count] = '\0'; +unlock: + mutex_unlock(&mdev->mic_mutex); + return count; +} +static DEVICE_ATTR(ramdisk, S_IRUGO | S_IWUSR, + mic_show_ramdisk, mic_store_ramdisk); + +static ssize_t +mic_show_bootmode(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + char *bootmode; + + if (!mdev) + return -EINVAL; + + bootmode = mdev->bootmode; + + if (bootmode) + return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode); + return 0; +} + +static ssize_t +mic_store_bootmode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf")) + return -EINVAL; + + mutex_lock(&mdev->mic_mutex); + kfree(mdev->bootmode); + + mdev->bootmode = kmalloc(count + 1, GFP_KERNEL); + if (!mdev->bootmode) { + count = -ENOMEM; + goto unlock; + } + + strncpy(mdev->bootmode, buf, count); + + if (mdev->bootmode[count - 1] == '\n') + mdev->bootmode[count - 1] = '\0'; + else + mdev->bootmode[count] = '\0'; +unlock: + mutex_unlock(&mdev->mic_mutex); + return count; +} +static DEVICE_ATTR(bootmode, S_IRUGO | S_IWUSR, + mic_show_bootmode, mic_store_bootmode); + +static ssize_t +mic_show_log_buf_addr(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr); +} + +static ssize_t +mic_store_log_buf_addr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + int ret; + unsigned long addr; + + if (!mdev) + return -EINVAL; + + ret = kstrtoul(buf, 16, &addr); + if (ret) + goto exit; + + mdev->log_buf_addr = (void *)addr; + ret = count; +exit: + return ret; +} +static DEVICE_ATTR(log_buf_addr, S_IRUGO | S_IWUSR, + mic_show_log_buf_addr, mic_store_log_buf_addr); + +static ssize_t +mic_show_log_buf_len(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + + if (!mdev) + return -EINVAL; + + return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len); +} + +static ssize_t +mic_store_log_buf_len(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mic_device *mdev = dev_get_drvdata(dev->parent); + int ret; + unsigned long addr; + + if (!mdev) + return -EINVAL; + + ret = kstrtoul(buf, 16, &addr); + if (ret) + goto exit; + + mdev->log_buf_len = (int *)addr; + ret = count; +exit: + return ret; +} +static DEVICE_ATTR(log_buf_len, S_IRUGO | S_IWUSR, + mic_show_log_buf_len, mic_store_log_buf_len); + static struct attribute *mic_default_attrs[] = { &dev_attr_family.attr, &dev_attr_stepping.attr, + &dev_attr_state.attr, + &dev_attr_shutdown_status.attr, + &dev_attr_cmdline.attr, + &dev_attr_firmware.attr, + &dev_attr_ramdisk.attr, + &dev_attr_bootmode.attr, + &dev_attr_log_buf_addr.attr, + &dev_attr_log_buf_len.attr, NULL }; diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index b63731691c73..a12ae5c8844d 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c @@ -20,6 +20,9 @@ */ #include #include +#include +#include +#include #include "../common/mic_device.h" #include "mic_device.h" @@ -256,6 +259,248 @@ mic_x100_program_msi_to_src_map(struct mic_device *mdev, mic_mmio_write(mw, reg, mxar); } +/* + * mic_x100_reset_fw_ready - Reset Firmware ready status field. + * @mdev: pointer to mic_device instance + */ +static void mic_x100_reset_fw_ready(struct mic_device *mdev) +{ + mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0); +} + +/* + * mic_x100_is_fw_ready - Check if firmware is ready. + * @mdev: pointer to mic_device instance + */ +static bool mic_x100_is_fw_ready(struct mic_device *mdev) +{ + u32 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO); + return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true : false; +} + +/** + * mic_x100_get_apic_id - Get bootstrap APIC ID. + * @mdev: pointer to mic_device instance + */ +static u32 mic_x100_get_apic_id(struct mic_device *mdev) +{ + u32 scratch2 = 0; + + scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO); + return MIC_X100_SPAD2_APIC_ID(scratch2); +} + +/** + * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC. + * @mdev: pointer to mic_device instance + */ +static void mic_x100_send_firmware_intr(struct mic_device *mdev) +{ + u32 apicicr_low; + u64 apic_icr_offset = MIC_X100_SBOX_APICICR7; + int vector = MIC_X100_BSP_INTERRUPT_VECTOR; + struct mic_mw *mw = &mdev->mmio; + + /* + * For MIC we need to make sure we "hit" + * the send_icr bit (13). + */ + apicicr_low = (vector | (1 << 13)); + + mic_mmio_write(mw, mic_x100_get_apic_id(mdev), + MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4); + + /* Ensure that the interrupt is ordered w.r.t. previous stores. */ + wmb(); + mic_mmio_write(mw, apicicr_low, + MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset); +} + +/** + * mic_x100_hw_reset - Reset the MIC device. + * @mdev: pointer to mic_device instance + */ +static void mic_x100_hw_reset(struct mic_device *mdev) +{ + u32 reset_reg; + u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR; + struct mic_mw *mw = &mdev->mmio; + + /* Ensure that the reset is ordered w.r.t. previous loads and stores */ + mb(); + /* Trigger reset */ + reset_reg = mic_mmio_read(mw, rgcr); + reset_reg |= 0x1; + mic_mmio_write(mw, reset_reg, rgcr); + /* + * It seems we really want to delay at least 1 second + * after touching reset to prevent a lot of problems. + */ + msleep(1000); +} + +/** + * mic_x100_load_command_line - Load command line to MIC. + * @mdev: pointer to mic_device instance + * @fw: the firmware image + * + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +static int +mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw) +{ + u32 len = 0; + u32 boot_mem; + char *buf; + void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr + fw->size; +#define CMDLINE_SIZE 2048 + + boot_mem = mdev->aper.len >> 20; + buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL); + if (!buf) { + dev_err(mdev->sdev->parent, + "%s %d allocation failed\n", __func__, __LINE__); + return -ENOMEM; + } + len += snprintf(buf, CMDLINE_SIZE - len, + " mem=%dM", boot_mem); + if (mdev->cmdline) + snprintf(buf + len, CMDLINE_SIZE - len, + " %s", mdev->cmdline); + memcpy_toio(cmd_line_va, buf, strlen(buf) + 1); + kfree(buf); + return 0; +} + +/** + * mic_x100_load_ramdisk - Load ramdisk to MIC. + * @mdev: pointer to mic_device instance + * + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +static int +mic_x100_load_ramdisk(struct mic_device *mdev) +{ + const struct firmware *fw; + int rc; + struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr; + + rc = request_firmware(&fw, + mdev->ramdisk, mdev->sdev->parent); + if (rc < 0) { + dev_err(mdev->sdev->parent, + "ramdisk request_firmware failed: %d %s\n", + rc, mdev->ramdisk); + goto error; + } + /* + * Typically the bootaddr for card OS is 64M + * so copy over the ramdisk @ 128M. + */ + memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), + fw->data, fw->size); + iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image); + iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size); + release_firmware(fw); +error: + return rc; +} + +/** + * mic_x100_get_boot_addr - Get MIC boot address. + * @mdev: pointer to mic_device instance + * + * This function is called during firmware load to determine + * the address at which the OS should be downloaded in card + * memory i.e. GDDR. + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +static int +mic_x100_get_boot_addr(struct mic_device *mdev) +{ + u32 scratch2, boot_addr; + int rc = 0; + + scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO); + boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2); + dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n", + __func__, __LINE__, boot_addr); + if (boot_addr > (1 << 31)) { + dev_err(mdev->sdev->parent, + "incorrect bootaddr 0x%x\n", + boot_addr); + rc = -EINVAL; + goto error; + } + mdev->bootaddr = boot_addr; +error: + return rc; +} + +/** + * mic_x100_load_firmware - Load firmware to MIC. + * @mdev: pointer to mic_device instance + * @buf: buffer containing boot string including firmware/ramdisk path. + * + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +static int +mic_x100_load_firmware(struct mic_device *mdev, const char *buf) +{ + int rc; + const struct firmware *fw; + + rc = mic_x100_get_boot_addr(mdev); + if (rc) + goto error; + /* load OS */ + rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent); + if (rc < 0) { + dev_err(mdev->sdev->parent, + "ramdisk request_firmware failed: %d %s\n", + rc, mdev->firmware); + goto error; + } + if (mdev->bootaddr > mdev->aper.len - fw->size) { + rc = -EINVAL; + dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n", + __func__, __LINE__, rc, mdev->bootaddr); + release_firmware(fw); + goto error; + } + memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size); + mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size); + if (!strcmp(mdev->bootmode, "elf")) + goto done; + /* load command line */ + rc = mic_x100_load_command_line(mdev, fw); + if (rc) { + dev_err(mdev->sdev->parent, "%s %d rc %d\n", + __func__, __LINE__, rc); + goto error; + } + release_firmware(fw); + /* load ramdisk */ + if (mdev->ramdisk) + rc = mic_x100_load_ramdisk(mdev); +error: + dev_dbg(mdev->sdev->parent, "%s %d rc %d\n", + __func__, __LINE__, rc); +done: + return rc; +} + +/** + * mic_x100_get_postcode - Get postcode status from firmware. + * @mdev: pointer to mic_device instance + * + * RETURNS: postcode. + */ +static u32 mic_x100_get_postcode(struct mic_device *mdev) +{ + return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE); +} + /** * mic_x100_smpt_set - Update an SMPT entry with a DMA address. * @mdev: pointer to mic_device instance @@ -311,6 +556,12 @@ struct mic_hw_ops mic_x100_ops = { .write_spad = mic_x100_write_spad, .send_intr = mic_x100_send_intr, .ack_interrupt = mic_x100_ack_interrupt, + .reset = mic_x100_hw_reset, + .reset_fw_ready = mic_x100_reset_fw_ready, + .is_fw_ready = mic_x100_is_fw_ready, + .send_firmware_intr = mic_x100_send_firmware_intr, + .load_mic_fw = mic_x100_load_firmware, + .get_postcode = mic_x100_get_postcode, }; struct mic_hw_intr_ops mic_x100_intr_ops = { diff --git a/drivers/misc/mic/host/mic_x100.h b/drivers/misc/mic/host/mic_x100.h index 642cae9a0041..8b7daa182e54 100644 --- a/drivers/misc/mic/host/mic_x100.h +++ b/drivers/misc/mic/host/mic_x100.h @@ -69,6 +69,15 @@ #define MIC_X100_NUM_SBOX_IRQ 8 #define MIC_X100_NUM_RDMASR_IRQ 8 #define MIC_X100_RDMASR_IRQ_BASE 17 +#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1) +#define MIC_X100_SPAD2_APIC_ID(x) (((x) >> 1) & 0x1ff) +#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000) +#define MIC_X100_SBOX_APICICR7 0x0000AA08 +#define MIC_X100_SBOX_RGCR 0x00004010 +#define MIC_X100_SBOX_SDBIC0 0x0000CC90 +#define MIC_X100_DOWNLOAD_INFO 2 +#define MIC_X100_FW_SIZE 5 +#define MIC_X100_POSTCODE 0x242c static const u16 mic_x100_intr_init[] = { MIC_X100_DOORBELL_IDX_START, @@ -79,6 +88,9 @@ static const u16 mic_x100_intr_init[] = { MIC_X100_NUM_ERR, }; +/* Host->Card(bootstrap) Interrupt Vector */ +#define MIC_X100_BSP_INTERRUPT_VECTOR 229 + extern struct mic_hw_ops mic_x100_ops; extern struct mic_smpt_ops mic_x100_smpt_ops; extern struct mic_hw_intr_ops mic_x100_intr_ops; diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 115add2515aa..d37263fbdca7 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -241,6 +241,7 @@ header-y += media.h header-y += mei.h header-y += mempolicy.h header-y += meye.h +header-y += mic_common.h header-y += mii.h header-y += minix_fs.h header-y += mman.h diff --git a/include/uapi/linux/mic_common.h b/include/uapi/linux/mic_common.h new file mode 100644 index 000000000000..a9091e529183 --- /dev/null +++ b/include/uapi/linux/mic_common.h @@ -0,0 +1,74 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC driver. + * + */ +#ifndef __MIC_COMMON_H_ +#define __MIC_COMMON_H_ + +#include + +/** + * struct mic_bootparam: Virtio device independent information in device page + * + * @magic: A magic value used by the card to ensure it can see the host + * @c2h_shutdown_db: Card to Host shutdown doorbell set by host + * @h2c_shutdown_db: Host to Card shutdown doorbell set by card + * @h2c_config_db: Host to Card Virtio config doorbell set by card + * @shutdown_status: Card shutdown status set by card + * @shutdown_card: Set to 1 by the host when a card shutdown is initiated + */ +struct mic_bootparam { + __u32 magic; + __s8 c2h_shutdown_db; + __s8 h2c_shutdown_db; + __s8 h2c_config_db; + __u8 shutdown_status; + __u8 shutdown_card; +} __aligned(8); + +/* Device page size */ +#define MIC_DP_SIZE 4096 + +#define MIC_MAGIC 0xc0ffee00 + +/** + * enum mic_states - MIC states. + */ +enum mic_states { + MIC_OFFLINE = 0, + MIC_ONLINE, + MIC_SHUTTING_DOWN, + MIC_RESET_FAILED, + MIC_LAST +}; + +/** + * enum mic_status - MIC status reported by card after + * a host or card initiated shutdown or a card crash. + */ +enum mic_status { + MIC_NOP = 0, + MIC_CRASHED, + MIC_HALTED, + MIC_POWER_OFF, + MIC_RESTART, + MIC_STATUS_LAST +}; + +#endif -- cgit From f69bcbf3b4c4b333dcd7a48eaf868bf0c88edab5 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Thu, 5 Sep 2013 16:42:18 -0700 Subject: Intel MIC Host Driver Changes for Virtio Devices. This patch introduces the host "Virtio over PCIe" interface for Intel MIC. It allows creating user space backends on the host and instantiating virtio devices for them on the Intel MIC card. It uses the existing VRINGH infrastructure in the kernel to access virtio rings from the host. A character device per MIC is exposed with IOCTL, mmap and poll callbacks. This allows the user space backend to: (a) add/remove a virtio device via a device page. (b) map (R/O) virtio rings and device page to user space. (c) poll for availability of data. (d) copy a descriptor or entire descriptor chain to/from the card. (e) modify virtio configuration. (f) handle virtio device reset. The buffers are copied over using CPU copies for this initial patch and host initiated MIC DMA support is planned for future patches. The avail and desc virtio rings are in host memory and the used ring is in card memory to maximize writes across PCIe for performance. Co-author: Sudeep Dutt Signed-off-by: Ashutosh Dixit Signed-off-by: Caz Yokoyama Signed-off-by: Dasaratharaman Chandramouli Signed-off-by: Nikhil Rao Signed-off-by: Harshavardhan R Kharche Signed-off-by: Sudeep Dutt Acked-by: Yaozu (Eddie) Dong Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/Kconfig | 1 + drivers/misc/mic/common/mic_device.h | 7 + drivers/misc/mic/host/Makefile | 2 + drivers/misc/mic/host/mic_boot.c | 3 +- drivers/misc/mic/host/mic_debugfs.c | 140 +++++++ drivers/misc/mic/host/mic_device.h | 5 + drivers/misc/mic/host/mic_fops.c | 221 +++++++++++ drivers/misc/mic/host/mic_fops.h | 32 ++ drivers/misc/mic/host/mic_main.c | 26 ++ drivers/misc/mic/host/mic_virtio.c | 703 +++++++++++++++++++++++++++++++++++ drivers/misc/mic/host/mic_virtio.h | 138 +++++++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/mic_common.h | 166 ++++++++- include/uapi/linux/mic_ioctl.h | 74 ++++ 14 files changed, 1517 insertions(+), 2 deletions(-) create mode 100644 drivers/misc/mic/host/mic_fops.c create mode 100644 drivers/misc/mic/host/mic_fops.h create mode 100644 drivers/misc/mic/host/mic_virtio.c create mode 100644 drivers/misc/mic/host/mic_virtio.h create mode 100644 include/uapi/linux/mic_ioctl.h (limited to 'include') diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index 279a2e649059..01f1a4a84c63 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig @@ -3,6 +3,7 @@ comment "Intel MIC Host Driver" config INTEL_MIC_HOST tristate "Intel MIC Host Driver" depends on 64BIT && PCI + select VHOST_RING default N help This enables Host Driver support for the Intel Many Integrated diff --git a/drivers/misc/mic/common/mic_device.h b/drivers/misc/mic/common/mic_device.h index 6440e9d58d3a..01eb74faae6b 100644 --- a/drivers/misc/mic/common/mic_device.h +++ b/drivers/misc/mic/common/mic_device.h @@ -41,4 +41,11 @@ struct mic_mw { #define MIC_DPLO_SPAD 14 #define MIC_DPHI_SPAD 15 +/* + * These values are supposed to be in the config_change field of the + * device page when the host sends a config change interrupt to the card. + */ +#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1 +#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2 + #endif diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile index a375dd32c3e2..c2197f999394 100644 --- a/drivers/misc/mic/host/Makefile +++ b/drivers/misc/mic/host/Makefile @@ -10,3 +10,5 @@ mic_host-objs += mic_smpt.o mic_host-objs += mic_intr.o mic_host-objs += mic_boot.o mic_host-objs += mic_debugfs.o +mic_host-objs += mic_fops.o +mic_host-objs += mic_virtio.o diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 936fc58084f3..fd9ff6d3784e 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -20,12 +20,12 @@ */ #include #include -#include #include #include "../common/mic_device.h" #include "mic_device.h" #include "mic_smpt.h" +#include "mic_virtio.h" /** * mic_reset - Reset the MIC device. @@ -117,6 +117,7 @@ void mic_stop(struct mic_device *mdev, bool force) { mutex_lock(&mdev->mic_mutex); if (MIC_OFFLINE != mdev->state || force) { + mic_virtio_reset_devices(mdev); mic_bootparam_init(mdev); mic_reset(mdev); if (MIC_RESET_FAILED == mdev->state) diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c index 78541d42aaf9..e22fb7bbbb98 100644 --- a/drivers/misc/mic/host/mic_debugfs.c +++ b/drivers/misc/mic/host/mic_debugfs.c @@ -26,6 +26,7 @@ #include "../common/mic_device.h" #include "mic_device.h" #include "mic_smpt.h" +#include "mic_virtio.h" /* Debugfs parent dir */ static struct dentry *mic_dbg; @@ -193,7 +194,13 @@ static const struct file_operations post_code_ops = { static int mic_dp_show(struct seq_file *s, void *pos) { struct mic_device *mdev = s->private; + struct mic_device_desc *d; + struct mic_device_ctrl *dc; + struct mic_vqconfig *vqconfig; + __u32 *features; + __u8 *config; struct mic_bootparam *bootparam = mdev->dp; + int i, j; seq_printf(s, "Bootparam: magic 0x%x\n", bootparam->magic); @@ -208,6 +215,53 @@ static int mic_dp_show(struct seq_file *s, void *pos) seq_printf(s, "Bootparam: shutdown_card %d\n", bootparam->shutdown_card); + for (i = sizeof(*bootparam); i < MIC_DP_SIZE; + i += mic_total_desc_size(d)) { + d = mdev->dp + i; + dc = (void *)d + mic_aligned_desc_size(d); + + /* end of list */ + if (d->type == 0) + break; + + if (d->type == -1) + continue; + + seq_printf(s, "Type %d ", d->type); + seq_printf(s, "Num VQ %d ", d->num_vq); + seq_printf(s, "Feature Len %d\n", d->feature_len); + seq_printf(s, "Config Len %d ", d->config_len); + seq_printf(s, "Shutdown Status %d\n", d->status); + + for (j = 0; j < d->num_vq; j++) { + vqconfig = mic_vq_config(d) + j; + seq_printf(s, "vqconfig[%d]: ", j); + seq_printf(s, "address 0x%llx ", vqconfig->address); + seq_printf(s, "num %d ", vqconfig->num); + seq_printf(s, "used address 0x%llx\n", + vqconfig->used_address); + } + + features = (__u32 *) mic_vq_features(d); + seq_printf(s, "Features: Host 0x%x ", features[0]); + seq_printf(s, "Guest 0x%x\n", features[1]); + + config = mic_vq_configspace(d); + for (j = 0; j < d->config_len; j++) + seq_printf(s, "config[%d]=%d\n", j, config[j]); + + seq_puts(s, "Device control:\n"); + seq_printf(s, "Config Change %d ", dc->config_change); + seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); + seq_printf(s, "Guest Ack %d ", dc->guest_ack); + seq_printf(s, "Host ack %d\n", dc->host_ack); + seq_printf(s, "Used address updated %d ", + dc->used_address_updated); + seq_printf(s, "Vdev 0x%llx\n", dc->vdev); + seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); + seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); + } + return 0; } @@ -229,6 +283,89 @@ static const struct file_operations dp_ops = { .release = mic_dp_debug_release }; +static int mic_vdev_info_show(struct seq_file *s, void *unused) +{ + struct mic_device *mdev = s->private; + struct list_head *pos, *tmp; + struct mic_vdev *mvdev; + int i, j; + + mutex_lock(&mdev->mic_mutex); + list_for_each_safe(pos, tmp, &mdev->vdev_list) { + mvdev = list_entry(pos, struct mic_vdev, list); + seq_printf(s, "VDEV type %d state %s in %ld out %ld\n", + mvdev->virtio_id, + mic_vdevup(mvdev) ? "UP" : "DOWN", + mvdev->in_bytes, + mvdev->out_bytes); + for (i = 0; i < MIC_MAX_VRINGS; i++) { + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; + struct mic_vringh *mvr = &mvdev->mvr[i]; + struct vringh *vrh = &mvr->vrh; + int num = vrh->vring.num; + if (!num) + continue; + desc = vrh->vring.desc; + seq_printf(s, "vring i %d avail_idx %d", + i, mvr->vring.info->avail_idx & (num - 1)); + seq_printf(s, " vring i %d avail_idx %d\n", + i, mvr->vring.info->avail_idx); + seq_printf(s, "vrh i %d weak_barriers %d", + i, vrh->weak_barriers); + seq_printf(s, " last_avail_idx %d last_used_idx %d", + vrh->last_avail_idx, vrh->last_used_idx); + seq_printf(s, " completed %d\n", vrh->completed); + for (j = 0; j < num; j++) { + seq_printf(s, "desc[%d] addr 0x%llx len %d", + j, desc->addr, desc->len); + seq_printf(s, " flags 0x%x next %d\n", + desc->flags, + desc->next); + desc++; + } + avail = vrh->vring.avail; + seq_printf(s, "avail flags 0x%x idx %d\n", + avail->flags, avail->idx & (num - 1)); + seq_printf(s, "avail flags 0x%x idx %d\n", + avail->flags, avail->idx); + for (j = 0; j < num; j++) + seq_printf(s, "avail ring[%d] %d\n", + j, avail->ring[j]); + used = vrh->vring.used; + seq_printf(s, "used flags 0x%x idx %d\n", + used->flags, used->idx & (num - 1)); + seq_printf(s, "used flags 0x%x idx %d\n", + used->flags, used->idx); + for (j = 0; j < num; j++) + seq_printf(s, "used ring[%d] id %d len %d\n", + j, used->ring[j].id, used->ring[j].len); + } + } + mutex_unlock(&mdev->mic_mutex); + + return 0; +} + +static int mic_vdev_info_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, mic_vdev_info_show, inode->i_private); +} + +static int mic_vdev_info_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations vdev_info_ops = { + .owner = THIS_MODULE, + .open = mic_vdev_info_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mic_vdev_info_debug_release +}; + static int mic_msi_irq_info_show(struct seq_file *s, void *pos) { struct mic_device *mdev = s->private; @@ -321,6 +458,9 @@ void mic_create_debug_dir(struct mic_device *mdev) debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops); + debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, + mdev, &vdev_info_ops); + debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev, &msi_irq_info_ops); } diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 50b8b88d70d3..dcba2a59e77f 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -21,6 +21,7 @@ #ifndef _MIC_DEVICE_H_ #define _MIC_DEVICE_H_ +#include #include #include "mic_intr.h" @@ -80,6 +81,8 @@ enum mic_stepping { * @dp_dma_addr: virtio device page DMA address. * @shutdown_db: shutdown doorbell. * @shutdown_cookie: shutdown cookie. + * @cdev: Character device for MIC. + * @vdev_list: list of virtio devices. */ struct mic_device { struct mic_mw mmio; @@ -113,6 +116,8 @@ struct mic_device { dma_addr_t dp_dma_addr; int shutdown_db; struct mic_irq *shutdown_cookie; + struct cdev cdev; + struct list_head vdev_list; }; /** diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c new file mode 100644 index 000000000000..661469ad339d --- /dev/null +++ b/drivers/misc/mic/host/mic_fops.c @@ -0,0 +1,221 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#include + +#include +#include "../common/mic_device.h" +#include "mic_device.h" +#include "mic_fops.h" +#include "mic_virtio.h" + +int mic_open(struct inode *inode, struct file *f) +{ + struct mic_vdev *mvdev; + struct mic_device *mdev = container_of(inode->i_cdev, + struct mic_device, cdev); + + mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL); + if (!mvdev) + return -ENOMEM; + + init_waitqueue_head(&mvdev->waitq); + INIT_LIST_HEAD(&mvdev->list); + mvdev->mdev = mdev; + mvdev->virtio_id = -1; + + f->private_data = mvdev; + return 0; +} + +int mic_release(struct inode *inode, struct file *f) +{ + struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; + + if (-1 != mvdev->virtio_id) + mic_virtio_del_device(mvdev); + f->private_data = NULL; + kfree(mvdev); + return 0; +} + +long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; + void __user *argp = (void __user *)arg; + int ret; + + switch (cmd) { + case MIC_VIRTIO_ADD_DEVICE: + { + ret = mic_virtio_add_device(mvdev, argp); + if (ret < 0) { + dev_err(mic_dev(mvdev), + "%s %d errno ret %d\n", + __func__, __LINE__, ret); + return ret; + } + break; + } + case MIC_VIRTIO_COPY_DESC: + { + struct mic_copy_desc copy; + + ret = mic_vdev_inited(mvdev); + if (ret) + return ret; + + if (copy_from_user(©, argp, sizeof(copy))) + return -EFAULT; + + dev_dbg(mic_dev(mvdev), + "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n", + __func__, __LINE__, copy.iovcnt, copy.vr_idx, + copy.update_used); + + ret = mic_virtio_copy_desc(mvdev, ©); + if (ret < 0) { + dev_err(mic_dev(mvdev), + "%s %d errno ret %d\n", + __func__, __LINE__, ret); + return ret; + } + if (copy_to_user( + &((struct mic_copy_desc __user *)argp)->out_len, + ©.out_len, sizeof(copy.out_len))) { + dev_err(mic_dev(mvdev), "%s %d errno ret %d\n", + __func__, __LINE__, -EFAULT); + return -EFAULT; + } + break; + } + case MIC_VIRTIO_CONFIG_CHANGE: + { + ret = mic_vdev_inited(mvdev); + if (ret) + return ret; + + ret = mic_virtio_config_change(mvdev, argp); + if (ret < 0) { + dev_err(mic_dev(mvdev), + "%s %d errno ret %d\n", + __func__, __LINE__, ret); + return ret; + } + break; + } + default: + return -ENOIOCTLCMD; + }; + return 0; +} + +/* + * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and + * not when previously enqueued buffers may be available. This means that + * in the card->host (TX) path, when userspace is unblocked by poll it + * must drain all available descriptors or it can stall. + */ +unsigned int mic_poll(struct file *f, poll_table *wait) +{ + struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; + int mask = 0; + + poll_wait(f, &mvdev->waitq, wait); + + if (mic_vdev_inited(mvdev)) + mask = POLLERR; + else if (mvdev->poll_wake) { + mvdev->poll_wake = 0; + mask = POLLIN | POLLOUT; + } + + return mask; +} + +static inline int +mic_query_offset(struct mic_vdev *mvdev, unsigned long offset, + unsigned long *size, unsigned long *pa) +{ + struct mic_device *mdev = mvdev->mdev; + unsigned long start = MIC_DP_SIZE; + int i; + + /* + * MMAP interface is as follows: + * offset region + * 0x0 virtio device_page + * 0x1000 first vring + * 0x1000 + size of 1st vring second vring + * .... + */ + if (!offset) { + *pa = virt_to_phys(mdev->dp); + *size = MIC_DP_SIZE; + return 0; + } + + for (i = 0; i < mvdev->dd->num_vq; i++) { + struct mic_vringh *mvr = &mvdev->mvr[i]; + if (offset == start) { + *pa = virt_to_phys(mvr->vring.va); + *size = mvr->vring.len; + return 0; + } + start += mvr->vring.len; + } + return -1; +} + +/* + * Maps the device page and virtio rings to user space for readonly access. + */ +int +mic_mmap(struct file *f, struct vm_area_struct *vma) +{ + struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size; + int i, err; + + err = mic_vdev_inited(mvdev); + if (err) + return err; + + if (vma->vm_flags & VM_WRITE) + return -EACCES; + + while (size_rem) { + i = mic_query_offset(mvdev, offset, &size, &pa); + if (i < 0) + return -EINVAL; + err = remap_pfn_range(vma, vma->vm_start + offset, + pa >> PAGE_SHIFT, size, vma->vm_page_prot); + if (err) + return err; + dev_dbg(mic_dev(mvdev), + "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n", + __func__, __LINE__, mvdev->virtio_id, size, offset, + pa, vma->vm_start + offset); + size_rem -= size; + offset += size; + } + return 0; +} diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h new file mode 100644 index 000000000000..dc3893dff667 --- /dev/null +++ b/drivers/misc/mic/host/mic_fops.h @@ -0,0 +1,32 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#ifndef _MIC_FOPS_H_ +#define _MIC_FOPS_H_ + +int mic_open(struct inode *inode, struct file *filp); +int mic_release(struct inode *inode, struct file *filp); +ssize_t mic_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos); +long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +int mic_mmap(struct file *f, struct vm_area_struct *vma); +unsigned int mic_poll(struct file *f, poll_table *wait); + +#endif diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index 998a20ab7e96..a8965d496e84 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -25,12 +25,15 @@ #include #include #include +#include #include #include "../common/mic_device.h" #include "mic_device.h" #include "mic_x100.h" #include "mic_smpt.h" +#include "mic_fops.h" +#include "mic_virtio.h" static const char mic_driver_name[] = "mic"; @@ -64,6 +67,15 @@ static struct class *g_mic_class; /* Base device node number for MIC devices */ static dev_t g_mic_devno; +static const struct file_operations mic_fops = { + .open = mic_open, + .release = mic_release, + .unlocked_ioctl = mic_ioctl, + .poll = mic_poll, + .mmap = mic_mmap, + .owner = THIS_MODULE, +}; + /* Initialize the device page */ static int mic_dp_init(struct mic_device *mdev) { @@ -193,6 +205,7 @@ mic_device_init(struct mic_device *mdev, struct pci_dev *pdev) mdev->irq_info.next_avail_src = 0; INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work); INIT_WORK(&mdev->shutdown_work, mic_shutdown_work); + INIT_LIST_HEAD(&mdev->vdev_list); } /** @@ -330,7 +343,19 @@ static int mic_probe(struct pci_dev *pdev, mic_bootparam_init(mdev); mic_create_debug_dir(mdev); + cdev_init(&mdev->cdev, &mic_fops); + mdev->cdev.owner = THIS_MODULE; + rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1); + if (rc) { + dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc); + goto cleanup_debug_dir; + } return 0; +cleanup_debug_dir: + mic_delete_debug_dir(mdev); + mutex_lock(&mdev->mic_mutex); + mic_free_irq(mdev, mdev->shutdown_cookie, mdev); + mutex_unlock(&mdev->mic_mutex); dp_uninit: mic_dp_uninit(mdev); sysfs_put: @@ -375,6 +400,7 @@ static void mic_remove(struct pci_dev *pdev) return; mic_stop(mdev, false); + cdev_del(&mdev->cdev); mic_delete_debug_dir(mdev); mutex_lock(&mdev->mic_mutex); mic_free_irq(mdev, mdev->shutdown_cookie, mdev); diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c new file mode 100644 index 000000000000..be2a1f06c4ca --- /dev/null +++ b/drivers/misc/mic/host/mic_virtio.c @@ -0,0 +1,703 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#include +#include +#include + +#include +#include "../common/mic_device.h" +#include "mic_device.h" +#include "mic_smpt.h" +#include "mic_virtio.h" + +/* + * Initiates the copies across the PCIe bus from card memory to + * a user space buffer. + */ +static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, + void __user *ubuf, size_t len, u64 addr) +{ + int err; + void __iomem *dbuf = mvdev->mdev->aper.va + addr; + /* + * We are copying from IO below an should ideally use something + * like copy_to_user_fromio(..) if it existed. + */ + if (copy_to_user(ubuf, dbuf, len)) { + err = -EFAULT; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + mvdev->in_bytes += len; + err = 0; +err: + return err; +} + +/* + * Initiates copies across the PCIe bus from a user space + * buffer to card memory. + */ +static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, + void __user *ubuf, size_t len, u64 addr) +{ + int err; + void __iomem *dbuf = mvdev->mdev->aper.va + addr; + /* + * We are copying to IO below and should ideally use something + * like copy_from_user_toio(..) if it existed. + */ + if (copy_from_user(dbuf, ubuf, len)) { + err = -EFAULT; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + mvdev->out_bytes += len; + err = 0; +err: + return err; +} + +#define MIC_VRINGH_READ true + +/* The function to call to notify the card about added buffers */ +static void mic_notify(struct vringh *vrh) +{ + struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh); + struct mic_vdev *mvdev = mvrh->mvdev; + s8 db = mvdev->dc->h2c_vdev_db; + + if (db != -1) + mvdev->mdev->ops->send_intr(mvdev->mdev, db); +} + +/* Determine the total number of bytes consumed in a VRINGH KIOV */ +static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov) +{ + int i; + u32 total = iov->consumed; + + for (i = 0; i < iov->i; i++) + total += iov->iov[i].iov_len; + return total; +} + +/* + * Traverse the VRINGH KIOV and issue the APIs to trigger the copies. + * This API is heavily based on the vringh_iov_xfer(..) implementation + * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..) + * and vringh_iov_push_kern(..) directly is because there is no + * way to override the VRINGH xfer(..) routines as of v3.10. + */ +static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, + void __user *ubuf, size_t len, bool read, size_t *out_len) +{ + int ret = 0; + size_t partlen, tot_len = 0; + + while (len && iov->i < iov->used) { + partlen = min(iov->iov[iov->i].iov_len, len); + if (read) + ret = mic_virtio_copy_to_user(mvdev, + ubuf, partlen, + (u64)iov->iov[iov->i].iov_base); + else + ret = mic_virtio_copy_from_user(mvdev, + ubuf, partlen, + (u64)iov->iov[iov->i].iov_base); + if (ret) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= partlen; + ubuf += partlen; + tot_len += partlen; + iov->consumed += partlen; + iov->iov[iov->i].iov_len -= partlen; + iov->iov[iov->i].iov_base += partlen; + if (!iov->iov[iov->i].iov_len) { + /* Fix up old iov element then increment. */ + iov->iov[iov->i].iov_len = iov->consumed; + iov->iov[iov->i].iov_base -= iov->consumed; + + iov->consumed = 0; + iov->i++; + } + } + *out_len = tot_len; + return ret; +} + +/* + * Use the standard VRINGH infrastructure in the kernel to fetch new + * descriptors, initiate the copies and update the used ring. + */ +static int _mic_virtio_copy(struct mic_vdev *mvdev, + struct mic_copy_desc *copy) +{ + int ret = 0, iovcnt = copy->iovcnt; + struct iovec iov; + struct iovec __user *u_iov = copy->iov; + void __user *ubuf = NULL; + struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx]; + struct vringh_kiov *riov = &mvr->riov; + struct vringh_kiov *wiov = &mvr->wiov; + struct vringh *vrh = &mvr->vrh; + u16 *head = &mvr->head; + struct mic_vring *vr = &mvr->vring; + size_t len = 0, out_len; + + copy->out_len = 0; + /* Fetch a new IOVEC if all previous elements have been processed */ + if (riov->i == riov->used && wiov->i == wiov->used) { + ret = vringh_getdesc_kern(vrh, riov, wiov, + head, GFP_KERNEL); + /* Check if there are available descriptors */ + if (ret <= 0) + return ret; + } + while (iovcnt) { + if (!len) { + /* Copy over a new iovec from user space. */ + ret = copy_from_user(&iov, u_iov, sizeof(*u_iov)); + if (ret) { + ret = -EINVAL; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len = iov.iov_len; + ubuf = iov.iov_base; + } + /* Issue all the read descriptors first */ + ret = mic_vringh_copy(mvdev, riov, ubuf, len, + MIC_VRINGH_READ, &out_len); + if (ret) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= out_len; + ubuf += out_len; + copy->out_len += out_len; + /* Issue the write descriptors next */ + ret = mic_vringh_copy(mvdev, wiov, ubuf, len, + !MIC_VRINGH_READ, &out_len); + if (ret) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= out_len; + ubuf += out_len; + copy->out_len += out_len; + if (!len) { + /* One user space iovec is now completed */ + iovcnt--; + u_iov++; + } + /* Exit loop if all elements in KIOVs have been processed. */ + if (riov->i == riov->used && wiov->i == wiov->used) + break; + } + /* + * Update the used ring if a descriptor was available and some data was + * copied in/out and the user asked for a used ring update. + */ + if (*head != USHRT_MAX && copy->out_len && + copy->update_used) { + u32 total = 0; + + /* Determine the total data consumed */ + total += mic_vringh_iov_consumed(riov); + total += mic_vringh_iov_consumed(wiov); + vringh_complete_kern(vrh, *head, total); + *head = USHRT_MAX; + if (vringh_need_notify_kern(vrh) > 0) + vringh_notify(vrh); + vringh_kiov_cleanup(riov); + vringh_kiov_cleanup(wiov); + /* Update avail idx for user space */ + vr->info->avail_idx = vrh->last_avail_idx; + } + return ret; +} + +static inline int mic_verify_copy_args(struct mic_vdev *mvdev, + struct mic_copy_desc *copy) +{ + if (copy->vr_idx >= mvdev->dd->num_vq) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -EINVAL); + return -EINVAL; + } + return 0; +} + +/* Copy a specified number of virtio descriptors in a chain */ +int mic_virtio_copy_desc(struct mic_vdev *mvdev, + struct mic_copy_desc *copy) +{ + int err; + struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx]; + + err = mic_verify_copy_args(mvdev, copy); + if (err) + return err; + + mutex_lock(&mvr->vr_mutex); + if (!mic_vdevup(mvdev)) { + err = -ENODEV; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + err = _mic_virtio_copy(mvdev, copy); + if (err) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, err); + } +err: + mutex_unlock(&mvr->vr_mutex); + return err; +} + +static void mic_virtio_init_post(struct mic_vdev *mvdev) +{ + struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd); + int i; + + for (i = 0; i < mvdev->dd->num_vq; i++) { + if (!le64_to_cpu(vqconfig[i].used_address)) { + dev_warn(mic_dev(mvdev), "used_address zero??\n"); + continue; + } + mvdev->mvr[i].vrh.vring.used = + mvdev->mdev->aper.va + + le64_to_cpu(vqconfig[i].used_address); + } + + mvdev->dc->used_address_updated = 0; + + dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n", + __func__, mvdev->virtio_id); +} + +static inline void mic_virtio_device_reset(struct mic_vdev *mvdev) +{ + int i; + + dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n", + __func__, mvdev->dd->status, mvdev->virtio_id); + + for (i = 0; i < mvdev->dd->num_vq; i++) + /* + * Avoid lockdep false positive. The + 1 is for the mic + * mutex which is held in the reset devices code path. + */ + mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1); + + /* 0 status means "reset" */ + mvdev->dd->status = 0; + mvdev->dc->vdev_reset = 0; + mvdev->dc->host_ack = 1; + + for (i = 0; i < mvdev->dd->num_vq; i++) { + struct vringh *vrh = &mvdev->mvr[i].vrh; + mvdev->mvr[i].vring.info->avail_idx = 0; + vrh->completed = 0; + vrh->last_avail_idx = 0; + vrh->last_used_idx = 0; + } + + for (i = 0; i < mvdev->dd->num_vq; i++) + mutex_unlock(&mvdev->mvr[i].vr_mutex); +} + +void mic_virtio_reset_devices(struct mic_device *mdev) +{ + struct list_head *pos, *tmp; + struct mic_vdev *mvdev; + + dev_dbg(mdev->sdev->parent, "%s\n", __func__); + + list_for_each_safe(pos, tmp, &mdev->vdev_list) { + mvdev = list_entry(pos, struct mic_vdev, list); + mic_virtio_device_reset(mvdev); + mvdev->poll_wake = 1; + wake_up(&mvdev->waitq); + } +} + +void mic_bh_handler(struct work_struct *work) +{ + struct mic_vdev *mvdev = container_of(work, struct mic_vdev, + virtio_bh_work); + + if (mvdev->dc->used_address_updated) + mic_virtio_init_post(mvdev); + + if (mvdev->dc->vdev_reset) + mic_virtio_device_reset(mvdev); + + mvdev->poll_wake = 1; + wake_up(&mvdev->waitq); +} + +static irqreturn_t mic_virtio_intr_handler(int irq, void *data) +{ + + struct mic_vdev *mvdev = data; + struct mic_device *mdev = mvdev->mdev; + + mdev->ops->ack_interrupt(mdev); + schedule_work(&mvdev->virtio_bh_work); + return IRQ_HANDLED; +} + +int mic_virtio_config_change(struct mic_vdev *mvdev, + void __user *argp) +{ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + int ret = 0, retry = 100, i; + struct mic_bootparam *bootparam = mvdev->mdev->dp; + s8 db = bootparam->h2c_config_db; + + mutex_lock(&mvdev->mdev->mic_mutex); + for (i = 0; i < mvdev->dd->num_vq; i++) + mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1); + + if (db == -1 || mvdev->dd->type == -1) { + ret = -EIO; + goto exit; + } + + if (copy_from_user(mic_vq_configspace(mvdev->dd), + argp, mvdev->dd->config_len)) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -EFAULT); + ret = -EFAULT; + goto exit; + } + mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED; + mvdev->mdev->ops->send_intr(mvdev->mdev, db); + + for (i = retry; i--;) { + ret = wait_event_timeout(wake, + mvdev->dc->guest_ack, msecs_to_jiffies(100)); + if (ret) + break; + } + + dev_dbg(mic_dev(mvdev), + "%s %d retry: %d\n", __func__, __LINE__, retry); + mvdev->dc->config_change = 0; + mvdev->dc->guest_ack = 0; +exit: + for (i = 0; i < mvdev->dd->num_vq; i++) + mutex_unlock(&mvdev->mvr[i].vr_mutex); + mutex_unlock(&mvdev->mdev->mic_mutex); + return ret; +} + +static int mic_copy_dp_entry(struct mic_vdev *mvdev, + void __user *argp, + __u8 *type, + struct mic_device_desc **devpage) +{ + struct mic_device *mdev = mvdev->mdev; + struct mic_device_desc dd, *dd_config, *devp; + struct mic_vqconfig *vqconfig; + int ret = 0, i; + bool slot_found = false; + + if (copy_from_user(&dd, argp, sizeof(dd))) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -EFAULT); + return -EFAULT; + } + + if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE + || dd.num_vq > MIC_MAX_VRINGS) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -EINVAL); + return -EINVAL; + } + + dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL); + if (dd_config == NULL) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -ENOMEM); + return -ENOMEM; + } + if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) { + ret = -EFAULT; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto exit; + } + + vqconfig = mic_vq_config(dd_config); + for (i = 0; i < dd.num_vq; i++) { + if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) { + ret = -EINVAL; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto exit; + } + } + + /* Find the first free device page entry */ + for (i = mic_aligned_size(struct mic_bootparam); + i < MIC_DP_SIZE - mic_total_desc_size(dd_config); + i += mic_total_desc_size(devp)) { + devp = mdev->dp + i; + if (devp->type == 0 || devp->type == -1) { + slot_found = true; + break; + } + } + if (!slot_found) { + ret = -EINVAL; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto exit; + } + /* + * Save off the type before doing the memcpy. Type will be set in the + * end after completing all initialization for the new device. + */ + *type = dd_config->type; + dd_config->type = 0; + memcpy(devp, dd_config, mic_desc_size(dd_config)); + + *devpage = devp; +exit: + kfree(dd_config); + return ret; +} + +static void mic_init_device_ctrl(struct mic_vdev *mvdev, + struct mic_device_desc *devpage) +{ + struct mic_device_ctrl *dc; + + dc = mvdev->dc = (void *)devpage + mic_aligned_desc_size(devpage); + + dc->config_change = 0; + dc->guest_ack = 0; + dc->vdev_reset = 0; + dc->host_ack = 0; + dc->used_address_updated = 0; + dc->c2h_vdev_db = -1; + dc->h2c_vdev_db = -1; +} + +int mic_virtio_add_device(struct mic_vdev *mvdev, + void __user *argp) +{ + struct mic_device *mdev = mvdev->mdev; + struct mic_device_desc *dd; + struct mic_vqconfig *vqconfig; + int vr_size, i, j, ret; + u8 type; + s8 db; + char irqname[10]; + struct mic_bootparam *bootparam = mdev->dp; + u16 num; + + mutex_lock(&mdev->mic_mutex); + + ret = mic_copy_dp_entry(mvdev, argp, &type, &dd); + if (ret) { + mutex_unlock(&mdev->mic_mutex); + return ret; + } + + mic_init_device_ctrl(mvdev, dd); + + mvdev->dd = dd; + mvdev->virtio_id = type; + vqconfig = mic_vq_config(dd); + INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler); + + for (i = 0; i < dd->num_vq; i++) { + struct mic_vringh *mvr = &mvdev->mvr[i]; + struct mic_vring *vr = &mvdev->mvr[i].vring; + num = le16_to_cpu(vqconfig[i].num); + mutex_init(&mvr->vr_mutex); + vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) + + sizeof(struct _mic_vring_info)); + vr->va = (void *) + __get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(vr_size)); + if (!vr->va) { + ret = -ENOMEM; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vr->len = vr_size; + vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN); + vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i; + vqconfig[i].address = mic_map_single(mdev, + vr->va, vr_size); + if (mic_map_error(vqconfig[i].address)) { + free_pages((unsigned long)vr->va, + get_order(vr_size)); + ret = -ENOMEM; + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vqconfig[i].address = cpu_to_le64(vqconfig[i].address); + + vring_init(&vr->vr, num, + vr->va, MIC_VIRTIO_RING_ALIGN); + ret = vringh_init_kern(&mvr->vrh, + *(u32 *)mic_vq_features(mvdev->dd), num, false, + vr->vr.desc, vr->vr.avail, vr->vr.used); + if (ret) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vringh_kiov_init(&mvr->riov, NULL, 0); + vringh_kiov_init(&mvr->wiov, NULL, 0); + mvr->head = USHRT_MAX; + mvr->mvdev = mvdev; + mvr->vrh.notify = mic_notify; + dev_dbg(mdev->sdev->parent, + "%s %d index %d va %p info %p vr_size 0x%x\n", + __func__, __LINE__, i, vr->va, vr->info, vr_size); + } + + snprintf(irqname, sizeof(irqname), + "mic%dvirtio%d", mdev->id, mvdev->virtio_id); + mvdev->virtio_db = mic_next_db(mdev); + mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler, + irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB); + if (IS_ERR(mvdev->virtio_cookie)) { + ret = PTR_ERR(mvdev->virtio_cookie); + dev_dbg(mdev->sdev->parent, "request irq failed\n"); + goto err; + } + + mvdev->dc->c2h_vdev_db = mvdev->virtio_db; + + list_add_tail(&mvdev->list, &mdev->vdev_list); + /* + * Order the type update with previous stores. This write barrier + * is paired with the corresponding read barrier before the uncached + * system memory read of the type, on the card while scanning the + * device page. + */ + smp_wmb(); + dd->type = type; + + dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type); + + db = bootparam->h2c_config_db; + if (db != -1) + mdev->ops->send_intr(mdev, db); + mutex_unlock(&mdev->mic_mutex); + return 0; +err: + vqconfig = mic_vq_config(dd); + for (j = 0; j < i; j++) { + struct mic_vringh *mvr = &mvdev->mvr[j]; + mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address), + mvr->vring.len); + free_pages((unsigned long)mvr->vring.va, + get_order(mvr->vring.len)); + } + mutex_unlock(&mdev->mic_mutex); + return ret; +} + +void mic_virtio_del_device(struct mic_vdev *mvdev) +{ + struct list_head *pos, *tmp; + struct mic_vdev *tmp_mvdev; + struct mic_device *mdev = mvdev->mdev; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + int i, ret, retry = 100; + struct mic_vqconfig *vqconfig; + struct mic_bootparam *bootparam = mdev->dp; + s8 db; + + mutex_lock(&mdev->mic_mutex); + db = bootparam->h2c_config_db; + if (db == -1) + goto skip_hot_remove; + dev_dbg(mdev->sdev->parent, + "Requesting hot remove id %d\n", mvdev->virtio_id); + mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE; + mdev->ops->send_intr(mdev, db); + for (i = retry; i--;) { + ret = wait_event_timeout(wake, + mvdev->dc->guest_ack, msecs_to_jiffies(100)); + if (ret) + break; + } + dev_dbg(mdev->sdev->parent, + "Device id %d config_change %d guest_ack %d\n", + mvdev->virtio_id, mvdev->dc->config_change, + mvdev->dc->guest_ack); + mvdev->dc->config_change = 0; + mvdev->dc->guest_ack = 0; +skip_hot_remove: + mic_free_irq(mdev, mvdev->virtio_cookie, mvdev); + flush_work(&mvdev->virtio_bh_work); + vqconfig = mic_vq_config(mvdev->dd); + for (i = 0; i < mvdev->dd->num_vq; i++) { + struct mic_vringh *mvr = &mvdev->mvr[i]; + vringh_kiov_cleanup(&mvr->riov); + vringh_kiov_cleanup(&mvr->wiov); + mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address), + mvr->vring.len); + free_pages((unsigned long)mvr->vring.va, + get_order(mvr->vring.len)); + } + + list_for_each_safe(pos, tmp, &mdev->vdev_list) { + tmp_mvdev = list_entry(pos, struct mic_vdev, list); + if (tmp_mvdev == mvdev) { + list_del(pos); + dev_dbg(mdev->sdev->parent, + "Removing virtio device id %d\n", + mvdev->virtio_id); + break; + } + } + /* + * Order the type update with previous stores. This write barrier + * is paired with the corresponding read barrier before the uncached + * system memory read of the type, on the card while scanning the + * device page. + */ + smp_wmb(); + mvdev->dd->type = -1; + mutex_unlock(&mdev->mic_mutex); +} diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h new file mode 100644 index 000000000000..184f3c84805b --- /dev/null +++ b/drivers/misc/mic/host/mic_virtio.h @@ -0,0 +1,138 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#ifndef MIC_VIRTIO_H +#define MIC_VIRTIO_H + +#include +#include + +/* + * Note on endianness. + * 1. Host can be both BE or LE + * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail + * rings and ioreadXX/iowriteXX to access used ring. + * 3. Device page exposed by host to guest contains LE values. Guest + * accesses these using ioreadXX/iowriteXX etc. This way in general we + * obey the virtio spec according to which guest works with native + * endianness and host is aware of guest endianness and does all + * required endianness conversion. + * 4. Data provided from user space to guest (in ADD_DEVICE and + * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be + * in guest endianness. + */ + +/** + * struct mic_vringh - Virtio ring host information. + * + * @vring: The MIC vring used for setting up user space mappings. + * @vrh: The host VRINGH used for accessing the card vrings. + * @riov: The VRINGH read kernel IOV. + * @wiov: The VRINGH write kernel IOV. + * @head: The VRINGH head index address passed to vringh_getdesc_kern(..). + * @vr_mutex: Mutex for synchronizing access to the VRING. + * @mvdev: Back pointer to MIC virtio device for vringh_notify(..). + */ +struct mic_vringh { + struct mic_vring vring; + struct vringh vrh; + struct vringh_kiov riov; + struct vringh_kiov wiov; + u16 head; + struct mutex vr_mutex; + struct mic_vdev *mvdev; +}; + +/** + * struct mic_vdev - Host information for a card Virtio device. + * + * @virtio_id - Virtio device id. + * @waitq - Waitqueue to allow ring3 apps to poll. + * @mdev - Back pointer to host MIC device. + * @poll_wake - Used for waking up threads blocked in poll. + * @out_bytes - Debug stats for number of bytes copied from host to card. + * @in_bytes - Debug stats for number of bytes copied from card to host. + * @mvr - Store per VRING data structures. + * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. + * @dd - Virtio device descriptor. + * @dc - Virtio device control fields. + * @list - List of Virtio devices. + * @virtio_db - The doorbell used by the card to interrupt the host. + * @virtio_cookie - The cookie returned while requesting interrupts. + */ +struct mic_vdev { + int virtio_id; + wait_queue_head_t waitq; + struct mic_device *mdev; + int poll_wake; + unsigned long out_bytes; + unsigned long in_bytes; + struct mic_vringh mvr[MIC_MAX_VRINGS]; + struct work_struct virtio_bh_work; + struct mic_device_desc *dd; + struct mic_device_ctrl *dc; + struct list_head list; + int virtio_db; + struct mic_irq *virtio_cookie; +}; + +void mic_virtio_uninit(struct mic_device *mdev); +int mic_virtio_add_device(struct mic_vdev *mvdev, + void __user *argp); +void mic_virtio_del_device(struct mic_vdev *mvdev); +int mic_virtio_config_change(struct mic_vdev *mvdev, + void __user *argp); +int mic_virtio_copy_desc(struct mic_vdev *mvdev, + struct mic_copy_desc *request); +void mic_virtio_reset_devices(struct mic_device *mdev); +void mic_bh_handler(struct work_struct *work); + +/* Helper API to obtain the MIC PCIe device */ +static inline struct device *mic_dev(struct mic_vdev *mvdev) +{ + return mvdev->mdev->sdev->parent; +} + +/* Helper API to check if a virtio device is initialized */ +static inline int mic_vdev_inited(struct mic_vdev *mvdev) +{ + /* Device has not been created yet */ + if (!mvdev->dd || !mvdev->dd->type) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -EINVAL); + return -EINVAL; + } + + /* Device has been removed/deleted */ + if (mvdev->dd->type == -1) { + dev_err(mic_dev(mvdev), "%s %d err %d\n", + __func__, __LINE__, -ENODEV); + return -ENODEV; + } + + return 0; +} + +/* Helper API to check if a virtio device is running */ +static inline bool mic_vdevup(struct mic_vdev *mvdev) +{ + return !!mvdev->dd->status; +} +#endif diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index d37263fbdca7..33d2b8fe166d 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -242,6 +242,7 @@ header-y += mei.h header-y += mempolicy.h header-y += meye.h header-y += mic_common.h +header-y += mic_ioctl.h header-y += mii.h header-y += minix_fs.h header-y += mman.h diff --git a/include/uapi/linux/mic_common.h b/include/uapi/linux/mic_common.h index a9091e529183..364ac751bd04 100644 --- a/include/uapi/linux/mic_common.h +++ b/include/uapi/linux/mic_common.h @@ -21,7 +21,60 @@ #ifndef __MIC_COMMON_H_ #define __MIC_COMMON_H_ -#include +#include + +#ifndef __KERNEL__ +#define ALIGN(a, x) (((a) + (x) - 1) & ~((x) - 1)) +#define __aligned(x) __attribute__ ((aligned(x))) +#endif + +#define mic_aligned_size(x) ALIGN(sizeof(x), 8) + +/** + * struct mic_device_desc: Virtio device information shared between the + * virtio driver and userspace backend + * + * @type: Device type: console/network/disk etc. Type 0/-1 terminates. + * @num_vq: Number of virtqueues. + * @feature_len: Number of bytes of feature bits. Multiply by 2: one for + host features and one for guest acknowledgements. + * @config_len: Number of bytes of the config array after virtqueues. + * @status: A status byte, written by the Guest. + * @config: Start of the following variable length config. + */ +struct mic_device_desc { + __s8 type; + __u8 num_vq; + __u8 feature_len; + __u8 config_len; + __u8 status; + __u64 config[0]; +} __aligned(8); + +/** + * struct mic_device_ctrl: Per virtio device information in the device page + * used internally by the host and card side drivers. + * + * @vdev: Used for storing MIC vdev information by the guest. + * @config_change: Set to 1 by host when a config change is requested. + * @vdev_reset: Set to 1 by guest to indicate virtio device has been reset. + * @guest_ack: Set to 1 by guest to ack a command. + * @host_ack: Set to 1 by host to ack a command. + * @used_address_updated: Set to 1 by guest when the used address should be + * updated. + * @c2h_vdev_db: The doorbell number to be used by guest. Set by host. + * @h2c_vdev_db: The doorbell number to be used by host. Set by guest. + */ +struct mic_device_ctrl { + __u64 vdev; + __u8 config_change; + __u8 vdev_reset; + __u8 guest_ack; + __u8 host_ack; + __u8 used_address_updated; + __s8 c2h_vdev_db; + __s8 h2c_vdev_db; +} __aligned(8); /** * struct mic_bootparam: Virtio device independent information in device page @@ -42,6 +95,117 @@ struct mic_bootparam { __u8 shutdown_card; } __aligned(8); +/** + * struct mic_device_page: High level representation of the device page + * + * @bootparam: The bootparam structure is used for sharing information and + * status updates between MIC host and card drivers. + * @desc: Array of MIC virtio device descriptors. + */ +struct mic_device_page { + struct mic_bootparam bootparam; + struct mic_device_desc desc[0]; +}; +/** + * struct mic_vqconfig: This is how we expect the device configuration field + * for a virtqueue to be laid out in config space. + * + * @address: Guest/MIC physical address of the virtio ring + * (avail and desc rings) + * @used_address: Guest/MIC physical address of the used ring + * @num: The number of entries in the virtio_ring + */ +struct mic_vqconfig { + __u64 address; + __u64 used_address; + __u16 num; +} __aligned(8); + +/* + * The alignment to use between consumer and producer parts of vring. + * This is pagesize for historical reasons. + */ +#define MIC_VIRTIO_RING_ALIGN 4096 + +#define MIC_MAX_VRINGS 4 +#define MIC_VRING_ENTRIES 128 + +/* + * Max vring entries (power of 2) to ensure desc and avail rings + * fit in a single page + */ +#define MIC_MAX_VRING_ENTRIES 128 + +/** + * Max size of the desc block in bytes: includes: + * - struct mic_device_desc + * - struct mic_vqconfig (num_vq of these) + * - host and guest features + * - virtio device config space + */ +#define MIC_MAX_DESC_BLK_SIZE 256 + +/** + * struct _mic_vring_info - Host vring info exposed to userspace backend + * for the avail index and magic for the card. + * + * @avail_idx: host avail idx + * @magic: A magic debug cookie. + */ +struct _mic_vring_info { + __u16 avail_idx; + int magic; +}; + +/** + * struct mic_vring - Vring information. + * + * @vr: The virtio ring. + * @info: Host vring information exposed to the userspace backend for the + * avail index and magic for the card. + * @va: The va for the buffer allocated for vr and info. + * @len: The length of the buffer required for allocating vr and info. + */ +struct mic_vring { + struct vring vr; + struct _mic_vring_info *info; + void *va; + int len; +}; + +#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8) + +#ifndef INTEL_MIC_CARD +static inline unsigned mic_desc_size(const struct mic_device_desc *desc) +{ + return mic_aligned_size(*desc) + + desc->num_vq * mic_aligned_size(struct mic_vqconfig) + + desc->feature_len * 2 + + desc->config_len; +} + +static inline struct mic_vqconfig * +mic_vq_config(const struct mic_device_desc *desc) +{ + return (struct mic_vqconfig *)(desc + 1); +} + +static inline __u8 *mic_vq_features(const struct mic_device_desc *desc) +{ + return (__u8 *)(mic_vq_config(desc) + desc->num_vq); +} + +static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc) +{ + return mic_vq_features(desc) + desc->feature_len * 2; +} +static inline unsigned mic_total_desc_size(struct mic_device_desc *desc) +{ + return mic_aligned_desc_size(desc) + + mic_aligned_size(struct mic_device_ctrl); +} +#endif + /* Device page size */ #define MIC_DP_SIZE 4096 diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h new file mode 100644 index 000000000000..0e6cbf3e5292 --- /dev/null +++ b/include/uapi/linux/mic_ioctl.h @@ -0,0 +1,74 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel MIC Host driver. + * + */ +#ifndef _MIC_IOCTL_H_ +#define _MIC_IOCTL_H_ + +/* + * mic_copy - MIC virtio descriptor copy. + * + * @iov: An array of IOVEC structures containing user space buffers. + * @iovcnt: Number of IOVEC structures in iov. + * @vr_idx: The vring index. + * @update_used: A non zero value results in used index being updated. + * @out_len: The aggregate of the total length written to or read from + * the virtio device. + */ +struct mic_copy_desc { +#ifdef __KERNEL__ + struct iovec __user *iov; +#else + struct iovec *iov; +#endif + int iovcnt; + __u8 vr_idx; + __u8 update_used; + __u32 out_len; +}; + +/* + * Add a new virtio device + * The (struct mic_device_desc *) pointer points to a device page entry + * for the virtio device consisting of: + * - struct mic_device_desc + * - struct mic_vqconfig (num_vq of these) + * - host and guest features + * - virtio device config space + * The total size referenced by the pointer should equal the size returned + * by desc_size() in mic_common.h + */ +#define MIC_VIRTIO_ADD_DEVICE _IOWR('s', 1, struct mic_device_desc *) + +/* + * Copy the number of entries in the iovec and update the used index + * if requested by the user. + */ +#define MIC_VIRTIO_COPY_DESC _IOWR('s', 2, struct mic_copy_desc *) + +/* + * Notify virtio device of a config change + * The (__u8 *) pointer points to config space values for the device + * as they should be written into the device page. The total size + * referenced by the pointer should equal the config_len field of struct + * mic_device_desc. + */ +#define MIC_VIRTIO_CONFIG_CHANGE _IOWR('s', 5, __u8 *) + +#endif -- cgit From a0f4ecf3494c9869d20f606e7e2b2f50f0e67a7f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 26 Sep 2013 14:48:15 -0700 Subject: netfilter: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches --- include/linux/netfilter.h | 10 +- include/linux/netfilter/nf_conntrack_common.h | 2 +- include/linux/netfilter/nf_conntrack_h323.h | 14 +-- include/linux/netfilter/nf_conntrack_proto_gre.h | 4 +- include/linux/netfilter/nf_conntrack_sip.h | 57 +++++----- include/linux/netfilter/nfnetlink.h | 28 ++--- include/linux/netfilter/nfnetlink_acct.h | 6 +- include/linux/netfilter/x_tables.h | 128 +++++++++++------------ include/linux/netfilter_bridge.h | 4 +- include/linux/netfilter_ipv4.h | 6 +- include/linux/netfilter_ipv6.h | 10 +- 11 files changed, 133 insertions(+), 136 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 708fe72ab913..61223c52414f 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -35,7 +35,7 @@ static inline void nf_inet_addr_mask(const union nf_inet_addr *a1, result->all[3] = a1->all[3] & mask->all[3]; } -extern int netfilter_init(void); +int netfilter_init(void); /* Largest hook number + 1 */ #define NF_MAX_HOOKS 8 @@ -208,7 +208,7 @@ int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, /* Call this before modifying an existing packet: ensures it is modifiable and linear to the point you care about (writable_len). Returns true or false. */ -extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); +int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); struct flowi; struct nf_queue_entry; @@ -269,8 +269,8 @@ nf_checksum_partial(struct sk_buff *skb, unsigned int hook, return csum; } -extern int nf_register_afinfo(const struct nf_afinfo *afinfo); -extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo); +int nf_register_afinfo(const struct nf_afinfo *afinfo); +void nf_unregister_afinfo(const struct nf_afinfo *afinfo); #include extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); @@ -315,7 +315,7 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) extern void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *) __rcu; -extern void nf_ct_attach(struct sk_buff *, const struct sk_buff *); +void nf_ct_attach(struct sk_buff *, const struct sk_buff *); extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu; struct nf_conn; diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 127d0b90604f..275505792664 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -23,6 +23,6 @@ struct ip_conntrack_stat { }; /* call to create an explicit dependency on nf_conntrack. */ -extern void need_conntrack(void); +void need_conntrack(void); #endif /* _NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index f381020eee92..858d9b214053 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -29,13 +29,13 @@ struct nf_ct_h323_master { struct nf_conn; -extern int get_h225_addr(struct nf_conn *ct, unsigned char *data, - TransportAddress *taddr, - union nf_inet_addr *addr, __be16 *port); -extern void nf_conntrack_h245_expect(struct nf_conn *new, - struct nf_conntrack_expect *this); -extern void nf_conntrack_q931_expect(struct nf_conn *new, - struct nf_conntrack_expect *this); +int get_h225_addr(struct nf_conn *ct, unsigned char *data, + TransportAddress *taddr, union nf_inet_addr *addr, + __be16 *port); +void nf_conntrack_h245_expect(struct nf_conn *new, + struct nf_conntrack_expect *this); +void nf_conntrack_q931_expect(struct nf_conn *new, + struct nf_conntrack_expect *this); extern int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff, unsigned char **data, int dataoff, H245_TransportAddress *taddr, diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h index 6a0664c0c451..ec2ffaf418c8 100644 --- a/include/linux/netfilter/nf_conntrack_proto_gre.h +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -87,8 +87,8 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, /* delete keymap entries */ void nf_ct_gre_keymap_destroy(struct nf_conn *ct); -extern void nf_ct_gre_keymap_flush(struct net *net); -extern void nf_nat_need_gre(void); +void nf_ct_gre_keymap_flush(struct net *net); +void nf_nat_need_gre(void); #endif /* __KERNEL__ */ #endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index ba7f571a2b1c..5cac0207b95d 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -157,35 +157,34 @@ extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int medialen, union nf_inet_addr *rtp_addr); -extern int ct_sip_parse_request(const struct nf_conn *ct, - const char *dptr, unsigned int datalen, - unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr, __be16 *port); -extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr, - unsigned int dataoff, unsigned int datalen, - enum sip_header_types type, - unsigned int *matchoff, unsigned int *matchlen); -extern int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, - unsigned int *dataoff, unsigned int datalen, - enum sip_header_types type, int *in_header, - unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr, __be16 *port); -extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, - unsigned int dataoff, unsigned int datalen, - const char *name, - unsigned int *matchoff, unsigned int *matchlen, - union nf_inet_addr *addr, bool delim); -extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, - unsigned int off, unsigned int datalen, - const char *name, - unsigned int *matchoff, unsigned int *matchen, - unsigned int *val); - -extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, - unsigned int dataoff, unsigned int datalen, - enum sdp_header_types type, - enum sdp_header_types term, - unsigned int *matchoff, unsigned int *matchlen); +int ct_sip_parse_request(const struct nf_conn *ct, const char *dptr, + unsigned int datalen, unsigned int *matchoff, + unsigned int *matchlen, union nf_inet_addr *addr, + __be16 *port); +int ct_sip_get_header(const struct nf_conn *ct, const char *dptr, + unsigned int dataoff, unsigned int datalen, + enum sip_header_types type, unsigned int *matchoff, + unsigned int *matchlen); +int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, + unsigned int *dataoff, unsigned int datalen, + enum sip_header_types type, int *in_header, + unsigned int *matchoff, unsigned int *matchlen, + union nf_inet_addr *addr, __be16 *port); +int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, + unsigned int dataoff, unsigned int datalen, + const char *name, unsigned int *matchoff, + unsigned int *matchlen, union nf_inet_addr *addr, + bool delim); +int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, + unsigned int off, unsigned int datalen, + const char *name, unsigned int *matchoff, + unsigned int *matchen, unsigned int *val); + +int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, + unsigned int dataoff, unsigned int datalen, + enum sdp_header_types type, + enum sdp_header_types term, + unsigned int *matchoff, unsigned int *matchlen); #endif /* __KERNEL__ */ #endif /* __NF_CONNTRACK_SIP_H__ */ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index cadb7402d7a7..4f68cd7141d2 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -25,20 +25,20 @@ struct nfnetlink_subsystem { const struct nfnl_callback *cb; /* callback for individual types */ }; -extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); -extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); - -extern int nfnetlink_has_listeners(struct net *net, unsigned int group); -extern struct sk_buff *nfnetlink_alloc_skb(struct net *net, unsigned int size, - u32 dst_portid, gfp_t gfp_mask); -extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid, - unsigned int group, int echo, gfp_t flags); -extern int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error); -extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, - u32 portid, int flags); - -extern void nfnl_lock(__u8 subsys_id); -extern void nfnl_unlock(__u8 subsys_id); +int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); +int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); + +int nfnetlink_has_listeners(struct net *net, unsigned int group); +struct sk_buff *nfnetlink_alloc_skb(struct net *net, unsigned int size, + u32 dst_portid, gfp_t gfp_mask); +int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid, + unsigned int group, int echo, gfp_t flags); +int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error); +int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid, + int flags); + +void nfnl_lock(__u8 subsys_id); +void nfnl_unlock(__u8 subsys_id); #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) diff --git a/include/linux/netfilter/nfnetlink_acct.h b/include/linux/netfilter/nfnetlink_acct.h index bb4bbc9b7a18..b2e85e59f760 100644 --- a/include/linux/netfilter/nfnetlink_acct.h +++ b/include/linux/netfilter/nfnetlink_acct.h @@ -6,8 +6,8 @@ struct nf_acct; -extern struct nf_acct *nfnl_acct_find_get(const char *filter_name); -extern void nfnl_acct_put(struct nf_acct *acct); -extern void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct); +struct nf_acct *nfnl_acct_find_get(const char *filter_name); +void nfnl_acct_put(struct nf_acct *acct); +void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct); #endif /* _NFNL_ACCT_H */ diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index dd49566315c6..a3e215bb0241 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -229,50 +229,48 @@ struct xt_table_info { #define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \ + nr_cpu_ids * sizeof(char *)) -extern int xt_register_target(struct xt_target *target); -extern void xt_unregister_target(struct xt_target *target); -extern int xt_register_targets(struct xt_target *target, unsigned int n); -extern void xt_unregister_targets(struct xt_target *target, unsigned int n); - -extern int xt_register_match(struct xt_match *target); -extern void xt_unregister_match(struct xt_match *target); -extern int xt_register_matches(struct xt_match *match, unsigned int n); -extern void xt_unregister_matches(struct xt_match *match, unsigned int n); - -extern int xt_check_match(struct xt_mtchk_param *, - unsigned int size, u_int8_t proto, bool inv_proto); -extern int xt_check_target(struct xt_tgchk_param *, - unsigned int size, u_int8_t proto, bool inv_proto); - -extern struct xt_table *xt_register_table(struct net *net, - const struct xt_table *table, - struct xt_table_info *bootstrap, - struct xt_table_info *newinfo); -extern void *xt_unregister_table(struct xt_table *table); - -extern struct xt_table_info *xt_replace_table(struct xt_table *table, - unsigned int num_counters, - struct xt_table_info *newinfo, - int *error); - -extern struct xt_match *xt_find_match(u8 af, const char *name, u8 revision); -extern struct xt_target *xt_find_target(u8 af, const char *name, u8 revision); -extern struct xt_match *xt_request_find_match(u8 af, const char *name, - u8 revision); -extern struct xt_target *xt_request_find_target(u8 af, const char *name, - u8 revision); -extern int xt_find_revision(u8 af, const char *name, u8 revision, - int target, int *err); - -extern struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, - const char *name); -extern void xt_table_unlock(struct xt_table *t); - -extern int xt_proto_init(struct net *net, u_int8_t af); -extern void xt_proto_fini(struct net *net, u_int8_t af); - -extern struct xt_table_info *xt_alloc_table_info(unsigned int size); -extern void xt_free_table_info(struct xt_table_info *info); +int xt_register_target(struct xt_target *target); +void xt_unregister_target(struct xt_target *target); +int xt_register_targets(struct xt_target *target, unsigned int n); +void xt_unregister_targets(struct xt_target *target, unsigned int n); + +int xt_register_match(struct xt_match *target); +void xt_unregister_match(struct xt_match *target); +int xt_register_matches(struct xt_match *match, unsigned int n); +void xt_unregister_matches(struct xt_match *match, unsigned int n); + +int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, + bool inv_proto); +int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, + bool inv_proto); + +struct xt_table *xt_register_table(struct net *net, + const struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo); +void *xt_unregister_table(struct xt_table *table); + +struct xt_table_info *xt_replace_table(struct xt_table *table, + unsigned int num_counters, + struct xt_table_info *newinfo, + int *error); + +struct xt_match *xt_find_match(u8 af, const char *name, u8 revision); +struct xt_target *xt_find_target(u8 af, const char *name, u8 revision); +struct xt_match *xt_request_find_match(u8 af, const char *name, u8 revision); +struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision); +int xt_find_revision(u8 af, const char *name, u8 revision, int target, + int *err); + +struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, + const char *name); +void xt_table_unlock(struct xt_table *t); + +int xt_proto_init(struct net *net, u_int8_t af); +void xt_proto_fini(struct net *net, u_int8_t af); + +struct xt_table_info *xt_alloc_table_info(unsigned int size); +void xt_free_table_info(struct xt_table_info *info); /** * xt_recseq - recursive seqcount for netfilter use @@ -353,8 +351,8 @@ static inline unsigned long ifname_compare_aligned(const char *_a, return ret; } -extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); -extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); +struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); +void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); #ifdef CONFIG_COMPAT #include @@ -414,25 +412,25 @@ struct _compat_xt_align { #define COMPAT_XT_ALIGN(s) __ALIGN_KERNEL((s), __alignof__(struct _compat_xt_align)) -extern void xt_compat_lock(u_int8_t af); -extern void xt_compat_unlock(u_int8_t af); - -extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta); -extern void xt_compat_flush_offsets(u_int8_t af); -extern void xt_compat_init_offsets(u_int8_t af, unsigned int number); -extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset); - -extern int xt_compat_match_offset(const struct xt_match *match); -extern int xt_compat_match_from_user(struct xt_entry_match *m, - void **dstptr, unsigned int *size); -extern int xt_compat_match_to_user(const struct xt_entry_match *m, - void __user **dstptr, unsigned int *size); - -extern int xt_compat_target_offset(const struct xt_target *target); -extern void xt_compat_target_from_user(struct xt_entry_target *t, - void **dstptr, unsigned int *size); -extern int xt_compat_target_to_user(const struct xt_entry_target *t, - void __user **dstptr, unsigned int *size); +void xt_compat_lock(u_int8_t af); +void xt_compat_unlock(u_int8_t af); + +int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta); +void xt_compat_flush_offsets(u_int8_t af); +void xt_compat_init_offsets(u_int8_t af, unsigned int number); +int xt_compat_calc_jump(u_int8_t af, unsigned int offset); + +int xt_compat_match_offset(const struct xt_match *match); +int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, + unsigned int *size); +int xt_compat_match_to_user(const struct xt_entry_match *m, + void __user **dstptr, unsigned int *size); + +int xt_compat_target_offset(const struct xt_target *target); +void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, + unsigned int *size); +int xt_compat_target_to_user(const struct xt_entry_target *t, + void __user **dstptr, unsigned int *size); #endif /* CONFIG_COMPAT */ #endif /* _X_TABLES_H */ diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index dfb4d9e52bcb..8ab1c278b66d 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -25,7 +25,7 @@ enum nf_br_hook_priorities { #define BRNF_PPPoE 0x20 /* Only used in br_forward.c */ -extern int nf_bridge_copy_header(struct sk_buff *skb); +int nf_bridge_copy_header(struct sk_buff *skb); static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) { if (skb->nf_bridge && @@ -53,7 +53,7 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) return 0; } -extern int br_handle_frame_finish(struct sk_buff *skb); +int br_handle_frame_finish(struct sk_buff *skb); /* Only used in br_device.c */ static inline int br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) { diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index dfaf116b3e81..6e4591bb54d4 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -6,7 +6,7 @@ #include -extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type); -extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, - unsigned int dataoff, u_int8_t protocol); +int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type); +__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); #endif /*__LINUX_IP_NETFILTER_H*/ diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index 2d4df6ce043e..64dad1cc1a4b 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -11,12 +11,12 @@ #ifdef CONFIG_NETFILTER -extern int ip6_route_me_harder(struct sk_buff *skb); -extern __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, - unsigned int dataoff, u_int8_t protocol); +int ip6_route_me_harder(struct sk_buff *skb); +__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); -extern int ipv6_netfilter_init(void); -extern void ipv6_netfilter_fini(void); +int ipv6_netfilter_init(void); +void ipv6_netfilter_fini(void); /* * Hook functions for ipv6 to allow xt_* modules to be built-in even -- cgit From 58292cbe6669d74498a5f08db13e57cb3bcfb81d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:04 -0400 Subject: sysfs: make attr namespace interface less convoluted sysfs ns (namespace) implementation became more convoluted than necessary while trying to hide ns information from visible interface. The relatively recent attr ns support is a good example. * attr ns tag is determined by sysfs_ops->namespace() callback while dir tag is determined by kobj_type->namespace(). The placement is arbitrary. * Instead of performing operations with explicit ns tag, the namespace callback is routed through sysfs_attr_ns(), sysfs_ops->namespace(), class_attr_namespace(), class_attr->namespace(). It's not simpler in any sense. The only thing this convolution does is traversing the whole stack backwards. The namespace callbacks are unncessary because the operations involved are inherently synchronous. The information can be provided in in straight-forward top-down direction and reversing that direction is unnecessary and against basic design principles. This backward interface is unnecessarily convoluted and hinders properly separating out sysfs from driver model / kobject for proper layering. This patch updates attr ns support such that * sysfs_ops->namespace() and class_attr->namespace() are dropped. * sysfs_{create|remove}_file_ns(), which take explicit @ns param, are added and sysfs_{create|remove}_file() are now simple wrappers around the ns aware functions. * ns handling is dropped from sysfs_chmod_file(). Nobody uses it at this point. sysfs_chmod_file_ns() can be added later if necessary. * Explicit @ns is propagated through class_{create|remove}_file_ns() and netdev_class_{create|remove}_file_ns(). * driver/net/bonding which is currently the only user of attr namespace is updated to use netdev_class_{create|remove}_file_ns() with @bh->net as the ns tag instead of using the namespace callback. This patch should be an equivalent conversion without any functional difference. It makes the code easier to follow, reduces lines of code a bit and helps proper separation and layering. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 29 ++++-------- drivers/net/bonding/bond_sysfs.c | 14 ++---- fs/sysfs/file.c | 95 ++++++++++------------------------------ fs/sysfs/group.c | 7 +-- fs/sysfs/sysfs.h | 5 ++- include/linux/device.h | 24 +++++++--- include/linux/netdevice.h | 16 ++++++- include/linux/sysfs.h | 31 +++++++++---- net/core/net-sysfs.c | 14 +++--- 9 files changed, 106 insertions(+), 129 deletions(-) (limited to 'include') diff --git a/drivers/base/class.c b/drivers/base/class.c index 8b7818b80056..f96f70419a78 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -47,18 +47,6 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static const void *class_attr_namespace(struct kobject *kobj, - const struct attribute *attr) -{ - struct class_attribute *class_attr = to_class_attr(attr); - struct subsys_private *cp = to_subsys_private(kobj); - const void *ns = NULL; - - if (class_attr->namespace) - ns = class_attr->namespace(cp->class, class_attr); - return ns; -} - static void class_release(struct kobject *kobj) { struct subsys_private *cp = to_subsys_private(kobj); @@ -86,7 +74,6 @@ static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject static const struct sysfs_ops class_sysfs_ops = { .show = class_attr_show, .store = class_attr_store, - .namespace = class_attr_namespace, }; static struct kobj_type class_ktype = { @@ -99,21 +86,23 @@ static struct kobj_type class_ktype = { static struct kset *class_kset; -int class_create_file(struct class *cls, const struct class_attribute *attr) +int class_create_file_ns(struct class *cls, const struct class_attribute *attr, + const void *ns) { int error; if (cls) - error = sysfs_create_file(&cls->p->subsys.kobj, - &attr->attr); + error = sysfs_create_file_ns(&cls->p->subsys.kobj, + &attr->attr, ns); else error = -EINVAL; return error; } -void class_remove_file(struct class *cls, const struct class_attribute *attr) +void class_remove_file_ns(struct class *cls, const struct class_attribute *attr, + const void *ns) { if (cls) - sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr); + sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns); } static struct class *class_get(struct class *cls) @@ -600,8 +589,8 @@ int __init classes_init(void) return 0; } -EXPORT_SYMBOL_GPL(class_create_file); -EXPORT_SYMBOL_GPL(class_remove_file); +EXPORT_SYMBOL_GPL(class_create_file_ns); +EXPORT_SYMBOL_GPL(class_remove_file_ns); EXPORT_SYMBOL_GPL(class_unregister); EXPORT_SYMBOL_GPL(class_destroy); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index c29b836749b6..ec9b6460a38d 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -149,14 +149,6 @@ err_no_cmd: return -EPERM; } -static const void *bonding_namespace(struct class *cls, - const struct class_attribute *attr) -{ - const struct bond_net *bn = - container_of(attr, struct bond_net, class_attr_bonding_masters); - return bn->net; -} - /* class attribute for bond_masters file. This ends up in /sys/class/net */ static const struct class_attribute class_attr_bonding_masters = { .attr = { @@ -165,7 +157,6 @@ static const struct class_attribute class_attr_bonding_masters = { }, .show = bonding_show_bonds, .store = bonding_store_bonds, - .namespace = bonding_namespace, }; int bond_create_slave_symlinks(struct net_device *master, @@ -1787,7 +1778,8 @@ int bond_create_sysfs(struct bond_net *bn) bn->class_attr_bonding_masters = class_attr_bonding_masters; sysfs_attr_init(&bn->class_attr_bonding_masters.attr); - ret = netdev_class_create_file(&bn->class_attr_bonding_masters); + ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters, + bn->net); /* * Permit multiple loads of the module by ignoring failures to * create the bonding_masters sysfs file. Bonding devices @@ -1817,7 +1809,7 @@ int bond_create_sysfs(struct bond_net *bn) */ void bond_destroy_sysfs(struct bond_net *bn) { - netdev_class_remove_file(&bn->class_attr_bonding_masters); + netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net); } /* diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 15ef5eb13663..e784340f1599 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -485,58 +485,15 @@ const struct file_operations sysfs_file_operations = { .poll = sysfs_poll, }; -static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, - const void **pns) -{ - struct sysfs_dirent *dir_sd = kobj->sd; - const struct sysfs_ops *ops; - const void *ns = NULL; - int err; - - if (!dir_sd) { - WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n", - kobject_name(kobj)); - return -ENOENT; - } - - err = 0; - if (!sysfs_ns_type(dir_sd)) - goto out; - - err = -EINVAL; - if (!kobj->ktype) - goto out; - ops = kobj->ktype->sysfs_ops; - if (!ops) - goto out; - if (!ops->namespace) - goto out; - - err = 0; - ns = ops->namespace(kobj, attr); -out: - if (err) { - WARN(1, KERN_ERR - "missing sysfs namespace attribute operation for kobject: %s\n", - kobject_name(kobj)); - } - *pns = ns; - return err; -} - -int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, - const struct attribute *attr, int type, umode_t amode) +int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, + const struct attribute *attr, int type, + umode_t amode, const void *ns) { umode_t mode = (amode & S_IALLUGO) | S_IFREG; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; - const void *ns; int rc; - rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns); - if (rc) - return rc; - sd = sysfs_new_dirent(attr->name, mode, type); if (!sd) return -ENOMEM; @@ -559,23 +516,25 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type) { - return sysfs_add_file_mode(dir_sd, attr, type, attr->mode); + return sysfs_add_file_mode_ns(dir_sd, attr, type, attr->mode, NULL); } - /** - * sysfs_create_file - create an attribute file for an object. - * @kobj: object we're creating for. - * @attr: attribute descriptor. + * sysfs_create_file_ns - create an attribute file for an object with custom ns + * @kobj: object we're creating for + * @attr: attribute descriptor + * @ns: namespace the new file should belong to */ -int sysfs_create_file(struct kobject *kobj, const struct attribute *attr) +int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr, + const void *ns) { BUG_ON(!kobj || !kobj->sd || !attr); - return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); + return sysfs_add_file_mode_ns(kobj->sd, attr, SYSFS_KOBJ_ATTR, + attr->mode, ns); } -EXPORT_SYMBOL_GPL(sysfs_create_file); +EXPORT_SYMBOL_GPL(sysfs_create_file_ns); int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) { @@ -630,17 +589,12 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, { struct sysfs_dirent *sd; struct iattr newattrs; - const void *ns; int rc; - rc = sysfs_attr_ns(kobj, attr, &ns); - if (rc) - return rc; - mutex_lock(&sysfs_mutex); rc = -ENOENT; - sd = sysfs_find_dirent(kobj->sd, ns, attr->name); + sd = sysfs_find_dirent(kobj->sd, NULL, attr->name); if (!sd) goto out; @@ -655,22 +609,21 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, EXPORT_SYMBOL_GPL(sysfs_chmod_file); /** - * sysfs_remove_file - remove an object attribute. - * @kobj: object we're acting for. - * @attr: attribute descriptor. + * sysfs_remove_file_ns - remove an object attribute with a custom ns tag + * @kobj: object we're acting for + * @attr: attribute descriptor + * @ns: namespace tag of the file to remove * - * Hash the attribute name and kill the victim. + * Hash the attribute name and namespace tag and kill the victim. */ -void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) +void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, + const void *ns) { - const void *ns; - - if (sysfs_attr_ns(kobj, attr, &ns)) - return; + struct sysfs_dirent *dir_sd = kobj->sd; - sysfs_hash_and_remove(kobj->sd, ns, attr->name); + sysfs_hash_and_remove(dir_sd, ns, attr->name); } -EXPORT_SYMBOL_GPL(sysfs_remove_file); +EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) { diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 5f92cd2f61c1..25c78f23dae8 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -56,9 +56,10 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, if (!mode) continue; } - error = sysfs_add_file_mode(dir_sd, *attr, - SYSFS_KOBJ_ATTR, - (*attr)->mode | mode); + error = sysfs_add_file_mode_ns(dir_sd, *attr, + SYSFS_KOBJ_ATTR, + (*attr)->mode | mode, + NULL); if (unlikely(error)) break; } diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index b6deca3e301d..a96da2559db2 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -230,8 +230,9 @@ extern const struct file_operations sysfs_file_operations; int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type); -int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, - const struct attribute *attr, int type, umode_t amode); +int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, + const struct attribute *attr, int type, + umode_t amode, const void *ns); /* * bin.c */ diff --git a/include/linux/device.h b/include/linux/device.h index 2a9d6ed59579..ce690ea34547 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -427,8 +427,6 @@ struct class_attribute { char *buf); ssize_t (*store)(struct class *class, struct class_attribute *attr, const char *buf, size_t count); - const void *(*namespace)(struct class *class, - const struct class_attribute *attr); }; #define CLASS_ATTR(_name, _mode, _show, _store) \ @@ -438,10 +436,24 @@ struct class_attribute { #define CLASS_ATTR_RO(_name) \ struct class_attribute class_attr_##_name = __ATTR_RO(_name) -extern int __must_check class_create_file(struct class *class, - const struct class_attribute *attr); -extern void class_remove_file(struct class *class, - const struct class_attribute *attr); +extern int __must_check class_create_file_ns(struct class *class, + const struct class_attribute *attr, + const void *ns); +extern void class_remove_file_ns(struct class *class, + const struct class_attribute *attr, + const void *ns); + +static inline int __must_check class_create_file(struct class *class, + const struct class_attribute *attr) +{ + return class_create_file_ns(class, attr, NULL); +} + +static inline void class_remove_file(struct class *class, + const struct class_attribute *attr) +{ + return class_remove_file_ns(class, attr, NULL); +} /* Simple class attribute that is just a static string */ struct class_attribute_string { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3de49aca4519..42421ed49a47 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2873,8 +2873,20 @@ extern int __init dev_proc_init(void); #define dev_proc_init() 0 #endif -extern int netdev_class_create_file(struct class_attribute *class_attr); -extern void netdev_class_remove_file(struct class_attribute *class_attr); +extern int netdev_class_create_file_ns(struct class_attribute *class_attr, + const void *ns); +extern void netdev_class_remove_file_ns(struct class_attribute *class_attr, + const void *ns); + +static inline int netdev_class_create_file(struct class_attribute *class_attr) +{ + return netdev_class_create_file_ns(class_attr, NULL); +} + +static inline void netdev_class_remove_file(struct class_attribute *class_attr) +{ + netdev_class_remove_file_ns(class_attr, NULL); +} extern struct kobj_ns_type_operations net_ns_type_operations; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 11baec7c9b26..82f7fac78e77 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -173,7 +173,6 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size) struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); - const void *(*namespace)(struct kobject *, const struct attribute *); }; struct sysfs_dirent; @@ -189,13 +188,15 @@ int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); int __must_check sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj); -int __must_check sysfs_create_file(struct kobject *kobj, - const struct attribute *attr); +int __must_check sysfs_create_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns); int __must_check sysfs_create_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode); -void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); +void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, + const void *ns); void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, @@ -277,8 +278,9 @@ static inline int sysfs_move_dir(struct kobject *kobj, return 0; } -static inline int sysfs_create_file(struct kobject *kobj, - const struct attribute *attr) +static inline int sysfs_create_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns) { return 0; } @@ -295,8 +297,9 @@ static inline int sysfs_chmod_file(struct kobject *kobj, return 0; } -static inline void sysfs_remove_file(struct kobject *kobj, - const struct attribute *attr) +static inline void sysfs_remove_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns) { } @@ -435,4 +438,16 @@ static inline int __must_check sysfs_init(void) #endif /* CONFIG_SYSFS */ +static inline int __must_check sysfs_create_file(struct kobject *kobj, + const struct attribute *attr) +{ + return sysfs_create_file_ns(kobj, attr, NULL); +} + +static inline void sysfs_remove_file(struct kobject *kobj, + const struct attribute *attr) +{ + return sysfs_remove_file_ns(kobj, attr, NULL); +} + #endif /* _SYSFS_H_ */ diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index d954b56b4e47..325dee863e46 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1344,17 +1344,19 @@ int netdev_register_kobject(struct net_device *net) return error; } -int netdev_class_create_file(struct class_attribute *class_attr) +int netdev_class_create_file_ns(struct class_attribute *class_attr, + const void *ns) { - return class_create_file(&net_class, class_attr); + return class_create_file_ns(&net_class, class_attr, ns); } -EXPORT_SYMBOL(netdev_class_create_file); +EXPORT_SYMBOL(netdev_class_create_file_ns); -void netdev_class_remove_file(struct class_attribute *class_attr) +void netdev_class_remove_file_ns(struct class_attribute *class_attr, + const void *ns) { - class_remove_file(&net_class, class_attr); + class_remove_file_ns(&net_class, class_attr, ns); } -EXPORT_SYMBOL(netdev_class_remove_file); +EXPORT_SYMBOL(netdev_class_remove_file_ns); int netdev_kobject_init(void) { -- cgit From 7965bd4d71ef7cf1db00afb9e406ddfc13443c13 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 26 Sep 2013 14:48:15 -0700 Subject: net.h/skbuff.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches --- include/linux/net.h | 82 ++++++++-------- include/linux/skbuff.h | 250 ++++++++++++++++++++++--------------------------- 2 files changed, 148 insertions(+), 184 deletions(-) (limited to 'include') diff --git a/include/linux/net.h b/include/linux/net.h index 4f27575ce1d6..ca9ec8540905 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -195,27 +195,23 @@ enum { SOCK_WAKE_URG, }; -extern int sock_wake_async(struct socket *sk, int how, int band); -extern int sock_register(const struct net_proto_family *fam); -extern void sock_unregister(int family); -extern int __sock_create(struct net *net, int family, int type, int proto, - struct socket **res, int kern); -extern int sock_create(int family, int type, int proto, - struct socket **res); -extern int sock_create_kern(int family, int type, int proto, - struct socket **res); -extern int sock_create_lite(int family, int type, int proto, - struct socket **res); -extern void sock_release(struct socket *sock); -extern int sock_sendmsg(struct socket *sock, struct msghdr *msg, - size_t len); -extern int sock_recvmsg(struct socket *sock, struct msghdr *msg, - size_t size, int flags); -extern struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname); -extern struct socket *sockfd_lookup(int fd, int *err); -extern struct socket *sock_from_file(struct file *file, int *err); +int sock_wake_async(struct socket *sk, int how, int band); +int sock_register(const struct net_proto_family *fam); +void sock_unregister(int family); +int __sock_create(struct net *net, int family, int type, int proto, + struct socket **res, int kern); +int sock_create(int family, int type, int proto, struct socket **res); +int sock_create_kern(int family, int type, int proto, struct socket **res); +int sock_create_lite(int family, int type, int proto, struct socket **res); +void sock_release(struct socket *sock); +int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len); +int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, + int flags); +struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname); +struct socket *sockfd_lookup(int fd, int *err); +struct socket *sock_from_file(struct file *file, int *err); #define sockfd_put(sock) fput(sock->file) -extern int net_ratelimit(void); +int net_ratelimit(void); #define net_ratelimited_function(function, ...) \ do { \ @@ -243,32 +239,28 @@ do { \ #define net_random() prandom_u32() #define net_srandom(seed) prandom_seed((__force u32)(seed)) -extern int kernel_sendmsg(struct socket *sock, struct msghdr *msg, - struct kvec *vec, size_t num, size_t len); -extern int kernel_recvmsg(struct socket *sock, struct msghdr *msg, - struct kvec *vec, size_t num, - size_t len, int flags); +int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, + size_t num, size_t len); +int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, + size_t num, size_t len, int flags); -extern int kernel_bind(struct socket *sock, struct sockaddr *addr, - int addrlen); -extern int kernel_listen(struct socket *sock, int backlog); -extern int kernel_accept(struct socket *sock, struct socket **newsock, - int flags); -extern int kernel_connect(struct socket *sock, struct sockaddr *addr, - int addrlen, int flags); -extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr, - int *addrlen); -extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr, - int *addrlen); -extern int kernel_getsockopt(struct socket *sock, int level, int optname, - char *optval, int *optlen); -extern int kernel_setsockopt(struct socket *sock, int level, int optname, - char *optval, unsigned int optlen); -extern int kernel_sendpage(struct socket *sock, struct page *page, int offset, - size_t size, int flags); -extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); -extern int kernel_sock_shutdown(struct socket *sock, - enum sock_shutdown_cmd how); +int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen); +int kernel_listen(struct socket *sock, int backlog); +int kernel_accept(struct socket *sock, struct socket **newsock, int flags); +int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, + int flags); +int kernel_getsockname(struct socket *sock, struct sockaddr *addr, + int *addrlen); +int kernel_getpeername(struct socket *sock, struct sockaddr *addr, + int *addrlen); +int kernel_getsockopt(struct socket *sock, int level, int optname, char *optval, + int *optlen); +int kernel_setsockopt(struct socket *sock, int level, int optname, char *optval, + unsigned int optlen); +int kernel_sendpage(struct socket *sock, struct page *page, int offset, + size_t size, int flags); +int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); +int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how); #define MODULE_ALIAS_NETPROTO(proto) \ MODULE_ALIAS("net-pf-" __stringify(proto)) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2ddb48d9312c..6d56840e561e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -585,8 +585,8 @@ static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) skb->_skb_refdst = (unsigned long)dst; } -extern void __skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst, - bool force); +void __skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst, + bool force); /** * skb_dst_set_noref - sets skb dst, hopefully, without taking reference @@ -634,20 +634,20 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb) return (struct rtable *)skb_dst(skb); } -extern void kfree_skb(struct sk_buff *skb); -extern void kfree_skb_list(struct sk_buff *segs); -extern void skb_tx_error(struct sk_buff *skb); -extern void consume_skb(struct sk_buff *skb); -extern void __kfree_skb(struct sk_buff *skb); +void kfree_skb(struct sk_buff *skb); +void kfree_skb_list(struct sk_buff *segs); +void skb_tx_error(struct sk_buff *skb); +void consume_skb(struct sk_buff *skb); +void __kfree_skb(struct sk_buff *skb); extern struct kmem_cache *skbuff_head_cache; -extern void kfree_skb_partial(struct sk_buff *skb, bool head_stolen); -extern bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, - bool *fragstolen, int *delta_truesize); +void kfree_skb_partial(struct sk_buff *skb, bool head_stolen); +bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, + bool *fragstolen, int *delta_truesize); -extern struct sk_buff *__alloc_skb(unsigned int size, - gfp_t priority, int flags, int node); -extern struct sk_buff *build_skb(void *data, unsigned int frag_size); +struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags, + int node); +struct sk_buff *build_skb(void *data, unsigned int frag_size); static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority) { @@ -660,41 +660,33 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); } -extern struct sk_buff *__alloc_skb_head(gfp_t priority, int node); +struct sk_buff *__alloc_skb_head(gfp_t priority, int node); static inline struct sk_buff *alloc_skb_head(gfp_t priority) { return __alloc_skb_head(priority, -1); } -extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); -extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); -extern struct sk_buff *skb_clone(struct sk_buff *skb, - gfp_t priority); -extern struct sk_buff *skb_copy(const struct sk_buff *skb, - gfp_t priority); -extern struct sk_buff *__pskb_copy(struct sk_buff *skb, - int headroom, gfp_t gfp_mask); - -extern int pskb_expand_head(struct sk_buff *skb, - int nhead, int ntail, - gfp_t gfp_mask); -extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, - unsigned int headroom); -extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb, - int newheadroom, int newtailroom, - gfp_t priority); -extern int skb_to_sgvec(struct sk_buff *skb, - struct scatterlist *sg, int offset, - int len); -extern int skb_cow_data(struct sk_buff *skb, int tailbits, - struct sk_buff **trailer); -extern int skb_pad(struct sk_buff *skb, int pad); +struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); +int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); +struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); +struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority); +struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask); + +int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); +struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, + unsigned int headroom); +struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, + int newtailroom, gfp_t priority); +int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, + int len); +int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); +int skb_pad(struct sk_buff *skb, int pad); #define dev_kfree_skb(a) consume_skb(a) -extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, - int getfrag(void *from, char *to, int offset, - int len,int odd, struct sk_buff *skb), - void *from, int length); +int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, + int getfrag(void *from, char *to, int offset, + int len, int odd, struct sk_buff *skb), + void *from, int length); struct skb_seq_state { __u32 lower_offset; @@ -706,18 +698,17 @@ struct skb_seq_state { __u8 *frag_data; }; -extern void skb_prepare_seq_read(struct sk_buff *skb, - unsigned int from, unsigned int to, - struct skb_seq_state *st); -extern unsigned int skb_seq_read(unsigned int consumed, const u8 **data, - struct skb_seq_state *st); -extern void skb_abort_seq_read(struct skb_seq_state *st); +void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, + unsigned int to, struct skb_seq_state *st); +unsigned int skb_seq_read(unsigned int consumed, const u8 **data, + struct skb_seq_state *st); +void skb_abort_seq_read(struct skb_seq_state *st); -extern unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, - unsigned int to, struct ts_config *config, - struct ts_state *state); +unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, + unsigned int to, struct ts_config *config, + struct ts_state *state); -extern void __skb_get_rxhash(struct sk_buff *skb); +void __skb_get_rxhash(struct sk_buff *skb); static inline __u32 skb_get_rxhash(struct sk_buff *skb) { if (!skb->l4_rxhash) @@ -1095,7 +1086,8 @@ static inline void skb_queue_head_init_class(struct sk_buff_head *list, * The "__skb_xxxx()" functions are the non-atomic ones that * can only be called with interrupts disabled. */ -extern void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list); +void skb_insert(struct sk_buff *old, struct sk_buff *newsk, + struct sk_buff_head *list); static inline void __skb_insert(struct sk_buff *newsk, struct sk_buff *prev, struct sk_buff *next, struct sk_buff_head *list) @@ -1201,8 +1193,8 @@ static inline void __skb_queue_after(struct sk_buff_head *list, __skb_insert(newsk, prev, prev->next, list); } -extern void skb_append(struct sk_buff *old, struct sk_buff *newsk, - struct sk_buff_head *list); +void skb_append(struct sk_buff *old, struct sk_buff *newsk, + struct sk_buff_head *list); static inline void __skb_queue_before(struct sk_buff_head *list, struct sk_buff *next, @@ -1221,7 +1213,7 @@ static inline void __skb_queue_before(struct sk_buff_head *list, * * A buffer cannot be placed on two lists at the same time. */ -extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); +void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); static inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) { @@ -1238,7 +1230,7 @@ static inline void __skb_queue_head(struct sk_buff_head *list, * * A buffer cannot be placed on two lists at the same time. */ -extern void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk); +void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk); static inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) { @@ -1249,7 +1241,7 @@ static inline void __skb_queue_tail(struct sk_buff_head *list, * remove sk_buff from list. _Must_ be called atomically, and with * the list known.. */ -extern void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); +void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) { struct sk_buff *next, *prev; @@ -1270,7 +1262,7 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) * so must be used with appropriate locks held only. The head item is * returned or %NULL if the list is empty. */ -extern struct sk_buff *skb_dequeue(struct sk_buff_head *list); +struct sk_buff *skb_dequeue(struct sk_buff_head *list); static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek(list); @@ -1287,7 +1279,7 @@ static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) * so must be used with appropriate locks held only. The tail item is * returned or %NULL if the list is empty. */ -extern struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list); +struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list); static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek_tail(list); @@ -1373,8 +1365,8 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i, skb_shinfo(skb)->nr_frags = i + 1; } -extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, - int off, int size, unsigned int truesize); +void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, + int size, unsigned int truesize); #define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags) #define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb)) @@ -1418,7 +1410,7 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) /* * Add data to an sk_buff */ -extern unsigned char *skb_put(struct sk_buff *skb, unsigned int len); +unsigned char *skb_put(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) { unsigned char *tmp = skb_tail_pointer(skb); @@ -1428,7 +1420,7 @@ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) return tmp; } -extern unsigned char *skb_push(struct sk_buff *skb, unsigned int len); +unsigned char *skb_push(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) { skb->data -= len; @@ -1436,7 +1428,7 @@ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) return skb->data; } -extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); +unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; @@ -1449,7 +1441,7 @@ static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int l return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); } -extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta); +unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta); static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) { @@ -1753,7 +1745,7 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) #define NET_SKB_PAD max(32, L1_CACHE_BYTES) #endif -extern int ___pskb_trim(struct sk_buff *skb, unsigned int len); +int ___pskb_trim(struct sk_buff *skb, unsigned int len); static inline void __skb_trim(struct sk_buff *skb, unsigned int len) { @@ -1765,7 +1757,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len) skb_set_tail_pointer(skb, len); } -extern void skb_trim(struct sk_buff *skb, unsigned int len); +void skb_trim(struct sk_buff *skb, unsigned int len); static inline int __pskb_trim(struct sk_buff *skb, unsigned int len) { @@ -1838,7 +1830,7 @@ static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask) * the list and one reference dropped. This function does not take the * list lock and the caller must hold the relevant locks to use it. */ -extern void skb_queue_purge(struct sk_buff_head *list); +void skb_queue_purge(struct sk_buff_head *list); static inline void __skb_queue_purge(struct sk_buff_head *list) { struct sk_buff *skb; @@ -1850,11 +1842,10 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) #define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER) #define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE -extern void *netdev_alloc_frag(unsigned int fragsz); +void *netdev_alloc_frag(unsigned int fragsz); -extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev, - unsigned int length, - gfp_t gfp_mask); +struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length, + gfp_t gfp_mask); /** * netdev_alloc_skb - allocate an skbuff for rx on a specific device @@ -2342,60 +2333,42 @@ static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag) #define skb_walk_frags(skb, iter) \ for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next) -extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, - int *peeked, int *off, int *err); -extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, - int noblock, int *err); -extern unsigned int datagram_poll(struct file *file, struct socket *sock, - struct poll_table_struct *wait); -extern int skb_copy_datagram_iovec(const struct sk_buff *from, - int offset, struct iovec *to, - int size); -extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, - int hlen, - struct iovec *iov); -extern int skb_copy_datagram_from_iovec(struct sk_buff *skb, - int offset, - const struct iovec *from, - int from_offset, - int len); -extern int zerocopy_sg_from_iovec(struct sk_buff *skb, - const struct iovec *frm, - int offset, - size_t count); -extern int skb_copy_datagram_const_iovec(const struct sk_buff *from, - int offset, - const struct iovec *to, - int to_offset, - int size); -extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); -extern void skb_free_datagram_locked(struct sock *sk, - struct sk_buff *skb); -extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, - unsigned int flags); -extern __wsum skb_checksum(const struct sk_buff *skb, int offset, - int len, __wsum csum); -extern int skb_copy_bits(const struct sk_buff *skb, int offset, - void *to, int len); -extern int skb_store_bits(struct sk_buff *skb, int offset, - const void *from, int len); -extern __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, - int offset, u8 *to, int len, - __wsum csum); -extern int skb_splice_bits(struct sk_buff *skb, - unsigned int offset, - struct pipe_inode_info *pipe, - unsigned int len, - unsigned int flags); -extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); -extern void skb_split(struct sk_buff *skb, - struct sk_buff *skb1, const u32 len); -extern int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, - int shiftlen); -extern void skb_scrub_packet(struct sk_buff *skb, bool xnet); - -extern struct sk_buff *skb_segment(struct sk_buff *skb, - netdev_features_t features); +struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, + int *peeked, int *off, int *err); +struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, + int *err); +unsigned int datagram_poll(struct file *file, struct socket *sock, + struct poll_table_struct *wait); +int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, + struct iovec *to, int size); +int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, + struct iovec *iov); +int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, + const struct iovec *from, int from_offset, + int len); +int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *frm, + int offset, size_t count); +int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset, + const struct iovec *to, int to_offset, + int size); +void skb_free_datagram(struct sock *sk, struct sk_buff *skb); +void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb); +int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); +__wsum skb_checksum(const struct sk_buff *skb, int offset, int len, + __wsum csum); +int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len); +int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len); +__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, + int len, __wsum csum); +int skb_splice_bits(struct sk_buff *skb, unsigned int offset, + struct pipe_inode_info *pipe, unsigned int len, + unsigned int flags); +void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); +void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); +int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); +void skb_scrub_packet(struct sk_buff *skb, bool xnet); + +struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) @@ -2440,7 +2413,7 @@ static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb, memcpy(skb->data + offset, from, len); } -extern void skb_init(void); +void skb_init(void); static inline ktime_t skb_get_ktime(const struct sk_buff *skb) { @@ -2483,12 +2456,12 @@ static inline ktime_t net_invalid_timestamp(void) return ktime_set(0, 0); } -extern void skb_timestamping_init(void); +void skb_timestamping_init(void); #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING -extern void skb_clone_tx_timestamp(struct sk_buff *skb); -extern bool skb_defer_rx_timestamp(struct sk_buff *skb); +void skb_clone_tx_timestamp(struct sk_buff *skb); +bool skb_defer_rx_timestamp(struct sk_buff *skb); #else /* CONFIG_NETWORK_PHY_TIMESTAMPING */ @@ -2529,8 +2502,8 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, * generates a software time stamp (otherwise), then queues the clone * to the error queue of the socket. Errors are silently ignored. */ -extern void skb_tstamp_tx(struct sk_buff *orig_skb, - struct skb_shared_hwtstamps *hwtstamps); +void skb_tstamp_tx(struct sk_buff *orig_skb, + struct skb_shared_hwtstamps *hwtstamps); static inline void sw_tx_timestamp(struct sk_buff *skb) { @@ -2562,8 +2535,8 @@ static inline void skb_tx_timestamp(struct sk_buff *skb) */ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked); -extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); -extern __sum16 __skb_checksum_complete(struct sk_buff *skb); +__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); +__sum16 __skb_checksum_complete(struct sk_buff *skb); static inline int skb_csum_unnecessary(const struct sk_buff *skb) { @@ -2593,7 +2566,7 @@ static inline __sum16 skb_checksum_complete(struct sk_buff *skb) } #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) -extern void nf_conntrack_destroy(struct nf_conntrack *nfct); +void nf_conntrack_destroy(struct nf_conntrack *nfct); static inline void nf_conntrack_put(struct nf_conntrack *nfct) { if (nfct && atomic_dec_and_test(&nfct->use)) @@ -2732,9 +2705,8 @@ static inline bool skb_rx_queue_recorded(const struct sk_buff *skb) return skb->queue_mapping != 0; } -extern u16 __skb_tx_hash(const struct net_device *dev, - const struct sk_buff *skb, - unsigned int num_tx_queues); +u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, + unsigned int num_tx_queues); #ifdef CONFIG_XFRM static inline struct sec_path *skb_sec_path(struct sk_buff *skb) @@ -2788,7 +2760,7 @@ static inline bool skb_is_gso_v6(const struct sk_buff *skb) return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; } -extern void __skb_warn_lro_forwarding(const struct sk_buff *skb); +void __skb_warn_lro_forwarding(const struct sk_buff *skb); static inline bool skb_warn_if_lro(const struct sk_buff *skb) { -- cgit From f629d208d27a22f495b7734eede585b5d207e912 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 26 Sep 2013 14:48:15 -0700 Subject: [networking]device.h: Remove extern from function prototypes There are a mix of function prototypes with and without extern in the kernel sources. Standardize on not using extern for function prototypes. Function prototypes don't need to be written with extern. extern is assumed by the compiler. Its use is as unnecessary as using auto to declare automatic/local variables in a block. Signed-off-by: Joe Perches --- include/linux/etherdevice.h | 35 ++-- include/linux/fcdevice.h | 2 +- include/linux/fddidevice.h | 7 +- include/linux/hippidevice.h | 10 +- include/linux/inetdevice.h | 28 +-- include/linux/netdevice.h | 432 +++++++++++++++++++++----------------------- 6 files changed, 248 insertions(+), 266 deletions(-) (limited to 'include') diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index d8b512496e50..fc4a9aa7dd82 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -28,27 +28,24 @@ #include #ifdef __KERNEL__ -extern __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); +__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); extern const struct header_ops eth_header_ops; -extern int eth_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, - const void *daddr, const void *saddr, unsigned len); -extern int eth_rebuild_header(struct sk_buff *skb); -extern int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); -extern int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); -extern void eth_header_cache_update(struct hh_cache *hh, - const struct net_device *dev, - const unsigned char *haddr); -extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p); -extern void eth_commit_mac_addr_change(struct net_device *dev, void *p); -extern int eth_mac_addr(struct net_device *dev, void *p); -extern int eth_change_mtu(struct net_device *dev, int new_mtu); -extern int eth_validate_addr(struct net_device *dev); - - - -extern struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, +int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, + const void *daddr, const void *saddr, unsigned len); +int eth_rebuild_header(struct sk_buff *skb); +int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); +int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, + __be16 type); +void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, + const unsigned char *haddr); +int eth_prepare_mac_addr_change(struct net_device *dev, void *p); +void eth_commit_mac_addr_change(struct net_device *dev, void *p); +int eth_mac_addr(struct net_device *dev, void *p); +int eth_change_mtu(struct net_device *dev, int new_mtu); +int eth_validate_addr(struct net_device *dev); + +struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs); #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1) #define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count) diff --git a/include/linux/fcdevice.h b/include/linux/fcdevice.h index e460ef831984..5009fa16b5d8 100644 --- a/include/linux/fcdevice.h +++ b/include/linux/fcdevice.h @@ -27,7 +27,7 @@ #include #ifdef __KERNEL__ -extern struct net_device *alloc_fcdev(int sizeof_priv); +struct net_device *alloc_fcdev(int sizeof_priv); #endif #endif /* _LINUX_FCDEVICE_H */ diff --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h index 155bafd9e886..9a79f0106da1 100644 --- a/include/linux/fddidevice.h +++ b/include/linux/fddidevice.h @@ -25,10 +25,9 @@ #include #ifdef __KERNEL__ -extern __be16 fddi_type_trans(struct sk_buff *skb, - struct net_device *dev); -extern int fddi_change_mtu(struct net_device *dev, int new_mtu); -extern struct net_device *alloc_fddidev(int sizeof_priv); +__be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev); +int fddi_change_mtu(struct net_device *dev, int new_mtu); +struct net_device *alloc_fddidev(int sizeof_priv); #endif #endif /* _LINUX_FDDIDEVICE_H */ diff --git a/include/linux/hippidevice.h b/include/linux/hippidevice.h index f148e4908410..8ec23fb0b412 100644 --- a/include/linux/hippidevice.h +++ b/include/linux/hippidevice.h @@ -31,11 +31,11 @@ struct hippi_cb { __u32 ifield; }; -extern __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev); -extern int hippi_change_mtu(struct net_device *dev, int new_mtu); -extern int hippi_mac_addr(struct net_device *dev, void *p); -extern int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p); -extern struct net_device *alloc_hippi_dev(int sizeof_priv); +__be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev); +int hippi_change_mtu(struct net_device *dev, int new_mtu); +int hippi_mac_addr(struct net_device *dev, void *p); +int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p); +struct net_device *alloc_hippi_dev(int sizeof_priv); #endif #endif /* _LINUX_HIPPIDEVICE_H */ diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 79640e015a86..0d678aefe69d 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -147,25 +147,27 @@ struct in_ifaddr { unsigned long ifa_tstamp; /* updated timestamp */ }; -extern int register_inetaddr_notifier(struct notifier_block *nb); -extern int unregister_inetaddr_notifier(struct notifier_block *nb); +int register_inetaddr_notifier(struct notifier_block *nb); +int unregister_inetaddr_notifier(struct notifier_block *nb); -extern void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, - struct ipv4_devconf *devconf); +void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, + struct ipv4_devconf *devconf); -extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref); +struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref); static inline struct net_device *ip_dev_find(struct net *net, __be32 addr) { return __ip_dev_find(net, addr, true); } -extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); -extern int devinet_ioctl(struct net *net, unsigned int cmd, void __user *); -extern void devinet_init(void); -extern struct in_device *inetdev_by_index(struct net *, int); -extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); -extern __be32 inet_confirm_addr(struct in_device *in_dev, __be32 dst, __be32 local, int scope); -extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask); +int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); +int devinet_ioctl(struct net *net, unsigned int cmd, void __user *); +void devinet_init(void); +struct in_device *inetdev_by_index(struct net *, int); +__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); +__be32 inet_confirm_addr(struct in_device *in_dev, __be32 dst, __be32 local, + int scope); +struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, + __be32 mask); static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa) { @@ -218,7 +220,7 @@ static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev) return rtnl_dereference(dev->ip_ptr); } -extern void in_dev_finish_destroy(struct in_device *idev); +void in_dev_finish_destroy(struct in_device *idev); static inline void in_dev_put(struct in_device *idev) { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b4cfb63f264e..5f01af3927ca 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -60,8 +60,8 @@ struct wireless_dev; #define SET_ETHTOOL_OPS(netdev,ops) \ ( (netdev)->ethtool_ops = (ops) ) -extern void netdev_set_default_ethtool_ops(struct net_device *dev, - const struct ethtool_ops *ops); +void netdev_set_default_ethtool_ops(struct net_device *dev, + const struct ethtool_ops *ops); /* hardware address assignment types */ #define NET_ADDR_PERM 0 /* address is permanent (default) */ @@ -298,7 +298,7 @@ struct netdev_boot_setup { }; #define NETDEV_BOOT_SETUP_MAX 8 -extern int __init netdev_boot_setup(char *str); +int __init netdev_boot_setup(char *str); /* * Structure for NAPI scheduling similar to tasklet but with weighting @@ -394,7 +394,7 @@ enum rx_handler_result { typedef enum rx_handler_result rx_handler_result_t; typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb); -extern void __napi_schedule(struct napi_struct *n); +void __napi_schedule(struct napi_struct *n); static inline bool napi_disable_pending(struct napi_struct *n) { @@ -445,8 +445,8 @@ static inline bool napi_reschedule(struct napi_struct *napi) * * Mark NAPI processing as complete. */ -extern void __napi_complete(struct napi_struct *n); -extern void napi_complete(struct napi_struct *n); +void __napi_complete(struct napi_struct *n); +void napi_complete(struct napi_struct *n); /** * napi_by_id - lookup a NAPI by napi_id @@ -455,7 +455,7 @@ extern void napi_complete(struct napi_struct *n); * lookup @napi_id in napi_hash table * must be called under rcu_read_lock() */ -extern struct napi_struct *napi_by_id(unsigned int napi_id); +struct napi_struct *napi_by_id(unsigned int napi_id); /** * napi_hash_add - add a NAPI to global hashtable @@ -463,7 +463,7 @@ extern struct napi_struct *napi_by_id(unsigned int napi_id); * * generate a new napi_id and store a @napi under it in napi_hash */ -extern void napi_hash_add(struct napi_struct *napi); +void napi_hash_add(struct napi_struct *napi); /** * napi_hash_del - remove a NAPI from global table @@ -472,7 +472,7 @@ extern void napi_hash_add(struct napi_struct *napi); * Warning: caller must observe rcu grace period * before freeing memory containing @napi */ -extern void napi_hash_del(struct napi_struct *napi); +void napi_hash_del(struct napi_struct *napi); /** * napi_disable - prevent NAPI from scheduling @@ -664,8 +664,8 @@ static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table, extern struct rps_sock_flow_table __rcu *rps_sock_flow_table; #ifdef CONFIG_RFS_ACCEL -extern bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, - u32 flow_id, u16 filter_id); +bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, u32 flow_id, + u16 filter_id); #endif /* This structure contains an instance of an RX queue. */ @@ -1497,9 +1497,9 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, f(dev, &dev->_tx[i], arg); } -extern struct netdev_queue *netdev_pick_tx(struct net_device *dev, - struct sk_buff *skb); -extern u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); +struct netdev_queue *netdev_pick_tx(struct net_device *dev, + struct sk_buff *skb); +u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); /* * Net namespace inlines @@ -1683,8 +1683,8 @@ struct packet_offload { #define NETDEV_CHANGEUPPER 0x0015 #define NETDEV_RESEND_IGMP 0x0016 -extern int register_netdevice_notifier(struct notifier_block *nb); -extern int unregister_netdevice_notifier(struct notifier_block *nb); +int register_netdevice_notifier(struct notifier_block *nb); +int unregister_netdevice_notifier(struct notifier_block *nb); struct netdev_notifier_info { struct net_device *dev; @@ -1707,9 +1707,9 @@ netdev_notifier_info_to_dev(const struct netdev_notifier_info *info) return info->dev; } -extern int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev, - struct netdev_notifier_info *info); -extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); +int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev, + struct netdev_notifier_info *info); +int call_netdevice_notifiers(unsigned long val, struct net_device *dev); extern rwlock_t dev_base_lock; /* Device list lock */ @@ -1764,54 +1764,52 @@ static inline struct net_device *first_net_device_rcu(struct net *net) return lh == &net->dev_base_head ? NULL : net_device_entry(lh); } -extern int netdev_boot_setup_check(struct net_device *dev); -extern unsigned long netdev_boot_base(const char *prefix, int unit); -extern struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, - const char *hwaddr); -extern struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type); -extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type); -extern void dev_add_pack(struct packet_type *pt); -extern void dev_remove_pack(struct packet_type *pt); -extern void __dev_remove_pack(struct packet_type *pt); -extern void dev_add_offload(struct packet_offload *po); -extern void dev_remove_offload(struct packet_offload *po); -extern void __dev_remove_offload(struct packet_offload *po); - -extern struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags, - unsigned short mask); -extern struct net_device *dev_get_by_name(struct net *net, const char *name); -extern struct net_device *dev_get_by_name_rcu(struct net *net, const char *name); -extern struct net_device *__dev_get_by_name(struct net *net, const char *name); -extern int dev_alloc_name(struct net_device *dev, const char *name); -extern int dev_open(struct net_device *dev); -extern int dev_close(struct net_device *dev); -extern void dev_disable_lro(struct net_device *dev); -extern int dev_loopback_xmit(struct sk_buff *newskb); -extern int dev_queue_xmit(struct sk_buff *skb); -extern int register_netdevice(struct net_device *dev); -extern void unregister_netdevice_queue(struct net_device *dev, - struct list_head *head); -extern void unregister_netdevice_many(struct list_head *head); +int netdev_boot_setup_check(struct net_device *dev); +unsigned long netdev_boot_base(const char *prefix, int unit); +struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, + const char *hwaddr); +struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type); +struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type); +void dev_add_pack(struct packet_type *pt); +void dev_remove_pack(struct packet_type *pt); +void __dev_remove_pack(struct packet_type *pt); +void dev_add_offload(struct packet_offload *po); +void dev_remove_offload(struct packet_offload *po); +void __dev_remove_offload(struct packet_offload *po); + +struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags, + unsigned short mask); +struct net_device *dev_get_by_name(struct net *net, const char *name); +struct net_device *dev_get_by_name_rcu(struct net *net, const char *name); +struct net_device *__dev_get_by_name(struct net *net, const char *name); +int dev_alloc_name(struct net_device *dev, const char *name); +int dev_open(struct net_device *dev); +int dev_close(struct net_device *dev); +void dev_disable_lro(struct net_device *dev); +int dev_loopback_xmit(struct sk_buff *newskb); +int dev_queue_xmit(struct sk_buff *skb); +int register_netdevice(struct net_device *dev); +void unregister_netdevice_queue(struct net_device *dev, struct list_head *head); +void unregister_netdevice_many(struct list_head *head); static inline void unregister_netdevice(struct net_device *dev) { unregister_netdevice_queue(dev, NULL); } -extern int netdev_refcnt_read(const struct net_device *dev); -extern void free_netdev(struct net_device *dev); -extern void synchronize_net(void); -extern int init_dummy_netdev(struct net_device *dev); +int netdev_refcnt_read(const struct net_device *dev); +void free_netdev(struct net_device *dev); +void synchronize_net(void); +int init_dummy_netdev(struct net_device *dev); -extern struct net_device *dev_get_by_index(struct net *net, int ifindex); -extern struct net_device *__dev_get_by_index(struct net *net, int ifindex); -extern struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); -extern int netdev_get_name(struct net *net, char *name, int ifindex); -extern int dev_restart(struct net_device *dev); +struct net_device *dev_get_by_index(struct net *net, int ifindex); +struct net_device *__dev_get_by_index(struct net *net, int ifindex); +struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); +int netdev_get_name(struct net *net, char *name, int ifindex); +int dev_restart(struct net_device *dev); #ifdef CONFIG_NETPOLL_TRAP -extern int netpoll_trap(void); +int netpoll_trap(void); #endif -extern int skb_gro_receive(struct sk_buff **head, - struct sk_buff *skb); +int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb); static inline unsigned int skb_gro_offset(const struct sk_buff *skb) { @@ -1883,7 +1881,7 @@ static inline int dev_parse_header(const struct sk_buff *skb, } typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len); -extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); +int register_gifconf(unsigned int family, gifconf_func_t *gifconf); static inline int unregister_gifconf(unsigned int family) { return register_gifconf(family, NULL); @@ -1954,7 +1952,7 @@ static inline void input_queue_tail_incr_save(struct softnet_data *sd, DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); -extern void __netif_schedule(struct Qdisc *q); +void __netif_schedule(struct Qdisc *q); static inline void netif_schedule_queue(struct netdev_queue *txq) { @@ -2274,8 +2272,8 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index) } #ifdef CONFIG_XPS -extern int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, - u16 index); +int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, + u16 index); #else static inline int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, @@ -2306,12 +2304,10 @@ static inline bool netif_is_multiqueue(const struct net_device *dev) return dev->num_tx_queues > 1; } -extern int netif_set_real_num_tx_queues(struct net_device *dev, - unsigned int txq); +int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq); #ifdef CONFIG_RPS -extern int netif_set_real_num_rx_queues(struct net_device *dev, - unsigned int rxq); +int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq); #else static inline int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq) @@ -2338,28 +2334,27 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev, } #define DEFAULT_MAX_NUM_RSS_QUEUES (8) -extern int netif_get_num_default_rss_queues(void); +int netif_get_num_default_rss_queues(void); /* Use this variant when it is known for sure that it * is executing from hardware interrupt context or with hardware interrupts * disabled. */ -extern void dev_kfree_skb_irq(struct sk_buff *skb); +void dev_kfree_skb_irq(struct sk_buff *skb); /* Use this variant in places where it could be invoked * from either hardware interrupt or other context, with hardware interrupts * either disabled or enabled. */ -extern void dev_kfree_skb_any(struct sk_buff *skb); +void dev_kfree_skb_any(struct sk_buff *skb); -extern int netif_rx(struct sk_buff *skb); -extern int netif_rx_ni(struct sk_buff *skb); -extern int netif_receive_skb(struct sk_buff *skb); -extern gro_result_t napi_gro_receive(struct napi_struct *napi, - struct sk_buff *skb); -extern void napi_gro_flush(struct napi_struct *napi, bool flush_old); -extern struct sk_buff * napi_get_frags(struct napi_struct *napi); -extern gro_result_t napi_gro_frags(struct napi_struct *napi); +int netif_rx(struct sk_buff *skb); +int netif_rx_ni(struct sk_buff *skb); +int netif_receive_skb(struct sk_buff *skb); +gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); +void napi_gro_flush(struct napi_struct *napi, bool flush_old); +struct sk_buff *napi_get_frags(struct napi_struct *napi); +gro_result_t napi_gro_frags(struct napi_struct *napi); static inline void napi_free_frags(struct napi_struct *napi) { @@ -2367,40 +2362,35 @@ static inline void napi_free_frags(struct napi_struct *napi) napi->skb = NULL; } -extern int netdev_rx_handler_register(struct net_device *dev, - rx_handler_func_t *rx_handler, - void *rx_handler_data); -extern void netdev_rx_handler_unregister(struct net_device *dev); - -extern bool dev_valid_name(const char *name); -extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); -extern int dev_ethtool(struct net *net, struct ifreq *); -extern unsigned int dev_get_flags(const struct net_device *); -extern int __dev_change_flags(struct net_device *, unsigned int flags); -extern int dev_change_flags(struct net_device *, unsigned int); -extern void __dev_notify_flags(struct net_device *, unsigned int old_flags); -extern int dev_change_name(struct net_device *, const char *); -extern int dev_set_alias(struct net_device *, const char *, size_t); -extern int dev_change_net_namespace(struct net_device *, - struct net *, const char *); -extern int dev_set_mtu(struct net_device *, int); -extern void dev_set_group(struct net_device *, int); -extern int dev_set_mac_address(struct net_device *, - struct sockaddr *); -extern int dev_change_carrier(struct net_device *, - bool new_carrier); -extern int dev_get_phys_port_id(struct net_device *dev, - struct netdev_phys_port_id *ppid); -extern int dev_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev, - struct netdev_queue *txq); -extern int dev_forward_skb(struct net_device *dev, - struct sk_buff *skb); +int netdev_rx_handler_register(struct net_device *dev, + rx_handler_func_t *rx_handler, + void *rx_handler_data); +void netdev_rx_handler_unregister(struct net_device *dev); + +bool dev_valid_name(const char *name); +int dev_ioctl(struct net *net, unsigned int cmd, void __user *); +int dev_ethtool(struct net *net, struct ifreq *); +unsigned int dev_get_flags(const struct net_device *); +int __dev_change_flags(struct net_device *, unsigned int flags); +int dev_change_flags(struct net_device *, unsigned int); +void __dev_notify_flags(struct net_device *, unsigned int old_flags); +int dev_change_name(struct net_device *, const char *); +int dev_set_alias(struct net_device *, const char *, size_t); +int dev_change_net_namespace(struct net_device *, struct net *, const char *); +int dev_set_mtu(struct net_device *, int); +void dev_set_group(struct net_device *, int); +int dev_set_mac_address(struct net_device *, struct sockaddr *); +int dev_change_carrier(struct net_device *, bool new_carrier); +int dev_get_phys_port_id(struct net_device *dev, + struct netdev_phys_port_id *ppid); +int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, + struct netdev_queue *txq); +int dev_forward_skb(struct net_device *dev, struct sk_buff *skb); extern int netdev_budget; /* Called by rtnetlink.c:rtnl_unlock() */ -extern void netdev_run_todo(void); +void netdev_run_todo(void); /** * dev_put - release reference to device @@ -2433,9 +2423,9 @@ static inline void dev_hold(struct net_device *dev) * kind of lower layer not just hardware media. */ -extern void linkwatch_init_dev(struct net_device *dev); -extern void linkwatch_fire_event(struct net_device *dev); -extern void linkwatch_forget_dev(struct net_device *dev); +void linkwatch_init_dev(struct net_device *dev); +void linkwatch_fire_event(struct net_device *dev); +void linkwatch_forget_dev(struct net_device *dev); /** * netif_carrier_ok - test if carrier present @@ -2448,13 +2438,13 @@ static inline bool netif_carrier_ok(const struct net_device *dev) return !test_bit(__LINK_STATE_NOCARRIER, &dev->state); } -extern unsigned long dev_trans_start(struct net_device *dev); +unsigned long dev_trans_start(struct net_device *dev); -extern void __netdev_watchdog_up(struct net_device *dev); +void __netdev_watchdog_up(struct net_device *dev); -extern void netif_carrier_on(struct net_device *dev); +void netif_carrier_on(struct net_device *dev); -extern void netif_carrier_off(struct net_device *dev); +void netif_carrier_off(struct net_device *dev); /** * netif_dormant_on - mark device as dormant. @@ -2522,9 +2512,9 @@ static inline bool netif_device_present(struct net_device *dev) return test_bit(__LINK_STATE_PRESENT, &dev->state); } -extern void netif_device_detach(struct net_device *dev); +void netif_device_detach(struct net_device *dev); -extern void netif_device_attach(struct net_device *dev); +void netif_device_attach(struct net_device *dev); /* * Network interface message level settings @@ -2733,98 +2723,93 @@ static inline void netif_addr_unlock_bh(struct net_device *dev) /* These functions live elsewhere (drivers/net/net_init.c, but related) */ -extern void ether_setup(struct net_device *dev); +void ether_setup(struct net_device *dev); /* Support for loadable net-drivers */ -extern struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, - void (*setup)(struct net_device *), - unsigned int txqs, unsigned int rxqs); +struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, + void (*setup)(struct net_device *), + unsigned int txqs, unsigned int rxqs); #define alloc_netdev(sizeof_priv, name, setup) \ alloc_netdev_mqs(sizeof_priv, name, setup, 1, 1) #define alloc_netdev_mq(sizeof_priv, name, setup, count) \ alloc_netdev_mqs(sizeof_priv, name, setup, count, count) -extern int register_netdev(struct net_device *dev); -extern void unregister_netdev(struct net_device *dev); +int register_netdev(struct net_device *dev); +void unregister_netdev(struct net_device *dev); /* General hardware address lists handling functions */ -extern int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, unsigned char addr_type); -extern void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len, unsigned char addr_type); -extern int __hw_addr_sync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len); -extern void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len); -extern void __hw_addr_flush(struct netdev_hw_addr_list *list); -extern void __hw_addr_init(struct netdev_hw_addr_list *list); +int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type); +void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len, unsigned char addr_type); +int __hw_addr_sync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, int addr_len); +void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, int addr_len); +void __hw_addr_flush(struct netdev_hw_addr_list *list); +void __hw_addr_init(struct netdev_hw_addr_list *list); /* Functions used for device addresses handling */ -extern int dev_addr_add(struct net_device *dev, const unsigned char *addr, - unsigned char addr_type); -extern int dev_addr_del(struct net_device *dev, const unsigned char *addr, - unsigned char addr_type); -extern int dev_addr_add_multiple(struct net_device *to_dev, - struct net_device *from_dev, - unsigned char addr_type); -extern int dev_addr_del_multiple(struct net_device *to_dev, - struct net_device *from_dev, - unsigned char addr_type); -extern void dev_addr_flush(struct net_device *dev); -extern int dev_addr_init(struct net_device *dev); +int dev_addr_add(struct net_device *dev, const unsigned char *addr, + unsigned char addr_type); +int dev_addr_del(struct net_device *dev, const unsigned char *addr, + unsigned char addr_type); +int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, unsigned char addr_type); +int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, unsigned char addr_type); +void dev_addr_flush(struct net_device *dev); +int dev_addr_init(struct net_device *dev); /* Functions used for unicast addresses handling */ -extern int dev_uc_add(struct net_device *dev, const unsigned char *addr); -extern int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr); -extern int dev_uc_del(struct net_device *dev, const unsigned char *addr); -extern int dev_uc_sync(struct net_device *to, struct net_device *from); -extern int dev_uc_sync_multiple(struct net_device *to, struct net_device *from); -extern void dev_uc_unsync(struct net_device *to, struct net_device *from); -extern void dev_uc_flush(struct net_device *dev); -extern void dev_uc_init(struct net_device *dev); +int dev_uc_add(struct net_device *dev, const unsigned char *addr); +int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr); +int dev_uc_del(struct net_device *dev, const unsigned char *addr); +int dev_uc_sync(struct net_device *to, struct net_device *from); +int dev_uc_sync_multiple(struct net_device *to, struct net_device *from); +void dev_uc_unsync(struct net_device *to, struct net_device *from); +void dev_uc_flush(struct net_device *dev); +void dev_uc_init(struct net_device *dev); /* Functions used for multicast addresses handling */ -extern int dev_mc_add(struct net_device *dev, const unsigned char *addr); -extern int dev_mc_add_global(struct net_device *dev, const unsigned char *addr); -extern int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr); -extern int dev_mc_del(struct net_device *dev, const unsigned char *addr); -extern int dev_mc_del_global(struct net_device *dev, const unsigned char *addr); -extern int dev_mc_sync(struct net_device *to, struct net_device *from); -extern int dev_mc_sync_multiple(struct net_device *to, struct net_device *from); -extern void dev_mc_unsync(struct net_device *to, struct net_device *from); -extern void dev_mc_flush(struct net_device *dev); -extern void dev_mc_init(struct net_device *dev); +int dev_mc_add(struct net_device *dev, const unsigned char *addr); +int dev_mc_add_global(struct net_device *dev, const unsigned char *addr); +int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr); +int dev_mc_del(struct net_device *dev, const unsigned char *addr); +int dev_mc_del_global(struct net_device *dev, const unsigned char *addr); +int dev_mc_sync(struct net_device *to, struct net_device *from); +int dev_mc_sync_multiple(struct net_device *to, struct net_device *from); +void dev_mc_unsync(struct net_device *to, struct net_device *from); +void dev_mc_flush(struct net_device *dev); +void dev_mc_init(struct net_device *dev); /* Functions used for secondary unicast and multicast support */ -extern void dev_set_rx_mode(struct net_device *dev); -extern void __dev_set_rx_mode(struct net_device *dev); -extern int dev_set_promiscuity(struct net_device *dev, int inc); -extern int dev_set_allmulti(struct net_device *dev, int inc); -extern void netdev_state_change(struct net_device *dev); -extern void netdev_notify_peers(struct net_device *dev); -extern void netdev_features_change(struct net_device *dev); +void dev_set_rx_mode(struct net_device *dev); +void __dev_set_rx_mode(struct net_device *dev); +int dev_set_promiscuity(struct net_device *dev, int inc); +int dev_set_allmulti(struct net_device *dev, int inc); +void netdev_state_change(struct net_device *dev); +void netdev_notify_peers(struct net_device *dev); +void netdev_features_change(struct net_device *dev); /* Load a device via the kmod */ -extern void dev_load(struct net *net, const char *name); -extern struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, - struct rtnl_link_stats64 *storage); -extern void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, - const struct net_device_stats *netdev_stats); +void dev_load(struct net *net, const char *name); +struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, + struct rtnl_link_stats64 *storage); +void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, + const struct net_device_stats *netdev_stats); extern int netdev_max_backlog; extern int netdev_tstamp_prequeue; extern int weight_p; extern int bpf_jit_enable; -extern bool netdev_has_upper_dev(struct net_device *dev, - struct net_device *upper_dev); -extern bool netdev_has_any_upper_dev(struct net_device *dev); -extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, - struct list_head **iter); +bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev); +bool netdev_has_any_upper_dev(struct net_device *dev); +struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, + struct list_head **iter); /* iterate through upper list, must be called under RCU read lock */ #define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \ @@ -2833,10 +2818,10 @@ extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *d updev; \ updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter))) -extern void *netdev_lower_get_next_private(struct net_device *dev, - struct list_head **iter); -extern void *netdev_lower_get_next_private_rcu(struct net_device *dev, - struct list_head **iter); +void *netdev_lower_get_next_private(struct net_device *dev, + struct list_head **iter); +void *netdev_lower_get_next_private_rcu(struct net_device *dev, + struct list_head **iter); #define netdev_for_each_lower_private(dev, priv, iter) \ for (iter = (dev)->adj_list.lower.next, \ @@ -2850,27 +2835,26 @@ extern void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv; \ priv = netdev_lower_get_next_private_rcu(dev, &(iter))) -extern void *netdev_adjacent_get_private(struct list_head *adj_list); -extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev); -extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); -extern int netdev_upper_dev_link(struct net_device *dev, +void *netdev_adjacent_get_private(struct list_head *adj_list); +struct net_device *netdev_master_upper_dev_get(struct net_device *dev); +struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); +int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); +int netdev_master_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); -extern int netdev_master_upper_dev_link(struct net_device *dev, - struct net_device *upper_dev); -extern int netdev_master_upper_dev_link_private(struct net_device *dev, - struct net_device *upper_dev, - void *private); -extern void netdev_upper_dev_unlink(struct net_device *dev, - struct net_device *upper_dev); -extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev, - struct net_device *lower_dev); -extern void *netdev_lower_dev_get_private(struct net_device *dev, - struct net_device *lower_dev); -extern int skb_checksum_help(struct sk_buff *skb); -extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, - netdev_features_t features, bool tx_path); -extern struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, - netdev_features_t features); +int netdev_master_upper_dev_link_private(struct net_device *dev, + struct net_device *upper_dev, + void *private); +void netdev_upper_dev_unlink(struct net_device *dev, + struct net_device *upper_dev); +void *netdev_lower_dev_get_private_rcu(struct net_device *dev, + struct net_device *lower_dev); +void *netdev_lower_dev_get_private(struct net_device *dev, + struct net_device *lower_dev); +int skb_checksum_help(struct sk_buff *skb); +struct sk_buff *__skb_gso_segment(struct sk_buff *skb, + netdev_features_t features, bool tx_path); +struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, + netdev_features_t features); static inline struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features) @@ -2892,30 +2876,30 @@ static inline bool can_checksum_protocol(netdev_features_t features, } #ifdef CONFIG_BUG -extern void netdev_rx_csum_fault(struct net_device *dev); +void netdev_rx_csum_fault(struct net_device *dev); #else static inline void netdev_rx_csum_fault(struct net_device *dev) { } #endif /* rx skb timestamps */ -extern void net_enable_timestamp(void); -extern void net_disable_timestamp(void); +void net_enable_timestamp(void); +void net_disable_timestamp(void); #ifdef CONFIG_PROC_FS -extern int __init dev_proc_init(void); +int __init dev_proc_init(void); #else #define dev_proc_init() 0 #endif -extern int netdev_class_create_file(struct class_attribute *class_attr); -extern void netdev_class_remove_file(struct class_attribute *class_attr); +int netdev_class_create_file(struct class_attribute *class_attr); +void netdev_class_remove_file(struct class_attribute *class_attr); extern struct kobj_ns_type_operations net_ns_type_operations; -extern const char *netdev_drivername(const struct net_device *dev); +const char *netdev_drivername(const struct net_device *dev); -extern void linkwatch_run_queue(void); +void linkwatch_run_queue(void); static inline netdev_features_t netdev_get_wanted_features( struct net_device *dev) @@ -3007,22 +2991,22 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } -extern __printf(3, 4) +__printf(3, 4) int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_emerg(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_alert(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_crit(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_err(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_warn(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_notice(const struct net_device *dev, const char *format, ...); -extern __printf(2, 3) +__printf(2, 3) int netdev_info(const struct net_device *dev, const char *format, ...); #define MODULE_ALIAS_NETDEV(device) \ -- cgit From e34ff4906199d2ebd248ae897ae34f52bea151c9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:05 -0400 Subject: sysfs: remove ktype->namespace() invocations in directory code For some unrecognizable reason, namespace information is communicated to sysfs through ktype->namespace() callback when there's *nothing* which needs the use of a callback. The whole sequence of operations is completely synchronous and sysfs operations simply end up calling back into the layer which just invoked it in order to find out the namespace information, which is completely backwards, obfuscates what's going on and unnecessarily tangles two separate layers. This patch doesn't remove ktype->namespace() but shifts its handling to kobject layer. We probably want to get rid of the callback in the long term. This patch adds an explicit param to sysfs_{create|rename|move}_dir() and renames them to sysfs_{create|rename|move}_dir_ns(), respectively. ktype->namespace() invocations are moved to the calling sites of the above functions. A new helper kboject_namespace() is introduced which directly tests kobj_ns_type_operations->type which should give the same result as testing sysfs_fs_type(parent_sd) and returns @kobj's namespace tag as necessary. kobject_namespace() is extern as it will be used from another file in the following patches. This patch should be an equivalent conversion without any functional difference. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 23 ++++++++--------------- include/linux/kobject.h | 1 + include/linux/sysfs.h | 20 ++++++++++++-------- lib/kobject.c | 28 ++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 834c64cb7f88..878ac3afe1b8 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -730,14 +730,14 @@ static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj) } /** - * sysfs_create_dir - create a directory for an object. - * @kobj: object we're creating directory for. + * sysfs_create_dir_ns - create a directory for an object with a namespace tag + * @kobj: object we're creating directory for + * @ns: the namespace tag to use */ -int sysfs_create_dir(struct kobject *kobj) +int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) { enum kobj_ns_type type; struct sysfs_dirent *parent_sd, *sd; - const void *ns = NULL; int error = 0; BUG_ON(!kobj); @@ -750,8 +750,6 @@ int sysfs_create_dir(struct kobject *kobj) if (!parent_sd) return -ENOENT; - if (sysfs_ns_type(parent_sd)) - ns = kobj->ktype->namespace(kobj); type = sysfs_read_ns_type(kobj); error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd); @@ -909,26 +907,21 @@ int sysfs_rename(struct sysfs_dirent *sd, return error; } -int sysfs_rename_dir(struct kobject *kobj, const char *new_name) +int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, + const void *new_ns) { struct sysfs_dirent *parent_sd = kobj->sd->s_parent; - const void *new_ns = NULL; - - if (sysfs_ns_type(parent_sd)) - new_ns = kobj->ktype->namespace(kobj); return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name); } -int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) +int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, + const void *new_ns) { struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; - const void *new_ns = NULL; BUG_ON(!sd->s_parent); - if (sysfs_ns_type(sd->s_parent)) - new_ns = kobj->ktype->namespace(kobj); new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index de6dcbcc6ef7..e7ba650086ce 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -107,6 +107,7 @@ extern int __must_check kobject_move(struct kobject *, struct kobject *); extern struct kobject *kobject_get(struct kobject *kobj); extern void kobject_put(struct kobject *kobj); +extern const void *kobject_namespace(struct kobject *kobj); extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); struct kobj_type { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 82f7fac78e77..7f56bad3be82 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -182,11 +182,13 @@ struct sysfs_dirent; int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), void *data, struct module *owner); -int __must_check sysfs_create_dir(struct kobject *kobj); +int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns); void sysfs_remove_dir(struct kobject *kobj); -int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); -int __must_check sysfs_move_dir(struct kobject *kobj, - struct kobject *new_parent_kobj); +int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, + const void *new_ns); +int __must_check sysfs_move_dir_ns(struct kobject *kobj, + struct kobject *new_parent_kobj, + const void *new_ns); int __must_check sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr, @@ -258,7 +260,7 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, return -ENOSYS; } -static inline int sysfs_create_dir(struct kobject *kobj) +static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) { return 0; } @@ -267,13 +269,15 @@ static inline void sysfs_remove_dir(struct kobject *kobj) { } -static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) +static inline int sysfs_rename_dir_ns(struct kobject *kobj, + const char *new_name, const void *new_ns) { return 0; } -static inline int sysfs_move_dir(struct kobject *kobj, - struct kobject *new_parent_kobj) +static inline int sysfs_move_dir_ns(struct kobject *kobj, + struct kobject *new_parent_kobj, + const void *new_ns) { return 0; } diff --git a/lib/kobject.c b/lib/kobject.c index 962175134702..85fb3a161b21 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -18,6 +18,24 @@ #include #include +/** + * kobject_namespace - return @kobj's namespace tag + * @kobj: kobject in question + * + * Returns namespace tag of @kobj if its parent has namespace ops enabled + * and thus @kobj should have a namespace tag associated with it. Returns + * %NULL otherwise. + */ +const void *kobject_namespace(struct kobject *kobj) +{ + const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj); + + if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) + return NULL; + + return kobj->ktype->namespace(kobj); +} + /* * populate_dir - populate directory with attributes. * @kobj: object we're working on. @@ -46,8 +64,9 @@ static int populate_dir(struct kobject *kobj) static int create_dir(struct kobject *kobj) { - int error = 0; - error = sysfs_create_dir(kobj); + int error; + + error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj)); if (!error) { error = populate_dir(kobj); if (error) @@ -428,7 +447,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name) goto out; } - error = sysfs_rename_dir(kobj, new_name); + error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj)); if (error) goto out; @@ -472,6 +491,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) if (kobj->kset) new_parent = kobject_get(&kobj->kset->kobj); } + /* old object path */ devpath = kobject_get_path(kobj, GFP_KERNEL); if (!devpath) { @@ -486,7 +506,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) sprintf(devpath_string, "DEVPATH_OLD=%s", devpath); envp[0] = devpath_string; envp[1] = NULL; - error = sysfs_move_dir(kobj, new_parent); + error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj)); if (error) goto out; old_parent = kobj->parent; -- cgit From 4b30ee58ee64c64f59fd876e4afa6ed82caef3a4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:06 -0400 Subject: sysfs: remove ktype->namespace() invocations in symlink code There's no reason for sysfs to be calling ktype->namespace(). It is backwards, obfuscates what's going on and unnecessarily tangles two separate layers. There are two places where symlink code calls ktype->namespace(). * sysfs_do_create_link_sd() calls it to find out the namespace tag of the target directory. Unless symlinking races with cross-namespace renaming, this equals @target_sd->s_ns. * sysfs_rename_link() uses it to find out the new namespace to rename to and the new namespace can be different from the existing one. The function is renamed to sysfs_rename_link_ns() with an explicit @ns argument and the ktype->namespace() invocation is shifted to the device layer. While this patch replaces ktype->namespace() invocation with the recorded result in @target_sd, this shouldn't result in any behvior difference. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 8 +++++--- fs/sysfs/symlink.c | 16 +++++++--------- include/linux/sysfs.h | 16 ++++++++++++---- 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/base/core.c b/drivers/base/core.c index c7cfadcf6752..3335000be2dc 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1881,6 +1881,7 @@ EXPORT_SYMBOL_GPL(device_destroy); */ int device_rename(struct device *dev, const char *new_name) { + struct kobject *kobj = &dev->kobj; char *old_device_name = NULL; int error; @@ -1898,13 +1899,14 @@ int device_rename(struct device *dev, const char *new_name) } if (dev->class) { - error = sysfs_rename_link(&dev->class->p->subsys.kobj, - &dev->kobj, old_device_name, new_name); + error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj, + kobj, old_device_name, + new_name, kobject_namespace(kobj)); if (error) goto out; } - error = kobject_rename(&dev->kobj, new_name); + error = kobject_rename(kobj, new_name); if (error) goto out; diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 2dd4507d9edd..12d58ada3e6d 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -52,7 +52,7 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, ns_type = sysfs_ns_type(parent_sd); if (ns_type) - sd->s_ns = target->ktype->namespace(target); + sd->s_ns = target_sd->s_ns; sd->s_symlink.target_sd = target_sd; target_sd = NULL; /* reference is now owned by the symlink */ @@ -181,19 +181,20 @@ void sysfs_remove_link(struct kobject *kobj, const char *name) EXPORT_SYMBOL_GPL(sysfs_remove_link); /** - * sysfs_rename_link - rename symlink in object's directory. + * sysfs_rename_link_ns - rename symlink in object's directory. * @kobj: object we're acting for. * @targ: object we're pointing to. * @old: previous name of the symlink. * @new: new name of the symlink. + * @new_ns: new namespace of the symlink. * * A helper function for the common rename symlink idiom. */ -int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, - const char *old, const char *new) +int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new, const void *new_ns) { struct sysfs_dirent *parent_sd, *sd = NULL; - const void *old_ns = NULL, *new_ns = NULL; + const void *old_ns = NULL; int result; if (!kobj) @@ -215,16 +216,13 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, if (sd->s_symlink.target_sd->s_dir.kobj != targ) goto out; - if (sysfs_ns_type(parent_sd)) - new_ns = targ->ktype->namespace(targ); - result = sysfs_rename(sd, parent_sd, new_ns, new); out: sysfs_put(sd); return result; } -EXPORT_SYMBOL_GPL(sysfs_rename_link); +EXPORT_SYMBOL_GPL(sysfs_rename_link_ns); static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7f56bad3be82..c792f73ac7fa 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -213,8 +213,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj, const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); -int sysfs_rename_link(struct kobject *kobj, struct kobject *target, - const char *old_name, const char *new_name); +int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name, + const void *new_ns); void sysfs_delete_link(struct kobject *dir, struct kobject *targ, const char *name); @@ -340,8 +341,9 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } -static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, - const char *old_name, const char *new_name) +static inline int sysfs_rename_link_ns(struct kobject *k, struct kobject *t, + const char *old_name, + const char *new_name, const void *ns) { return 0; } @@ -454,4 +456,10 @@ static inline void sysfs_remove_file(struct kobject *kobj, return sysfs_remove_file_ns(kobj, attr, NULL); } +static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name) +{ + return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL); +} + #endif /* _SYSFS_H_ */ -- cgit From 388975cccaaf11abd47525f664c76891c440481a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 23:19:13 -0400 Subject: sysfs: clean up sysfs_get_dirent() The pre-existing sysfs interfaces which take explicit namespace argument are weird in that they place the optional @ns in front of @name which is contrary to the established convention. For example, we end up forcing vast majority of sysfs_get_dirent() users to do sysfs_get_dirent(parent, NULL, name), which is silly and error-prone especially as @ns and @name may be interchanged without causing compilation warning. This renames sysfs_get_dirent() to sysfs_get_dirent_ns() and swap the positions of @name and @ns, and sysfs_get_dirent() is now a wrapper around sysfs_get_dirent_ns(). This makes confusions a lot less likely. There are other interfaces which take @ns before @name. They'll be updated by following patches. This patch doesn't introduce any functional changes. v2: EXPORT_SYMBOL_GPL() wasn't updated leading to undefined symbol error on module builds. Reported by build test robot. Fixed. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Cc: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 2 +- drivers/md/bitmap.c | 4 ++-- drivers/md/md.c | 2 +- drivers/md/md.h | 2 +- fs/sysfs/dir.c | 11 ++++++----- fs/sysfs/file.c | 4 ++-- fs/sysfs/group.c | 10 +++++----- fs/sysfs/symlink.c | 2 +- fs/sysfs/sysfs.h | 3 --- include/linux/sysfs.h | 19 ++++++++++++------- 10 files changed, 31 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 86ef3461ec06..a094356020a6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -408,7 +408,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; if (!value_sd) { - value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); + value_sd = sysfs_get_dirent(dev->kobj.sd, "value"); if (!value_sd) { ret = -ENODEV; goto err_out; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index a7fd82133b12..12dc29ba7399 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1654,9 +1654,9 @@ int bitmap_create(struct mddev *mddev) bitmap->mddev = mddev; if (mddev->kobj.sd) - bm = sysfs_get_dirent(mddev->kobj.sd, NULL, "bitmap"); + bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap"); if (bm) { - bitmap->sysfs_can_clear = sysfs_get_dirent(bm, NULL, "can_clear"); + bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear"); sysfs_put(bm); } else bitmap->sysfs_can_clear = NULL; diff --git a/drivers/md/md.c b/drivers/md/md.c index adf4d7e1d5e1..8a0d7625681c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3555,7 +3555,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) printk(KERN_WARNING "md: cannot register extra attributes for %s\n", mdname(mddev)); - mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, NULL, "sync_action"); + mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); } if (mddev->pers->sync_request != NULL && pers->sync_request == NULL) { diff --git a/drivers/md/md.h b/drivers/md/md.h index 608050c43f17..b0051f2fbc0c 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -501,7 +501,7 @@ extern struct attribute_group md_bitmap_group; static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name) { if (sd) - return sysfs_get_dirent(sd, NULL, name); + return sysfs_get_dirent(sd, name); return sd; } static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 1dfb4aaf9446..fee19d16e4a2 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -630,9 +630,10 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, } /** - * sysfs_get_dirent - find and get sysfs_dirent with the given name + * sysfs_get_dirent_ns - find and get sysfs_dirent with the given name * @parent_sd: sysfs_dirent to search under * @name: name to look for + * @ns: the namespace tag to use * * Look for sysfs_dirent with name @name under @parent_sd and get * it if found. @@ -643,9 +644,9 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, * RETURNS: * Pointer to sysfs_dirent if found, NULL if not. */ -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name) +struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, + const unsigned char *name, + const void *ns) { struct sysfs_dirent *sd; @@ -656,7 +657,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, return sd; } -EXPORT_SYMBOL_GPL(sysfs_get_dirent); +EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, const void *ns, const char *name, struct sysfs_dirent **p_sd) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e784340f1599..0f3214a70985 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -563,7 +563,7 @@ int sysfs_add_file_to_group(struct kobject *kobj, int error; if (group) - dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); + dir_sd = sysfs_get_dirent(kobj->sd, group); else dir_sd = sysfs_get(kobj->sd); @@ -645,7 +645,7 @@ void sysfs_remove_file_from_group(struct kobject *kobj, struct sysfs_dirent *dir_sd; if (group) - dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); + dir_sd = sysfs_get_dirent(kobj->sd, group); else dir_sd = sysfs_get(kobj->sd); if (dir_sd) { diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 25c78f23dae8..21102158ca33 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -207,7 +207,7 @@ void sysfs_remove_group(struct kobject *kobj, struct sysfs_dirent *sd; if (grp->name) { - sd = sysfs_get_dirent(dir_sd, NULL, grp->name); + sd = sysfs_get_dirent(dir_sd, grp->name); if (!sd) { WARN(!sd, KERN_WARNING "sysfs group %p not found for kobject '%s'\n", @@ -262,7 +262,7 @@ int sysfs_merge_group(struct kobject *kobj, struct attribute *const *attr; int i; - dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); + dir_sd = sysfs_get_dirent(kobj->sd, grp->name); if (!dir_sd) return -ENOENT; @@ -289,7 +289,7 @@ void sysfs_unmerge_group(struct kobject *kobj, struct sysfs_dirent *dir_sd; struct attribute *const *attr; - dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); + dir_sd = sysfs_get_dirent(kobj->sd, grp->name); if (dir_sd) { for (attr = grp->attrs; *attr; ++attr) sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); @@ -311,7 +311,7 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, struct sysfs_dirent *dir_sd; int error = 0; - dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); + dir_sd = sysfs_get_dirent(kobj->sd, group_name); if (!dir_sd) return -ENOENT; @@ -333,7 +333,7 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, { struct sysfs_dirent *dir_sd; - dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); + dir_sd = sysfs_get_dirent(kobj->sd, group_name); if (dir_sd) { sysfs_hash_and_remove(dir_sd, NULL, link_name); sysfs_put(dir_sd); diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 7d981ce2e87f..c96b31a16485 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -191,7 +191,7 @@ int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ, old_ns = targ->sd->s_ns; result = -ENOENT; - sd = sysfs_get_dirent(parent_sd, old_ns, old); + sd = sysfs_get_dirent_ns(parent_sd, old, old_ns); if (!sd) goto out; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7664d1b3d594..6faacafda777 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -164,9 +164,6 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, const void *ns, const unsigned char *name); -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name); struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); void release_sysfs_dirent(struct sysfs_dirent *sd); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c792f73ac7fa..6695040a0317 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -245,9 +245,9 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); void sysfs_notify_dirent(struct sysfs_dirent *sd); -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name); +struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, + const unsigned char *name, + const void *ns); struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); void sysfs_put(struct sysfs_dirent *sd); @@ -422,10 +422,9 @@ static inline void sysfs_notify(struct kobject *kobj, const char *dir, static inline void sysfs_notify_dirent(struct sysfs_dirent *sd) { } -static inline -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name) +static inline struct sysfs_dirent * +sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, const unsigned char *name, + const void *ns) { return NULL; } @@ -462,4 +461,10 @@ static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL); } +static inline struct sysfs_dirent * +sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name) +{ + return sysfs_get_dirent_ns(parent_sd, name, NULL); +} + #endif /* _SYSFS_H_ */ -- cgit From eee031649707db3c9920d9498f8d03819b74fc23 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 11 Sep 2013 13:00:30 -0400 Subject: kobject: introduce kobj_completion A common way to handle kobject lifetimes in embedded in objects with different lifetime rules is to pair the kobject with a struct completion. This introduces a kobj_completion structure that can be used in place of the pairing, along with several convenience functions for initialization, release, and put-and-wait. Signed-off-by: Jeff Mahoney Signed-off-by: Greg Kroah-Hartman --- include/linux/kobj_completion.h | 18 +++++++++++++++ lib/kobject.c | 50 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 include/linux/kobj_completion.h (limited to 'include') diff --git a/include/linux/kobj_completion.h b/include/linux/kobj_completion.h new file mode 100644 index 000000000000..a428f6436063 --- /dev/null +++ b/include/linux/kobj_completion.h @@ -0,0 +1,18 @@ +#ifndef _KOBJ_COMPLETION_H_ +#define _KOBJ_COMPLETION_H_ + +#include +#include + +struct kobj_completion { + struct kobject kc_kobj; + struct completion kc_unregister; +}; + +#define kobj_to_kobj_completion(kobj) \ + container_of(kobj, struct kobj_completion, kc_kobj) + +void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype); +void kobj_completion_release(struct kobject *kobj); +void kobj_completion_del_and_wait(struct kobj_completion *kc); +#endif /* _KOBJ_COMPLETION_H_ */ diff --git a/lib/kobject.c b/lib/kobject.c index e769ee3c2fb9..a5a9b13b0648 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -749,6 +750,55 @@ const struct sysfs_ops kobj_sysfs_ops = { .store = kobj_attr_store, }; +/** + * kobj_completion_init - initialize a kobj_completion object. + * @kc: kobj_completion + * @ktype: type of kobject to initialize + * + * kobj_completion structures can be embedded within structures with different + * lifetime rules. During the release of the enclosing object, we can + * wait on the release of the kobject so that we don't free it while it's + * still busy. + */ +void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype) +{ + init_completion(&kc->kc_unregister); + kobject_init(&kc->kc_kobj, ktype); +} +EXPORT_SYMBOL_GPL(kobj_completion_init); + +/** + * kobj_completion_release - release a kobj_completion object + * @kobj: kobject embedded in kobj_completion + * + * Used with kobject_release to notify waiters that the kobject has been + * released. + */ +void kobj_completion_release(struct kobject *kobj) +{ + struct kobj_completion *kc = kobj_to_kobj_completion(kobj); + complete(&kc->kc_unregister); +} +EXPORT_SYMBOL_GPL(kobj_completion_release); + +/** + * kobj_completion_del_and_wait - release the kobject and wait for it + * @kc: kobj_completion object to release + * + * Delete the kobject from sysfs and drop the reference count. Then wait + * until any other outstanding references are also dropped. This routine + * is only necessary once other references may have been taken on the + * kobject. Typically this happens when the kobject has been published + * to sysfs via kobject_add. + */ +void kobj_completion_del_and_wait(struct kobj_completion *kc) +{ + kobject_del(&kc->kc_kobj); + kobject_put(&kc->kc_kobj); + wait_for_completion(&kc->kc_unregister); +} +EXPORT_SYMBOL_GPL(kobj_completion_del_and_wait); + /** * kset_register - initialize and add a kset. * @k: kset. -- cgit From 3f9120b0424f3e03c75518cb751f9e2bfa73c32a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 23 Sep 2013 16:27:26 +0200 Subject: driver core: prevent deferred probe with platform_driver_probe Prevent drivers relying on platform_driver_probe from requesting deferred probing in order to avoid further futile probe attempts (either the driver has been unregistered or its probe function has been set to platform_drv_probe_fail when probing is retried). Note that several platform drivers currently return subsystem errors from probe and that these can include -EPROBE_DEFER (e.g. if a gpio request fails). Add a warning to platform_drv_probe that can be used to catch drivers that inadvertently request probe deferral while using platform_driver_probe. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 17 +++++++++++++---- include/linux/platform_device.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4f8bef3eb5a8..47051cd25113 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -488,6 +488,11 @@ static int platform_drv_probe(struct device *_dev) if (ret && ACPI_HANDLE(_dev)) acpi_dev_pm_detach(_dev, true); + if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { + dev_warn(_dev, "probe deferral not supported\n"); + ret = -ENXIO; + } + return ret; } @@ -553,8 +558,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister); /** * platform_driver_probe - register driver for non-hotpluggable device * @drv: platform driver structure - * @probe: the driver probe routine, probably from an __init section, - * must not return -EPROBE_DEFER. + * @probe: the driver probe routine, probably from an __init section * * Use this instead of platform_driver_register() when you know the device * is not hotpluggable and has already been registered, and you want to @@ -565,8 +569,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister); * into system-on-chip processors, where the controller devices have been * configured as part of board setup. * - * This is incompatible with deferred probing so probe() must not - * return -EPROBE_DEFER. + * Note that this is incompatible with deferred probing. * * Returns zero if the driver registered and bound to a device, else returns * a negative error code and with the driver not registered. @@ -576,6 +579,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, { int retval, code; + /* + * Prevent driver from requesting probe deferral to avoid further + * futile probe attempts. + */ + drv->prevent_deferred_probe = true; + /* make sure driver won't have bind/unbind attributes */ drv->driver.suppress_bind_attrs = true; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index ce8e4ffd78c7..16f6654082dd 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -178,6 +178,7 @@ struct platform_driver { int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; + bool prevent_deferred_probe; }; #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ -- cgit From a75e1c73a46eed0332d036e371f714e76d167c07 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Sat, 31 Aug 2013 13:16:49 +0900 Subject: extcon: Fix indentation coding style to improve readability Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham --- drivers/extcon/extcon-adc-jack.c | 20 +++++----- drivers/extcon/extcon-class.c | 26 ++++++------- include/linux/extcon.h | 67 ++++++++++++++++++---------------- include/linux/extcon/extcon-adc-jack.h | 42 ++++++++++----------- include/linux/extcon/extcon-gpio.h | 16 ++++---- 5 files changed, 87 insertions(+), 84 deletions(-) (limited to 'include') diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 5985807e52c9..5d16428afd53 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -27,16 +27,16 @@ /** * struct adc_jack_data - internal data for adc_jack device driver - * @edev - extcon device. - * @cable_names - list of supported cables. - * @num_cables - size of cable_names. - * @adc_conditions - list of adc value conditions. - * @num_conditions - size of adc_conditions. - * @irq - irq number of attach/detach event (0 if not exist). - * @handling_delay - interrupt handler will schedule extcon event - * handling at handling_delay jiffies. - * @handler - extcon event handler called by interrupt handler. - * @chan - iio channel being queried. + * @edev: extcon device. + * @cable_names: list of supported cables. + * @num_cables: size of cable_names. + * @adc_conditions: list of adc value conditions. + * @num_conditions: size of adc_conditions. + * @irq: irq number of attach/detach event (0 if not exist). + * @handling_delay: interrupt handler will schedule extcon event + * handling at handling_delay jiffies. + * @handler: extcon event handler called by interrupt handler. + * @chan: iio channel being queried. */ struct adc_jack_data { struct extcon_dev edev; diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 148382faded9..a29720822847 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -74,7 +74,7 @@ static DEFINE_MUTEX(extcon_dev_list_lock); /** * check_mutually_exclusive - Check if new_state violates mutually_exclusive - * condition. + * condition. * @edev: the extcon device * @new_state: new cable attach status for @edev * @@ -189,7 +189,7 @@ static ssize_t cable_state_show(struct device *dev, /** * extcon_update_state() - Update the cable attach states of the extcon device - * only for the masked bits. + * only for the masked bits. * @edev: the extcon device * @mask: the bit mask to designate updated bits. * @state: new cable attach status for @edev @@ -227,7 +227,6 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) edev->state |= state & mask; raw_notifier_call_chain(&edev->nh, old_state, edev); - /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (prop_buf) { @@ -339,8 +338,9 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state); /** * extcon_set_cable_state_() - Set the status of a specific cable. - * @edev: the extcon device that has the cable. - * @index: cable index that can be retrieved by extcon_find_cable_index(). + * @edev: the extcon device that has the cable. + * @index: cable index that can be retrieved by + * extcon_find_cable_index(). * @cable_state: the new cable status. The default semantics is * true: attached / false: detached. */ @@ -359,8 +359,8 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_); /** * extcon_set_cable_state() - Set the status of a specific cable. - * @edev: the extcon device that has the cable. - * @cable_name: cable name. + * @edev: the extcon device that has the cable. + * @cable_name: cable name. * @cable_state: the new cable status. The default semantics is * true: attached / false: detached. * @@ -419,14 +419,14 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, /** * extcon_register_interest() - Register a notifier for a state change of a - * specific cable, not an entier set of cables of a - * extcon device. - * @obj: an empty extcon_specific_cable_nb object to be returned. + * specific cable, not an entier set of cables of a + * extcon device. + * @obj: an empty extcon_specific_cable_nb object to be returned. * @extcon_name: the name of extcon device. * if NULL, extcon_register_interest will register * every cable with the target cable_name given. * @cable_name: the target cable name. - * @nb: the notifier block to get notified. + * @nb: the notifier block to get notified. * * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets * the struct for you. @@ -487,7 +487,7 @@ EXPORT_SYMBOL_GPL(extcon_register_interest); /** * extcon_unregister_interest() - Unregister the notifier registered by - * extcon_register_interest(). + * extcon_register_interest(). * @obj: the extcon_specific_cable_nb object returned by * extcon_register_interest(). */ @@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(extcon_unregister_interest); /** * extcon_register_notifier() - Register a notifiee to get notified by - * any attach status changes from the extcon. + * any attach status changes from the extcon. * @edev: the extcon device. * @nb: a notifier block to be registered. * diff --git a/include/linux/extcon.h b/include/linux/extcon.h index fcb51c88319f..c2b652dde72c 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -51,10 +51,10 @@ enum extcon_cable_name { EXTCON_USB = 0, EXTCON_USB_HOST, - EXTCON_TA, /* Travel Adaptor */ + EXTCON_TA, /* Travel Adaptor */ EXTCON_FAST_CHARGER, EXTCON_SLOW_CHARGER, - EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */ + EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */ EXTCON_HDMI, EXTCON_MHL, EXTCON_DVI, @@ -76,8 +76,8 @@ struct extcon_cable; /** * struct extcon_dev - An extcon device represents one external connector. - * @name: The name of this extcon device. Parent device name is used - * if NULL. + * @name: The name of this extcon device. Parent device name is + * used if NULL. * @supported_cable: Array of supported cable names ending with NULL. * If supported_cable is NULL, cable name related APIs * are disabled. @@ -89,21 +89,21 @@ struct extcon_cable; * be attached simulataneously. {0x7, 0} is equivalent to * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there * can be no simultaneous connections. - * @print_name: An optional callback to override the method to print the - * name of the extcon device. + * @print_name: An optional callback to override the method to print the + * name of the extcon device. * @print_state: An optional callback to override the method to print the - * status of the extcon device. - * @dev: Device of this extcon. Do not provide at register-time. - * @state: Attach/detach state of this extcon. Do not provide at - * register-time - * @nh: Notifier for the state change events from this extcon - * @entry: To support list of extcon devices so that users can search - * for extcon devices based on the extcon name. + * status of the extcon device. + * @dev: Device of this extcon. Do not provide at register-time. + * @state: Attach/detach state of this extcon. Do not provide at + * register-time. + * @nh: Notifier for the state change events from this extcon + * @entry: To support list of extcon devices so that users can search + * for extcon devices based on the extcon name. * @lock: * @max_supported: Internal value to store the number of cables. * @extcon_dev_type: Device_type struct to provide attribute_groups * customized for each extcon device. - * @cables: Sysfs subdirectories. Each represents one cable. + * @cables: Sysfs subdirectories. Each represents one cable. * * In most cases, users only need to provide "User initializing data" of * this struct when registering an extcon. In some exceptional cases, @@ -111,26 +111,27 @@ struct extcon_cable; * are overwritten by register function. */ struct extcon_dev { - /* --- Optional user initializing data --- */ - const char *name; + /* Optional user initializing data */ + const char *name; const char **supported_cable; - const u32 *mutually_exclusive; + const u32 *mutually_exclusive; - /* --- Optional callbacks to override class functions --- */ + /* Optional callbacks to override class functions */ ssize_t (*print_name)(struct extcon_dev *edev, char *buf); ssize_t (*print_state)(struct extcon_dev *edev, char *buf); - /* --- Internal data. Please do not set. --- */ - struct device *dev; - u32 state; + /* Internal data. Please do not set. */ + struct device *dev; struct raw_notifier_head nh; struct list_head entry; - spinlock_t lock; /* could be called by irq handler */ int max_supported; + spinlock_t lock; /* could be called by irq handler */ + u32 state; /* /sys/class/extcon/.../cable.n/... */ struct device_type extcon_dev_type; struct extcon_cable *cables; + /* /sys/class/extcon/.../mutually_exclusive/... */ struct attribute_group attr_g_muex; struct attribute **attrs_muex; @@ -138,13 +139,13 @@ struct extcon_dev { }; /** - * struct extcon_cable - An internal data for each cable of extcon device. - * @edev: The extcon device + * struct extcon_cable - An internal data for each cable of extcon device. + * @edev: The extcon device * @cable_index: Index of this cable in the edev - * @attr_g: Attribute group for the cable - * @attr_name: "name" sysfs entry - * @attr_state: "state" sysfs entry - * @attrs: Array pointing to attr_name and attr_state for attr_g + * @attr_g: Attribute group for the cable + * @attr_name: "name" sysfs entry + * @attr_state: "state" sysfs entry + * @attrs: Array pointing to attr_name and attr_state for attr_g */ struct extcon_cable { struct extcon_dev *edev; @@ -159,11 +160,13 @@ struct extcon_cable { /** * struct extcon_specific_cable_nb - An internal data for - * extcon_register_interest(). - * @internal_nb: a notifier block bridging extcon notifier and cable notifier. - * @user_nb: user provided notifier block for events from a specific cable. + * extcon_register_interest(). + * @internal_nb: A notifier block bridging extcon notifier + * and cable notifier. + * @user_nb: user provided notifier block for events from + * a specific cable. * @cable_index: the target cable. - * @edev: the target extcon device. + * @edev: the target extcon device. * @previous_value: the saved previous event value. */ struct extcon_specific_cable_nb { diff --git a/include/linux/extcon/extcon-adc-jack.h b/include/linux/extcon/extcon-adc-jack.h index 20e9eef25d4c..9ca958c4e94c 100644 --- a/include/linux/extcon/extcon-adc-jack.h +++ b/include/linux/extcon/extcon-adc-jack.h @@ -20,10 +20,10 @@ /** * struct adc_jack_cond - condition to use an extcon state - * @state - the corresponding extcon state (if 0, this struct denotes - * the last adc_jack_cond element among the array) - * @min_adc - min adc value for this condition - * @max_adc - max adc value for this condition + * @state: the corresponding extcon state (if 0, this struct + * denotes the last adc_jack_cond element among the array) + * @min_adc: min adc value for this condition + * @max_adc: max adc value for this condition * * For example, if { .state = 0x3, .min_adc = 100, .max_adc = 200}, it means * that if ADC value is between (inclusive) 100 and 200, than the cable 0 and @@ -33,34 +33,34 @@ * because when no adc_jack_cond is met, state = 0 is automatically chosen. */ struct adc_jack_cond { - u32 state; /* extcon state value. 0 if invalid */ + u32 state; /* extcon state value. 0 if invalid */ u32 min_adc; u32 max_adc; }; /** * struct adc_jack_pdata - platform data for adc jack device. - * @name - name of the extcon device. If null, "adc-jack" is used. - * @consumer_channel - Unique name to identify the channel on the consumer - * side. This typically describes the channels used within - * the consumer. E.g. 'battery_voltage' - * @cable_names - array of cable names ending with null. - * @adc_contitions - array of struct adc_jack_cond conditions ending - * with .state = 0 entry. This describes how to decode - * adc values into extcon state. - * @irq_flags - irq flags used for the @irq - * @handling_delay_ms - in some devices, we need to read ADC value some - * milli-seconds after the interrupt occurs. You may - * describe such delays with @handling_delay_ms, which - * is rounded-off by jiffies. + * @name: name of the extcon device. If null, "adc-jack" is used. + * @consumer_channel: Unique name to identify the channel on the consumer + * side. This typically describes the channels used within + * the consumer. E.g. 'battery_voltage' + * @cable_names: array of cable names ending with null. + * @adc_contitions: array of struct adc_jack_cond conditions ending + * with .state = 0 entry. This describes how to decode + * adc values into extcon state. + * @irq_flags: irq flags used for the @irq + * @handling_delay_ms: in some devices, we need to read ADC value some + * milli-seconds after the interrupt occurs. You may + * describe such delays with @handling_delay_ms, which + * is rounded-off by jiffies. */ struct adc_jack_pdata { const char *name; const char *consumer_channel; - /* - * The last entry should be NULL - */ + + /* The last entry should be NULL */ const char **cable_names; + /* The last entry's state should be 0 */ struct adc_jack_cond *adc_conditions; diff --git a/include/linux/extcon/extcon-gpio.h b/include/linux/extcon/extcon-gpio.h index 2d8307f7d67d..4ce1aa7d29bd 100644 --- a/include/linux/extcon/extcon-gpio.h +++ b/include/linux/extcon/extcon-gpio.h @@ -25,14 +25,14 @@ /** * struct gpio_extcon_platform_data - A simple GPIO-controlled extcon device. - * @name The name of this GPIO extcon device. - * @gpio Corresponding GPIO. - * @debounce Debounce time for GPIO IRQ in ms. - * @irq_flags IRQ Flags (e.g., IRQF_TRIGGER_LOW). - * @state_on print_state is overriden with state_on if attached. If Null, - * default method of extcon class is used. - * @state_off print_state is overriden with state_on if detached. If Null, - * default method of extcon class is used. + * @name: The name of this GPIO extcon device. + * @gpio: Corresponding GPIO. + * @debounce: Debounce time for GPIO IRQ in ms. + * @irq_flags: IRQ Flags (e.g., IRQF_TRIGGER_LOW). + * @state_on: print_state is overriden with state_on if attached. + * If NULL, default method of extcon class is used. + * @state_off: print_state is overriden with state_on if detached. + * If NUll, default method of extcon class is used. * * Note that in order for state_on or state_off to be valid, both state_on * and state_off should be not NULL. If at least one of them is NULL, -- cgit From 5bfbdc9caa7e16b2a77a62a9f9a63b5693e23716 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 12 Sep 2013 08:49:54 +0900 Subject: extcon: gpio: Add support for active-low presence to detect pins This patch add 'gpio_active_low' field to 'struct gpio_extcon_data' to check whether gpio active state is 1(high) or 0(low). Signed-off-by: Guenter Roeck Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-gpio.c | 4 ++++ include/linux/extcon/extcon-gpio.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index cd7dbb60f60f..b02c670ef01d 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -34,6 +34,7 @@ struct gpio_extcon_data { struct extcon_dev edev; unsigned gpio; + bool gpio_active_low; const char *state_on; const char *state_off; int irq; @@ -49,6 +50,8 @@ static void gpio_extcon_work(struct work_struct *work) work); state = gpio_get_value(data->gpio); + if (data->gpio_active_low) + state = !state; extcon_set_state(&data->edev, state); } @@ -96,6 +99,7 @@ static int gpio_extcon_probe(struct platform_device *pdev) extcon_data->edev.name = pdata->name; extcon_data->gpio = pdata->gpio; + extcon_data->gpio_active_low = pdata->gpio_active_low; extcon_data->state_on = pdata->state_on; extcon_data->state_off = pdata->state_off; if (pdata->state_on && pdata->state_off) diff --git a/include/linux/extcon/extcon-gpio.h b/include/linux/extcon/extcon-gpio.h index 4ce1aa7d29bd..4195810f87fe 100644 --- a/include/linux/extcon/extcon-gpio.h +++ b/include/linux/extcon/extcon-gpio.h @@ -27,6 +27,9 @@ * struct gpio_extcon_platform_data - A simple GPIO-controlled extcon device. * @name: The name of this GPIO extcon device. * @gpio: Corresponding GPIO. + * @gpio_active_low: Boolean describing whether gpio active state is 1 or 0 + * If true, low state of gpio means active. + * If false, high state of gpio means active. * @debounce: Debounce time for GPIO IRQ in ms. * @irq_flags: IRQ Flags (e.g., IRQF_TRIGGER_LOW). * @state_on: print_state is overriden with state_on if attached. @@ -41,6 +44,7 @@ struct gpio_extcon_platform_data { const char *name; unsigned gpio; + bool gpio_active_low; unsigned long debounce; unsigned long irq_flags; -- cgit From dae616512476024aa61d2a598461ab6eff8c0709 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 27 Sep 2013 09:19:40 +0900 Subject: extcon: Change field type of 'dev' in extcon_dev structure The extcon device must always need 'struct device' so this patch change field type of 'dev' instead of allocating memory for 'struct device' on extcon_dev_register() function. Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham --- drivers/extcon/extcon-adc-jack.c | 2 +- drivers/extcon/extcon-class.c | 52 ++++++++++++++++++---------------------- include/linux/extcon.h | 4 ++-- 3 files changed, 26 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 5694c468b958..dcbade667d0c 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -64,7 +64,7 @@ static void adc_jack_handler(struct work_struct *work) ret = iio_read_channel_raw(data->chan, &adc_val); if (ret < 0) { - dev_err(data->edev.dev, "read channel() error: %d\n", ret); + dev_err(&data->edev.dev, "read channel() error: %d\n", ret); return; } diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 2f2d374ccd1d..2801c14d5232 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -162,7 +162,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, return ret; } - return sprintf(buf, "%s\n", dev_name(edev->dev)); + return sprintf(buf, "%s\n", dev_name(&edev->dev)); } static DEVICE_ATTR_RO(name); @@ -230,7 +230,7 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (prop_buf) { - length = name_show(edev->dev, NULL, prop_buf); + length = name_show(&edev->dev, NULL, prop_buf); if (length > 0) { if (prop_buf[length - 1] == '\n') prop_buf[length - 1] = 0; @@ -238,7 +238,7 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) "NAME=%s", prop_buf); envp[env_offset++] = name_buf; } - length = state_show(edev->dev, NULL, prop_buf); + length = state_show(&edev->dev, NULL, prop_buf); if (length > 0) { if (prop_buf[length - 1] == '\n') prop_buf[length - 1] = 0; @@ -250,14 +250,14 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) /* Unlock early before uevent */ spin_unlock_irqrestore(&edev->lock, flags); - kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp); + kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp); free_page((unsigned long)prop_buf); } else { /* Unlock early before uevent */ spin_unlock_irqrestore(&edev->lock, flags); - dev_err(edev->dev, "out of memory in extcon_set_state\n"); - kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE); + dev_err(&edev->dev, "out of memory in extcon_set_state\n"); + kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE); } } else { /* No changes */ @@ -556,7 +556,6 @@ static int create_extcon_class(void) static void extcon_dev_release(struct device *dev) { - kfree(dev); } static const char *muex_name = "mutually_exclusive"; @@ -594,19 +593,16 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) } if (index > SUPPORTED_CABLE_MAX) { - dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n"); + dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n"); return -EINVAL; } - edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL); - if (!edev->dev) - return -ENOMEM; - edev->dev->parent = dev; - edev->dev->class = extcon_class; - edev->dev->release = extcon_dev_release; + edev->dev.parent = dev; + edev->dev.class = extcon_class; + edev->dev.release = extcon_dev_release; edev->name = edev->name ? edev->name : dev_name(dev); - dev_set_name(edev->dev, "%s", edev->name); + dev_set_name(&edev->dev, "%s", edev->name); if (edev->max_supported) { char buf[10]; @@ -714,7 +710,7 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) goto err_alloc_groups; } - edev->extcon_dev_type.name = dev_name(edev->dev); + edev->extcon_dev_type.name = dev_name(&edev->dev); edev->extcon_dev_type.release = dummy_sysfs_dev_release; for (index = 0; index < edev->max_supported; index++) @@ -724,25 +720,24 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) edev->extcon_dev_type.groups[index] = &edev->attr_g_muex; - edev->dev->type = &edev->extcon_dev_type; + edev->dev.type = &edev->extcon_dev_type; } - ret = device_register(edev->dev); + ret = device_register(&edev->dev); if (ret) { - put_device(edev->dev); + put_device(&edev->dev); goto err_dev; } #if defined(CONFIG_ANDROID) if (switch_class) - ret = class_compat_create_link(switch_class, edev->dev, - NULL); + ret = class_compat_create_link(switch_class, &edev->dev, NULL); #endif /* CONFIG_ANDROID */ spin_lock_init(&edev->lock); RAW_INIT_NOTIFIER_HEAD(&edev->nh); - dev_set_drvdata(edev->dev, edev); + dev_set_drvdata(&edev->dev, edev); edev->state = 0; mutex_lock(&extcon_dev_list_lock); @@ -768,7 +763,6 @@ err_alloc_cables: if (edev->max_supported) kfree(edev->cables); err_sysfs_alloc: - kfree(edev->dev); return ret; } EXPORT_SYMBOL_GPL(extcon_dev_register); @@ -788,9 +782,9 @@ void extcon_dev_unregister(struct extcon_dev *edev) list_del(&edev->entry); mutex_unlock(&extcon_dev_list_lock); - if (IS_ERR_OR_NULL(get_device(edev->dev))) { - dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n", - dev_name(edev->dev)); + if (IS_ERR_OR_NULL(get_device(&edev->dev))) { + dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n", + dev_name(&edev->dev)); return; } @@ -812,10 +806,10 @@ void extcon_dev_unregister(struct extcon_dev *edev) #if defined(CONFIG_ANDROID) if (switch_class) - class_compat_remove_link(switch_class, edev->dev, NULL); + class_compat_remove_link(switch_class, &edev->dev, NULL); #endif - device_unregister(edev->dev); - put_device(edev->dev); + device_unregister(&edev->dev); + put_device(&edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); diff --git a/include/linux/extcon.h b/include/linux/extcon.h index c2b652dde72c..0269bafb0ee8 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -93,7 +93,7 @@ struct extcon_cable; * name of the extcon device. * @print_state: An optional callback to override the method to print the * status of the extcon device. - * @dev: Device of this extcon. Do not provide at register-time. + * @dev: Device of this extcon. * @state: Attach/detach state of this extcon. Do not provide at * register-time. * @nh: Notifier for the state change events from this extcon @@ -121,7 +121,7 @@ struct extcon_dev { ssize_t (*print_state)(struct extcon_dev *edev, char *buf); /* Internal data. Please do not set. */ - struct device *dev; + struct device dev; struct raw_notifier_head nh; struct list_head entry; int max_supported; -- cgit From 42d7d7539a7bcf1d493b989465283c464f4a0525 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 27 Sep 2013 09:20:26 +0900 Subject: extcon: Simplify extcon_dev_register() prototype by removing unnecessary parameter This patch remove extcon_dev_register()'s second parameter which means the pointer of parent device to simplify prototype of this function. So, if extcon device has the parent device, it should set the pointer of parent device to edev.dev.parent in extcon device driver instead of in extcon_dev_register(). Cc: Graeme Gregory Cc: Kishon Vijay Abraham I Cc: Charles Keepax Cc: Mark Brown Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham --- Documentation/extcon/porting-android-switch-class | 6 ++++-- drivers/extcon/extcon-adc-jack.c | 3 ++- drivers/extcon/extcon-arizona.c | 3 ++- drivers/extcon/extcon-class.c | 11 +++++++---- drivers/extcon/extcon-gpio.c | 3 ++- drivers/extcon/extcon-max77693.c | 3 ++- drivers/extcon/extcon-max8997.c | 3 ++- drivers/extcon/extcon-palmas.c | 3 ++- include/linux/extcon.h | 5 ++--- 9 files changed, 25 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/Documentation/extcon/porting-android-switch-class b/Documentation/extcon/porting-android-switch-class index eb0fa5f4fe88..5377f6317961 100644 --- a/Documentation/extcon/porting-android-switch-class +++ b/Documentation/extcon/porting-android-switch-class @@ -25,8 +25,10 @@ MyungJoo Ham @print_state: no change but type change (switch_dev->extcon_dev) - switch_dev_register(sdev, dev) - => extcon_dev_register(edev, dev) - : no change but type change (sdev->edev) + => extcon_dev_register(edev) + : type change (sdev->edev) + : remove second param('dev'). if edev has parent device, should store + 'dev' to 'edev.dev.parent' before registering extcon device - switch_dev_unregister(sdev) => extcon_dev_unregister(edev) : no change but type change (sdev->edev) diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index dcbade667d0c..e23f1c2e5053 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -110,6 +110,7 @@ static int adc_jack_probe(struct platform_device *pdev) goto out; } + data->edev.dev.parent = &pdev->dev; data->edev.supported_cable = pdata->cable_names; /* Check the length of array and set num_cables */ @@ -148,7 +149,7 @@ static int adc_jack_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - err = extcon_dev_register(&data->edev, &pdev->dev); + err = extcon_dev_register(&data->edev); if (err) goto out; diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index e54ce08f669c..ec9a14e05fdd 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1130,9 +1130,10 @@ static int arizona_extcon_probe(struct platform_device *pdev) } info->edev.name = "Headset Jack"; + info->edev.dev.parent = arizona->dev; info->edev.supported_cable = arizona_cable; - ret = extcon_dev_register(&info->edev, arizona->dev); + ret = extcon_dev_register(&info->edev); if (ret < 0) { dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", ret); diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 2801c14d5232..84902d3fee11 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -566,14 +566,13 @@ static void dummy_sysfs_dev_release(struct device *dev) /** * extcon_dev_register() - Register a new extcon device * @edev : the new extcon device (should be allocated before calling) - * @dev : the parent device for this extcon device. * * Among the members of edev struct, please set the "user initializing data" * in any case and set the "optional callbacks" if required. However, please * do not set the values of "internal data", which are initialized by * this function. */ -int extcon_dev_register(struct extcon_dev *edev, struct device *dev) +int extcon_dev_register(struct extcon_dev *edev) { int ret, index = 0; @@ -597,11 +596,15 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) return -EINVAL; } - edev->dev.parent = dev; edev->dev.class = extcon_class; edev->dev.release = extcon_dev_release; - edev->name = edev->name ? edev->name : dev_name(dev); + edev->name = edev->name ? edev->name : dev_name(edev->dev.parent); + if (IS_ERR_OR_NULL(edev->name)) { + dev_err(&edev->dev, + "extcon device name is null\n"); + return -EINVAL; + } dev_set_name(&edev->dev, "%s", edev->name); if (edev->max_supported) { diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index b02c670ef01d..7e0dff58e494 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -98,6 +98,7 @@ static int gpio_extcon_probe(struct platform_device *pdev) return -ENOMEM; extcon_data->edev.name = pdata->name; + extcon_data->edev.dev.parent = &pdev->dev; extcon_data->gpio = pdata->gpio; extcon_data->gpio_active_low = pdata->gpio_active_low; extcon_data->state_on = pdata->state_on; @@ -112,7 +113,7 @@ static int gpio_extcon_probe(struct platform_device *pdev) msecs_to_jiffies(pdata->debounce); } - ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); + ret = extcon_dev_register(&extcon_data->edev); if (ret < 0) return ret; diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 4849ea1e92f6..ab9bc24e1a52 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -1171,8 +1171,9 @@ static int max77693_muic_probe(struct platform_device *pdev) goto err_irq; } info->edev->name = DEV_NAME; + info->edev->dev.parent = &pdev->dev; info->edev->supported_cable = max77693_extcon_cable; - ret = extcon_dev_register(info->edev, NULL); + ret = extcon_dev_register(info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); goto err_irq; diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index e55ec38b4148..0b1cbb5fdf9e 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -705,8 +705,9 @@ static int max8997_muic_probe(struct platform_device *pdev) goto err_irq; } info->edev->name = DEV_NAME; + info->edev->dev.parent = &pdev->dev; info->edev->supported_cable = max8997_extcon_cable; - ret = extcon_dev_register(info->edev, NULL); + ret = extcon_dev_register(info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); goto err_irq; diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 0c2fb68fb791..6c91976dd823 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -178,9 +178,10 @@ static int palmas_usb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, palmas_usb); palmas_usb->edev.supported_cable = palmas_extcon_cable; + palmas_usb->edev.dev.parent = palmas_usb->dev; palmas_usb->edev.mutually_exclusive = mutually_exclusive; - status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev); + status = extcon_dev_register(&palmas_usb->edev); if (status) { dev_err(&pdev->dev, "failed to register extcon device\n"); return status; diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 0269bafb0ee8..21c59af1150b 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -183,7 +183,7 @@ struct extcon_specific_cable_nb { * Following APIs are for notifiers or configurations. * Notifiers are the external port and connection devices. */ -extern int extcon_dev_register(struct extcon_dev *edev, struct device *dev); +extern int extcon_dev_register(struct extcon_dev *edev); extern void extcon_dev_unregister(struct extcon_dev *edev); extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); @@ -241,8 +241,7 @@ extern int extcon_register_notifier(struct extcon_dev *edev, extern int extcon_unregister_notifier(struct extcon_dev *edev, struct notifier_block *nb); #else /* CONFIG_EXTCON */ -static inline int extcon_dev_register(struct extcon_dev *edev, - struct device *dev) +static inline int extcon_dev_register(struct extcon_dev *edev) { return 0; } -- cgit From 8af2c2869fd129bce0d0dfd86c6364c1096f9eff Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 28 Mar 2013 22:53:42 +0800 Subject: video: atmel_lcdfb: fix platform data struct Today we mix pdata and drivers data in the struct atmel_lcdfb_info Fix it and introduce a new struct atmel_lcdfb_pdata for platform data only Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Tomi Valkeinen --- arch/arm/mach-at91/at91sam9261_devices.c | 6 +- arch/arm/mach-at91/at91sam9263_devices.c | 6 +- arch/arm/mach-at91/at91sam9g45_devices.c | 6 +- arch/arm/mach-at91/at91sam9rl_devices.c | 6 +- arch/arm/mach-at91/board-sam9261ek.c | 6 +- arch/arm/mach-at91/board-sam9263ek.c | 4 +- arch/arm/mach-at91/board-sam9m10g45ek.c | 4 +- arch/arm/mach-at91/board-sam9rlek.c | 4 +- arch/arm/mach-at91/board.h | 4 +- arch/avr32/boards/atngw100/evklcd10x.c | 6 +- arch/avr32/boards/atngw100/mrmt.c | 4 +- arch/avr32/boards/atstk1000/atstk1000.h | 2 +- arch/avr32/boards/atstk1000/setup.c | 2 +- arch/avr32/boards/favr-32/setup.c | 2 +- arch/avr32/boards/hammerhead/setup.c | 2 +- arch/avr32/boards/merisc/display.c | 2 +- arch/avr32/boards/mimc200/setup.c | 4 +- arch/avr32/mach-at32ap/at32ap700x.c | 8 +-- arch/avr32/mach-at32ap/include/mach/board.h | 4 +- drivers/video/atmel_lcdfb.c | 105 ++++++++++++++++++---------- include/video/atmel_lcdc.h | 23 +----- 21 files changed, 109 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 629ea5fc95cf..b2a34740146a 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -465,7 +465,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) static u64 lcdc_dmamask = DMA_BIT_MASK(32); -static struct atmel_lcdfb_info lcdc_data; +static struct atmel_lcdfb_pdata lcdc_data; static struct resource lcdc_resources[] = { [0] = { @@ -498,7 +498,7 @@ static struct platform_device at91_lcdc_device = { .num_resources = ARRAY_SIZE(lcdc_resources), }; -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) { if (!data) { return; @@ -559,7 +559,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) platform_device_register(&at91_lcdc_device); } #else -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 858c8aac2daf..4aeadddbc181 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -832,7 +832,7 @@ void __init at91_add_device_can(struct at91_can_data *data) {} #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) static u64 lcdc_dmamask = DMA_BIT_MASK(32); -static struct atmel_lcdfb_info lcdc_data; +static struct atmel_lcdfb_pdata lcdc_data; static struct resource lcdc_resources[] = { [0] = { @@ -859,7 +859,7 @@ static struct platform_device at91_lcdc_device = { .num_resources = ARRAY_SIZE(lcdc_resources), }; -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) { if (!data) return; @@ -891,7 +891,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) platform_device_register(&at91_lcdc_device); } #else -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index acb703e13331..cb36fa872d30 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -965,7 +965,7 @@ void __init at91_add_device_isi(struct isi_platform_data *data, #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) static u64 lcdc_dmamask = DMA_BIT_MASK(32); -static struct atmel_lcdfb_info lcdc_data; +static struct atmel_lcdfb_pdata lcdc_data; static struct resource lcdc_resources[] = { [0] = { @@ -991,7 +991,7 @@ static struct platform_device at91_lcdc_device = { .num_resources = ARRAY_SIZE(lcdc_resources), }; -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) { if (!data) return; @@ -1037,7 +1037,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) platform_device_register(&at91_lcdc_device); } #else -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 352468f265a9..a698bdab2cce 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -498,7 +498,7 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) static u64 lcdc_dmamask = DMA_BIT_MASK(32); -static struct atmel_lcdfb_info lcdc_data; +static struct atmel_lcdfb_pdata lcdc_data; static struct resource lcdc_resources[] = { [0] = { @@ -525,7 +525,7 @@ static struct platform_device at91_lcdc_device = { .num_resources = ARRAY_SIZE(lcdc_resources), }; -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) { if (!data) { return; @@ -557,7 +557,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) platform_device_register(&at91_lcdc_device); } #else -void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} +void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {} #endif diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index d3437624ca4e..4ab1ba7557e4 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -401,7 +401,7 @@ static void at91_lcdc_stn_power_control(int on) } } -static struct atmel_lcdfb_info __initdata ek_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = { .default_bpp = 1, .default_dmacon = ATMEL_LCDC_DMAEN, .default_lcdcon2 = AT91SAM9261_DEFAULT_STN_LCDCON2, @@ -453,7 +453,7 @@ static void at91_lcdc_tft_power_control(int on) at91_set_gpio_value(AT91_PIN_PA12, 1); /* power down */ } -static struct atmel_lcdfb_info __initdata ek_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = { .lcdcon_is_backlight = true, .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN, @@ -465,7 +465,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { #endif #else -static struct atmel_lcdfb_info __initdata ek_lcdc_data; +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data; #endif diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 3284df05df14..0fdae3f1541d 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -281,7 +281,7 @@ static void at91_lcdc_power_control(int on) } /* Driver datas */ -static struct atmel_lcdfb_info __initdata ek_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = { .lcdcon_is_backlight = true, .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN, @@ -292,7 +292,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { }; #else -static struct atmel_lcdfb_info __initdata ek_lcdc_data; +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data; #endif diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 2a94896a1375..ef39078c8ce2 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -284,7 +284,7 @@ static struct fb_monspecs at91fb_default_monspecs = { | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) /* Driver datas */ -static struct atmel_lcdfb_info __initdata ek_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = { .lcdcon_is_backlight = true, .default_bpp = 32, .default_dmacon = ATMEL_LCDC_DMAEN, @@ -295,7 +295,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { }; #else -static struct atmel_lcdfb_info __initdata ek_lcdc_data; +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data; #endif diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index aa265dcf2128..b77d7a9febd8 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -179,7 +179,7 @@ static void at91_lcdc_power_control(int on) } /* Driver datas */ -static struct atmel_lcdfb_info __initdata ek_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = { .lcdcon_is_backlight = true, .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN, @@ -191,7 +191,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { }; #else -static struct atmel_lcdfb_info __initdata ek_lcdc_data; +static struct atmel_lcdfb_pdata __initdata ek_lcdc_data; #endif diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h index 4a234fb2ab3b..6c08b341167d 100644 --- a/arch/arm/mach-at91/board.h +++ b/arch/arm/mach-at91/board.h @@ -107,8 +107,8 @@ extern void __init at91_add_device_pwm(u32 mask); extern void __init at91_add_device_ssc(unsigned id, unsigned pins); /* LCD Controller */ -struct atmel_lcdfb_info; -extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data); +struct atmel_lcdfb_pdata; +extern void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data); /* AC97 */ extern void __init at91_add_device_ac97(struct ac97c_platform_data *data); diff --git a/arch/avr32/boards/atngw100/evklcd10x.c b/arch/avr32/boards/atngw100/evklcd10x.c index 20388750d564..dc4280413e9d 100644 --- a/arch/avr32/boards/atngw100/evklcd10x.c +++ b/arch/avr32/boards/atngw100/evklcd10x.c @@ -58,7 +58,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { .dclkmax = 28330000, }; -static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT @@ -96,7 +96,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { .dclkmax = 7000000, }; -static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT @@ -134,7 +134,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { .dclkmax = 6400000, }; -static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = { .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c index 7de083d19b7e..1ba09e4c02b1 100644 --- a/arch/avr32/boards/atngw100/mrmt.c +++ b/arch/avr32/boards/atngw100/mrmt.c @@ -83,7 +83,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = { .dclkmax = 9260000, }; -static struct atmel_lcdfb_info __initdata rmt_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { .default_bpp = 24, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT @@ -126,7 +126,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = { .dclkmax = 9260000, }; -static struct atmel_lcdfb_info __initdata rmt_lcdc_data = { +static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { .default_bpp = 24, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h index 9392d3252865..653cc09e536c 100644 --- a/arch/avr32/boards/atstk1000/atstk1000.h +++ b/arch/avr32/boards/atstk1000/atstk1000.h @@ -10,7 +10,7 @@ #ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H #define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H -extern struct atmel_lcdfb_info atstk1000_lcdc_data; +extern struct atmel_lcdfb_pdata atstk1000_lcdc_data; void atstk1000_setup_j2_leds(void); diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 2d6b560115d9..b6b88f5e0b43 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c @@ -55,7 +55,7 @@ static struct fb_monspecs __initdata atstk1000_default_monspecs = { .dclkmax = 30000000, }; -struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = { +struct atmel_lcdfb_pdata __initdata atstk1000_lcdc_data = { .default_bpp = 24, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c index 27bd6fbe21cb..7b1f2cd85400 100644 --- a/arch/avr32/boards/favr-32/setup.c +++ b/arch/avr32/boards/favr-32/setup.c @@ -125,7 +125,7 @@ static struct fb_monspecs __initdata favr32_default_monspecs = { .dclkmax = 28000000, }; -struct atmel_lcdfb_info __initdata favr32_lcdc_data = { +struct atmel_lcdfb_pdata __initdata favr32_lcdc_data = { .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c index 9d1efd1cd425..dc0e317f2ecd 100644 --- a/arch/avr32/boards/hammerhead/setup.c +++ b/arch/avr32/boards/hammerhead/setup.c @@ -77,7 +77,7 @@ static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = { .dclkmax = 10000000, }; -struct atmel_lcdfb_info __initdata hammerhead_lcdc_data = { +struct atmel_lcdfb_pdata __initdata hammerhead_lcdc_data = { .default_bpp = 24, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/merisc/display.c b/arch/avr32/boards/merisc/display.c index 85a543cd4abc..e7683ee7ed40 100644 --- a/arch/avr32/boards/merisc/display.c +++ b/arch/avr32/boards/merisc/display.c @@ -45,7 +45,7 @@ static struct fb_monspecs merisc_fb_monspecs = { .dclkmax = 30000000, }; -struct atmel_lcdfb_info merisc_lcdc_data = { +struct atmel_lcdfb_pdata merisc_lcdc_data = { .default_bpp = 24, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c index 05358aa5ef7d..1cb8e9cc5cfa 100644 --- a/arch/avr32/boards/mimc200/setup.c +++ b/arch/avr32/boards/mimc200/setup.c @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ -extern struct atmel_lcdfb_info mimc200_lcdc_data; +extern struct atmel_lcdfb_pdata mimc200_lcdc_data; #include #include @@ -71,7 +71,7 @@ static struct fb_monspecs __initdata mimc200_default_monspecs = { .dclkmax = 25200000, }; -struct atmel_lcdfb_info __initdata mimc200_lcdc_data = { +struct atmel_lcdfb_pdata __initdata mimc200_lcdc_data = { .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index a68f3cf7c3c1..a1f4d1e91b52 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1439,7 +1439,7 @@ fail: * LCDC * -------------------------------------------------------------------- */ #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002) -static struct atmel_lcdfb_info atmel_lcdfb0_data; +static struct atmel_lcdfb_pdata atmel_lcdfb0_data; static struct resource atmel_lcdfb0_resource[] = { { .start = 0xff000000, @@ -1467,12 +1467,12 @@ static struct clk atmel_lcdfb0_pixclk = { }; struct platform_device *__init -at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, +at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data, unsigned long fbmem_start, unsigned long fbmem_len, u64 pin_mask) { struct platform_device *pdev; - struct atmel_lcdfb_info *info; + struct atmel_lcdfb_pdata *info; struct fb_monspecs *monspecs; struct fb_videomode *modedb; unsigned int modedb_size; @@ -1529,7 +1529,7 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, } info = pdev->dev.platform_data; - memcpy(info, data, sizeof(struct atmel_lcdfb_info)); + memcpy(info, data, sizeof(struct atmel_lcdfb_pdata)); info->default_monspecs = monspecs; pdev->name = "at32ap-lcdfb"; diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index d485b0391357..f1a316d52c73 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -44,9 +44,9 @@ struct platform_device * at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); void at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n); -struct atmel_lcdfb_info; +struct atmel_lcdfb_pdata; struct platform_device * -at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, +at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data, unsigned long fbmem_start, unsigned long fbmem_len, u64 pin_mask); diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 3f7d6dc3408d..0d7214df1237 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -20,12 +20,44 @@ #include #include #include +#include