diff --git a/.gitignore b/.gitignore
index 27fd37621255..b1f5b9df2ae1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,11 @@ include/config
include/linux/autoconf.h
include/linux/compile.h
include/linux/version.h
+include/linux/utsrelease.h
# stgit generated dirs
patches-*
+
+# quilt's files
+patches
+series
diff --git a/CREDITS b/CREDITS
index 29be6d1fdf49..0fe904ebb7c7 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2209,7 +2209,7 @@ S: (address available on request)
S: USA
N: Ian McDonald
-E: iam4@cs.waikato.ac.nz
+E: ian.mcdonald@jandi.co.nz
E: imcdnzl@gmail.com
W: http://wand.net.nz/~iam4
W: http://imcdnzl.blogspot.com
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 1ae4dc0fd856..f8fe882e33dc 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -58,6 +58,9 @@
!Iinclude/linux/ktime.h
!Iinclude/linux/hrtimer.h
!Ekernel/hrtimer.c
+
+ Workqueues and Kevents
+!Ekernel/workqueue.c
Internal Functions
!Ikernel/exit.c
@@ -300,7 +303,7 @@ X!Ekernel/module.c
Resources Management
-!Ekernel/resource.c
+!Ikernel/resource.c
MTRR Handling
@@ -312,9 +315,7 @@ X!Ekernel/module.c
!Edrivers/pci/pci-driver.c
!Edrivers/pci/remove.c
!Edrivers/pci/pci-acpi.c
-
+!Edrivers/pci/search.c
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
no irq is pending */
- irq = -1;
+ return NO_IRQ;
- return irq;
+ return irq_linear_revmap(primary_ipic->irqhost, irq);
}
static struct sysdev_class ipic_sysclass = {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index a60c9d18bb7f..c28e589877eb 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -15,7 +15,18 @@
#include
-#define MPC83xx_IPIC_SIZE (0x00100)
+#define NR_IPIC_INTS 128
+
+/* External IRQS */
+#define IPIC_IRQ_EXT0 48
+#define IPIC_IRQ_EXT1 17
+#define IPIC_IRQ_EXT7 23
+
+/* Default Priority Registers */
+#define IPIC_SIPRR_A_DEFAULT 0x05309770
+#define IPIC_SIPRR_D_DEFAULT 0x05309770
+#define IPIC_SMPRR_A_DEFAULT 0x05309770
+#define IPIC_SMPRR_B_DEFAULT 0x05309770
/* System Global Interrupt Configuration Register */
#define SICFR_IPSA 0x00010000
@@ -31,7 +42,15 @@
struct ipic {
volatile u32 __iomem *regs;
- unsigned int irq_offset;
+
+ /* The remapper for this IPIC */
+ struct irq_host *irqhost;
+
+ /* The "linux" controller struct */
+ struct irq_chip hc_irq;
+
+ /* The device node of the interrupt controller */
+ struct device_node *of_node;
};
struct ipic_info {
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6e0281afa6c3..b604926401f5 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock);
#endif
#endif
+#ifdef CONFIG_MPIC_WEIRD
+static u32 mpic_infos[][MPIC_IDX_END] = {
+ [0] = { /* Original OpenPIC compatible MPIC */
+ MPIC_GREG_BASE,
+ MPIC_GREG_FEATURE_0,
+ MPIC_GREG_GLOBAL_CONF_0,
+ MPIC_GREG_VENDOR_ID,
+ MPIC_GREG_IPI_VECTOR_PRI_0,
+ MPIC_GREG_IPI_STRIDE,
+ MPIC_GREG_SPURIOUS,
+ MPIC_GREG_TIMER_FREQ,
+
+ MPIC_TIMER_BASE,
+ MPIC_TIMER_STRIDE,
+ MPIC_TIMER_CURRENT_CNT,
+ MPIC_TIMER_BASE_CNT,
+ MPIC_TIMER_VECTOR_PRI,
+ MPIC_TIMER_DESTINATION,
+
+ MPIC_CPU_BASE,
+ MPIC_CPU_STRIDE,
+ MPIC_CPU_IPI_DISPATCH_0,
+ MPIC_CPU_IPI_DISPATCH_STRIDE,
+ MPIC_CPU_CURRENT_TASK_PRI,
+ MPIC_CPU_WHOAMI,
+ MPIC_CPU_INTACK,
+ MPIC_CPU_EOI,
+
+ MPIC_IRQ_BASE,
+ MPIC_IRQ_STRIDE,
+ MPIC_IRQ_VECTOR_PRI,
+ MPIC_VECPRI_VECTOR_MASK,
+ MPIC_VECPRI_POLARITY_POSITIVE,
+ MPIC_VECPRI_POLARITY_NEGATIVE,
+ MPIC_VECPRI_SENSE_LEVEL,
+ MPIC_VECPRI_SENSE_EDGE,
+ MPIC_VECPRI_POLARITY_MASK,
+ MPIC_VECPRI_SENSE_MASK,
+ MPIC_IRQ_DESTINATION
+ },
+ [1] = { /* Tsi108/109 PIC */
+ TSI108_GREG_BASE,
+ TSI108_GREG_FEATURE_0,
+ TSI108_GREG_GLOBAL_CONF_0,
+ TSI108_GREG_VENDOR_ID,
+ TSI108_GREG_IPI_VECTOR_PRI_0,
+ TSI108_GREG_IPI_STRIDE,
+ TSI108_GREG_SPURIOUS,
+ TSI108_GREG_TIMER_FREQ,
+
+ TSI108_TIMER_BASE,
+ TSI108_TIMER_STRIDE,
+ TSI108_TIMER_CURRENT_CNT,
+ TSI108_TIMER_BASE_CNT,
+ TSI108_TIMER_VECTOR_PRI,
+ TSI108_TIMER_DESTINATION,
+
+ TSI108_CPU_BASE,
+ TSI108_CPU_STRIDE,
+ TSI108_CPU_IPI_DISPATCH_0,
+ TSI108_CPU_IPI_DISPATCH_STRIDE,
+ TSI108_CPU_CURRENT_TASK_PRI,
+ TSI108_CPU_WHOAMI,
+ TSI108_CPU_INTACK,
+ TSI108_CPU_EOI,
+
+ TSI108_IRQ_BASE,
+ TSI108_IRQ_STRIDE,
+ TSI108_IRQ_VECTOR_PRI,
+ TSI108_VECPRI_VECTOR_MASK,
+ TSI108_VECPRI_POLARITY_POSITIVE,
+ TSI108_VECPRI_POLARITY_NEGATIVE,
+ TSI108_VECPRI_SENSE_LEVEL,
+ TSI108_VECPRI_SENSE_EDGE,
+ TSI108_VECPRI_POLARITY_MASK,
+ TSI108_VECPRI_SENSE_MASK,
+ TSI108_IRQ_DESTINATION
+ },
+};
+
+#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
+
+#else /* CONFIG_MPIC_WEIRD */
+
+#define MPIC_INFO(name) MPIC_##name
+
+#endif /* CONFIG_MPIC_WEIRD */
+
/*
* Register accessor functions
*/
@@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
{
unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+ (ipi * MPIC_INFO(GREG_IPI_STRIDE));
if (mpic->flags & MPIC_BROKEN_IPI)
be = !be;
@@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
{
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+ (ipi * MPIC_INFO(GREG_IPI_STRIDE));
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
}
@@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
unsigned int idx = src_no & mpic->isu_mask;
return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
- reg + (idx * MPIC_IRQ_STRIDE));
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)));
}
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
unsigned int idx = src_no & mpic->isu_mask;
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
- reg + (idx * MPIC_IRQ_STRIDE), value);
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
}
#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
@@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
{
u32 r;
- mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
- r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
+ r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
@@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq)
/* Send an EOI */
static inline void mpic_eoi(struct mpic *mpic)
{
- mpic_cpu_write(MPIC_CPU_EOI, 0);
- (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+ mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
+ (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
}
#ifdef CONFIG_SMP
@@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq)
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+ mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
~MPIC_VECPRI_MASK);
/* make sure mask gets to controller before we return to user */
do {
@@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq)
printk(KERN_ERR "mpic_enable_irq timeout\n");
break;
}
- } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+ } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
}
static void mpic_mask_irq(unsigned int irq)
@@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq)
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+ mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
MPIC_VECPRI_MASK);
/* make sure mask gets to controller before we return to user */
@@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq)
printk(KERN_ERR "mpic_enable_irq timeout\n");
break;
}
- } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+ } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
}
static void mpic_end_irq(unsigned int irq)
@@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
cpus_and(tmp, cpumask, cpu_online_map);
- mpic_irq_write(src, MPIC_IRQ_DESTINATION,
+ mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
mpic_physmask(cpus_addr(tmp)[0]));
}
-static unsigned int mpic_type_to_vecpri(unsigned int type)
+static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
{
/* Now convert sense value */
switch(type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
- return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
+ return MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE);
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_EDGE_BOTH:
- return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
+ return MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
case IRQ_TYPE_LEVEL_HIGH:
- return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
+ return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE);
case IRQ_TYPE_LEVEL_LOW:
default:
- return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
+ return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
}
}
@@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
MPIC_VECPRI_SENSE_EDGE;
else
- vecpri = mpic_type_to_vecpri(flow_type);
+ vecpri = mpic_type_to_vecpri(mpic, flow_type);
- vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
- vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
+ vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+ vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
+ MPIC_INFO(VECPRI_SENSE_MASK));
vnew |= vecpri;
if (vold != vnew)
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
return 0;
}
@@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->irq_count = irq_count;
mpic->num_sources = 0; /* so far */
+#ifdef CONFIG_MPIC_WEIRD
+ mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
+#endif
+
/* Map the global registers */
- mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
- mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+ mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000);
+ mpic->tmregs = mpic->gregs +
+ ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
BUG_ON(mpic->gregs == NULL);
/* Reset */
if (flags & MPIC_WANTS_RESET) {
- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
| MPIC_GREG_GCONF_RESET);
- while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+ while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
& MPIC_GREG_GCONF_RESET)
mb();
}
@@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
* MPICs, num sources as well. On ISU MPICs, sources are counted
* as ISUs are added
*/
- reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+ reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
>> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
if (isu_size == 0)
@@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
/* Map the per-CPU registers */
for (i = 0; i < mpic->num_cpus; i++) {
- mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
- i * MPIC_CPU_STRIDE, 0x1000);
+ mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) +
+ i * MPIC_INFO(CPU_STRIDE), 0x1000);
BUG_ON(mpic->cpuregs[i] == NULL);
}
/* Initialize main ISU if none provided */
if (mpic->isu_size == 0) {
mpic->isu_size = mpic->num_sources;
- mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
- MPIC_IRQ_STRIDE * mpic->isu_size);
+ mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE),
+ MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
BUG_ON(mpic->isus[0] == NULL);
}
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
BUG_ON(isu_num >= MPIC_MAX_ISU);
- mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+ mpic->isus[isu_num] = ioremap(phys_addr,
+ MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
if ((isu_first + mpic->isu_size) > mpic->num_sources)
mpic->num_sources = isu_first + mpic->isu_size;
}
@@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic)
printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
/* Set current processor priority to max */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
/* Initialize timers: just disable them all */
for (i = 0; i < 4; i++) {
mpic_write(mpic->tmregs,
- i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+ i * MPIC_INFO(TIMER_STRIDE) +
+ MPIC_INFO(TIMER_DESTINATION), 0);
mpic_write(mpic->tmregs,
- i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+ i * MPIC_INFO(TIMER_STRIDE) +
+ MPIC_INFO(TIMER_VECTOR_PRI),
MPIC_VECPRI_MASK |
(MPIC_VEC_TIMER_0 + i));
}
@@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic)
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
/* init hw */
- mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+ mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
1 << hard_smp_processor_id());
}
/* Init spurrious vector */
- mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS);
- /* Disable 8259 passthrough */
- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
- | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+ /* Disable 8259 passthrough, if supported */
+ if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | MPIC_GREG_GCONF_8259_PTHROU_DIS);
/* Set current processor priority to 0 */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
mpic_ipi_write(src - MPIC_VEC_IPI_0,
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
} else {
- reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
+ reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
& ~MPIC_VECPRI_PRIORITY_MASK;
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
}
spin_unlock_irqrestore(&mpic_lock, flags);
@@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
if (is_ipi)
reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
else
- reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
+ reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
spin_unlock_irqrestore(&mpic_lock, flags);
return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
}
@@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void)
*/
if (distribute_irqs) {
for (i = 0; i < mpic->num_sources ; i++)
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
- mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+ mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
}
/* Set current processor priority to 0 */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
spin_unlock_irqrestore(&mpic_lock, flags);
#endif /* CONFIG_SMP */
@@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void)
{
struct mpic *mpic = mpic_primary;
- return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+ return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
}
void mpic_cpu_set_priority(int prio)
@@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio)
struct mpic *mpic = mpic_primary;
prio &= MPIC_CPU_TASKPRI_MASK;
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
}
/*
@@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary)
/* let the mpic know we don't want intrs. */
for (i = 0; i < mpic->num_sources ; i++)
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
- mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+ mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
/* Set current processor priority to max */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
spin_unlock_irqrestore(&mpic_lock, flags);
}
@@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
#endif
- mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+ mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
+ ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
}
@@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
{
u32 src;
- src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+ src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
#ifdef DEBUG_LOW
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
#endif
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 26a0cc820cde..f3038461d4c0 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -93,13 +93,15 @@ static int __init tsi108_eth_of_init(void)
goto err;
r[1].name = "tx";
- r[1].start = np->intrs[0].line;
- r[1].end = np->intrs[0].line;
+ r[1].start = irq_of_parse_and_map(np, 0);
+ r[1].end = irq_of_parse_and_map(np, 0);
r[1].flags = IORESOURCE_IRQ;
+ DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+ __FUNCTION__,r[1].name, r[1].start, r[1].end);
tsi_eth_dev =
platform_device_register_simple("tsi-ethernet", i, &r[0],
- np->n_intrs + 1);
+ 1);
if (IS_ERR(tsi_eth_dev)) {
ret = PTR_ERR(tsi_eth_dev);
@@ -127,7 +129,7 @@ static int __init tsi108_eth_of_init(void)
tsi_eth_data.regs = r[0].start;
tsi_eth_data.phyregs = res.start;
tsi_eth_data.phy = *phy_id;
- tsi_eth_data.irq_num = np->intrs[0].line;
+ tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
of_node_put(phy);
ret =
platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 3265d54c82ed..2ab06ed3ae73 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -26,7 +26,6 @@
#include
#include
-
#include
#include
#include
@@ -228,7 +227,7 @@ int __init tsi108_setup_pci(struct device_node *dev)
(hose)->ops = &tsi108_direct_pci_ops;
- printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. "
+ printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. "
"Firmware bus number: %d->%d\n",
rsrc.start, hose->first_busno, hose->last_busno);
@@ -278,7 +277,7 @@ static void init_pci_source(void)
mb();
}
-static inline int get_pci_source(void)
+static inline unsigned int get_pci_source(void)
{
u_int temp = 0;
int irq = -1;
@@ -371,12 +370,12 @@ static void tsi108_pci_irq_end(u_int irq)
* Interrupt controller descriptor for cascaded PCI interrupt controller.
*/
-struct hw_interrupt_type tsi108_pci_irq = {
+static struct irq_chip tsi108_pci_irq = {
.typename = "tsi108_PCI_int",
- .enable = tsi108_pci_irq_enable,
- .disable = tsi108_pci_irq_disable,
+ .mask = tsi108_pci_irq_disable,
.ack = tsi108_pci_irq_ack,
.end = tsi108_pci_irq_end,
+ .unmask = tsi108_pci_irq_enable,
};
/*
@@ -399,14 +398,18 @@ void __init tsi108_pci_int_init(void)
DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
for (i = 0; i < NUM_PCI_IRQS; i++) {
- irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
+ irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq;
irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
}
init_pci_source();
}
-int tsi108_irq_cascade(struct pt_regs *regs, void *unused)
+void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
+ struct pt_regs *regs)
{
- return get_pci_source();
+ unsigned int cascade_irq = get_pci_source();
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq, regs);
+ desc->chip->eoi(irq);
}
diff --git a/arch/ppc/kernel/smp-tbsync.c b/arch/ppc/kernel/smp-tbsync.c
index 1576758debaf..d0cf3f86931d 100644
--- a/arch/ppc/kernel/smp-tbsync.c
+++ b/arch/ppc/kernel/smp-tbsync.c
@@ -47,8 +47,9 @@ void __devinit
smp_generic_take_timebase( void )
{
int cmd, tbl, tbu;
+ unsigned long flags;
- local_irq_disable();
+ local_irq_save(flags);
while( !running )
;
rmb();
@@ -64,7 +65,7 @@ smp_generic_take_timebase( void )
tbu = tbsync->tbu;
tbsync->ack = 0;
if( cmd == kExit )
- return;
+ break;
if( cmd == kSetAndTest ) {
while( tbsync->handshake )
@@ -77,7 +78,7 @@ smp_generic_take_timebase( void )
}
enter_contest( tbsync->mark, -1 );
}
- local_irq_enable();
+ local_irq_restore(flags);
}
static int __devinit
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 09c6525cfa61..095fd3323323 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -8,6 +8,7 @@ SECTIONS
. = + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) }
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index d90cd24d018e..94badafe4ef1 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
#include
@@ -58,6 +59,71 @@
* Setup the architecture
*
*/
+static void init_fcc_ioports(void)
+{
+ struct immap *immap;
+ struct io_port *io;
+ u32 tempval;
+
+ immap = cpm2_immr;
+
+ io = &immap->im_ioport;
+ /* FCC2/3 are on the ports B/C. */
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB2_DIRB0;
+ tempval |= PB2_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB2_PSORB0;
+ tempval |= PB2_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB2_DIRB0 | PB2_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB3_DIRB0;
+ tempval |= PB3_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB3_PSORB0;
+ tempval |= PB3_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB3_DIRB0 | PB3_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ tempval = in_be32(&io->iop_pdirc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pdirc, tempval);
+
+ tempval = in_be32(&io->iop_pparc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pparc, tempval);
+
+ /* Port C has clocks...... */
+ tempval = in_be32(&io->iop_psorc);
+ tempval &= ~(CLK_TRX);
+ out_be32(&io->iop_psorc, tempval);
+
+ tempval = in_be32(&io->iop_pdirc);
+ tempval &= ~(CLK_TRX);
+ out_be32(&io->iop_pdirc, tempval);
+ tempval = in_be32(&io->iop_pparc);
+ tempval |= (CLK_TRX);
+ out_be32(&io->iop_pparc, tempval);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all FCC bits to zero,
+ * then set the ones we want.
+ */
+ immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
+ immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
+}
static void __init
mpc8560ads_setup_arch(void)
@@ -66,6 +132,7 @@ mpc8560ads_setup_arch(void)
unsigned int freq;
struct gianfar_platform_data *pdata;
struct gianfar_mdio_data *mdata;
+ struct fs_platform_info *fpi;
cpm2_reset();
@@ -110,6 +177,28 @@ mpc8560ads_setup_arch(void)
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
+ init_fcc_ioports();
+ ppc_sys_device_remove(MPC85xx_CPM_FCC1);
+
+ fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
+ if (fpi) {
+ memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+ fpi->bus_id = "0:02";
+ fpi->phy_addr = 2;
+ fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+ fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
+ }
+
+ fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
+ if (fpi) {
+ memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+ fpi->macaddr[5] += 1;
+ fpi->bus_id = "0:03";
+ fpi->phy_addr = 3;
+ fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+ fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
+ }
+
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
ROOT_DEV = Root_RAM0;
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
index abf32281655d..c8c322fe3680 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
@@ -45,4 +45,23 @@ extern void mpc85xx_ads_map_io(void) __init;
#define MPC85XX_PCI1_IO_SIZE 0x01000000
+/* FCC1 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK9-12 */
+#define F1_RXCLK 12
+#define F1_TXCLK 11
+
+/* FCC2 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK13-16 */
+#define F2_RXCLK 13
+#define F2_TXCLK 14
+
+/* FCC3 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK13-16 */
+#define F3_RXCLK 15
+#define F3_TXCLK 16
+
+
#endif /* __MACH_MPC85XX_ADS_H__ */
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index abb7154de2c7..2a35fe2b9b96 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -56,64 +56,51 @@ static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
},
};
-static struct fs_mii_bus_info mii_bus_info = {
- .method = fsmii_bitbang,
- .id = 0,
- .i.bitbang = {
- .mdio_port = fsiop_portc,
- .mdio_bit = 18,
- .mdc_port = fsiop_portc,
- .mdc_bit = 19,
- .delay = 1,
+static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
+ .mdio_dat.bit = 18,
+ .mdio_dir.bit = 18,
+ .mdc_dat.bit = 19,
+ .delay = 1,
+};
+
+static struct fs_platform_info mpc82xx_enet_pdata[] = {
+ [fsid_fcc1] = {
+ .fs_no = fsid_fcc1,
+ .cp_page = CPM_CR_FCC1_PAGE,
+ .cp_block = CPM_CR_FCC1_SBLOCK,
+
+ .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
+ .clk_route = CMX1_CLK_ROUTE,
+ .clk_mask = CMX1_CLK_MASK,
+ .init_ioports = init_fcc1_ioports,
+
+ .mem_offset = FCC1_MEM_OFFSET,
+
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+ .bus_id = "0:00",
},
-};
+ [fsid_fcc2] = {
+ .fs_no = fsid_fcc2,
+ .cp_page = CPM_CR_FCC2_PAGE,
+ .cp_block = CPM_CR_FCC2_SBLOCK,
+ .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
+ .clk_route = CMX2_CLK_ROUTE,
+ .clk_mask = CMX2_CLK_MASK,
+ .init_ioports = init_fcc2_ioports,
-static struct fs_platform_info mpc82xx_fcc1_pdata = {
- .fs_no = fsid_fcc1,
- .cp_page = CPM_CR_FCC1_PAGE,
- .cp_block = CPM_CR_FCC1_SBLOCK,
- .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
- .clk_route = CMX1_CLK_ROUTE,
- .clk_mask = CMX1_CLK_MASK,
- .init_ioports = init_fcc1_ioports,
+ .mem_offset = FCC2_MEM_OFFSET,
- .phy_addr = 0,
-#ifdef PHY_INTERRUPT
- .phy_irq = PHY_INTERRUPT,
-#else
- .phy_irq = -1;
-#endif
- .mem_offset = FCC1_MEM_OFFSET,
- .bus_info = &mii_bus_info,
- .rx_ring = 32,
- .tx_ring = 32,
- .rx_copybreak = 240,
- .use_napi = 0,
- .napi_weight = 17,
-};
-
-static struct fs_platform_info mpc82xx_fcc2_pdata = {
- .fs_no = fsid_fcc2,
- .cp_page = CPM_CR_FCC2_PAGE,
- .cp_block = CPM_CR_FCC2_SBLOCK,
- .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
- .clk_route = CMX2_CLK_ROUTE,
- .clk_mask = CMX2_CLK_MASK,
- .init_ioports = init_fcc2_ioports,
-
- .phy_addr = 3,
-#ifdef PHY_INTERRUPT
- .phy_irq = PHY_INTERRUPT,
-#else
- .phy_irq = -1;
-#endif
- .mem_offset = FCC2_MEM_OFFSET,
- .bus_info = &mii_bus_info,
- .rx_ring = 32,
- .tx_ring = 32,
- .rx_copybreak = 240,
- .use_napi = 0,
- .napi_weight = 17,
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+ .bus_id = "0:03",
+ },
};
static void init_fcc1_ioports(void)
@@ -209,20 +196,21 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
bd_t* bi = (void*)__res;
int fs_no = fsid_fcc1+pdev->id-1;
- mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
- mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
-
- switch(fs_no) {
- case fsid_fcc1:
- memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
- pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
- break;
- case fsid_fcc2:
- memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
- mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
- pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
- break;
+ if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
+ return;
}
+
+ mpc82xx_enet_pdata[fs_no].dpram_offset=
+ (u32)cpm2_immr->im_dprambase;
+ mpc82xx_enet_pdata[fs_no].fcc_regs_c =
+ (u32)cpm2_immr->im_fcc_c;
+ memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
+
+ /* prevent dup mac */
+ if(fs_no == fsid_fcc2)
+ mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
+
+ pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
}
static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
@@ -274,6 +262,29 @@ static void init_scc4_uart_ioports(void)
iounmap(immap);
}
+static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
+ int idx)
+{
+ m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
+ m82xx_mii_bb_pdata.irq[1] = -1;
+ m82xx_mii_bb_pdata.irq[2] = -1;
+ m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
+ m82xx_mii_bb_pdata.irq[31] = -1;
+
+
+ m82xx_mii_bb_pdata.mdio_dat.offset =
+ (u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+ m82xx_mii_bb_pdata.mdio_dir.offset =
+ (u32)&cpm2_immr->im_ioport.iop_pdirc;
+
+ m82xx_mii_bb_pdata.mdc_dat.offset =
+ (u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+
+ pdev->dev.platform_data = &m82xx_mii_bb_pdata;
+}
+
static int mpc8272ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -285,6 +296,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
.bus_id = "fsl-cpm-scc:uart",
.rtn = mpc8272ads_fixup_uart_pdata,
},
+ {
+ .bus_id = "fsl-bb-mdio",
+ .rtn = mpc8272ads_fixup_mdio_pdata,
+ },
{
.bus_id = NULL
}
@@ -319,6 +334,7 @@ int __init mpc8272ads_init(void)
ppc_sys_device_enable(MPC82xx_CPM_SCC4);
#endif
+ ppc_sys_device_enable(MPC82xx_MDIO_BB);
return 0;
}
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index f19b6167c770..e12cece4c9fd 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -1,10 +1,10 @@
-/*arch/ppc/platforms/mpc885ads-setup.c
+/*arch/ppc/platforms/mpc866ads-setup.c
*
- * Platform setup for the Freescale mpc885ads board
+ * Platform setup for the Freescale mpc866ads board
*
* Vitaly Bordug
*
- * Copyright 2005 MontaVista Software Inc.
+ * Copyright 2005-2006 MontaVista Software Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -42,49 +42,36 @@ static void setup_scc1_ioports(void);
static void setup_smc1_ioports(void);
static void setup_smc2_ioports(void);
-static struct fs_mii_bus_info fec_mii_bus_info = {
- .method = fsmii_fec,
- .id = 0,
-};
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
-static struct fs_mii_bus_info scc_mii_bus_info = {
- .method = fsmii_fixed,
- .id = 0,
- .i.fixed.speed = 10,
- .i.fixed.duplex = 0,
-};
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
- {
- .rx_ring = 128,
- .tx_ring = 16,
- .rx_copybreak = 240,
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+ [fsid_fec1] = {
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
- .use_napi = 1,
- .napi_weight = 17,
+ .use_napi = 1,
+ .napi_weight = 17,
- .phy_addr = 15,
- .phy_irq = -1,
+ .init_ioports = setup_fec1_ioports,
- .use_rmii = 0,
+ .bus_id = "0:0f",
+ .has_phy = 1,
+ },
+ [fsid_scc1] = {
+ .rx_ring = 64,
+ .tx_ring = 8,
+ .rx_copybreak = 240,
+ .use_napi = 1,
+ .napi_weight = 17,
- .bus_info = &fec_mii_bus_info,
- }
-};
-static struct fs_platform_info mpc8xx_scc_pdata = {
- .rx_ring = 64,
- .tx_ring = 8,
- .rx_copybreak = 240,
-
- .use_napi = 1,
- .napi_weight = 17,
-
- .phy_addr = -1,
- .phy_irq = -1,
-
- .bus_info = &scc_mii_bus_info,
+ .init_ioports = setup_scc1_ioports,
+ .bus_id = "fixed@100:1",
+ },
};
static struct fs_uart_platform_info mpc866_uart_pdata[] = {
@@ -207,63 +194,6 @@ static void setup_scc1_ioports(void)
}
-static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
-{
- struct fs_platform_info *fpi = pdev->dev.platform_data;
-
- volatile cpm8xx_t *cp;
- bd_t *bd = (bd_t *) __res;
- char *e;
- int i;
-
- /* Get pointer to Communication Processor */
- cp = cpmp;
- switch (fs_no) {
- case fsid_fec1:
- fpi = &mpc8xx_fec_pdata[0];
- fpi->init_ioports = &setup_fec1_ioports;
-
- break;
- case fsid_scc1:
- fpi = &mpc8xx_scc_pdata;
- fpi->init_ioports = &setup_scc1_ioports;
-
- break;
- default:
- printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
- return;
- }
-
- pdev->dev.platform_data = fpi;
- fpi->fs_no = fs_no;
-
- e = (unsigned char *)&bd->bi_enetaddr;
- for (i = 0; i < 6; i++)
- fpi->macaddr[i] = *e++;
-
- fpi->macaddr[5 - pdev->id]++;
-
-}
-
-static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
- int idx)
-{
- /* This is for FEC devices only */
- if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
- return;
- mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
-}
-
-static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
- int idx)
-{
- /* This is for SCC devices only */
- if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
- return;
-
- mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
-}
-
static void setup_smc1_ioports(void)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -315,6 +245,56 @@ static void setup_smc2_ioports(void)
}
+static int ma_count = 0;
+
+static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+{
+ struct fs_platform_info *fpi;
+
+ volatile cpm8xx_t *cp;
+ bd_t *bd = (bd_t *) __res;
+ char *e;
+ int i;
+
+ /* Get pointer to Communication Processor */
+ cp = cpmp;
+
+ if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+ printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+ return;
+ }
+
+
+ fpi = &mpc8xx_enet_pdata[fs_no];
+ fpi->fs_no = fs_no;
+ pdev->dev.platform_data = fpi;
+
+ e = (unsigned char *)&bd->bi_enetaddr;
+ for (i = 0; i < 6; i++)
+ fpi->macaddr[i] = *e++;
+
+ fpi->macaddr[5] += ma_count++;
+}
+
+static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for FEC devices only */
+ if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
+ return;
+ mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for SCC devices only */
+ if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
+ return;
+
+ mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
int idx)
{
@@ -359,6 +339,9 @@ static int mpc866ads_platform_notify(struct device *dev)
int __init mpc866ads_init(void)
{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_mii_fec_platform_info* fmpi;
+
printk(KERN_NOTICE "mpc866ads: Init\n");
platform_notify = mpc866ads_platform_notify;
@@ -366,11 +349,20 @@ int __init mpc866ads_init(void)
ppc_sys_device_initfunc();
ppc_sys_device_disable_all();
-#ifdef MPC8xx_SECOND_ETH_SCC1
+#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
ppc_sys_device_enable(MPC8xx_CPM_SCC1);
#endif
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+ ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+ fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+ &mpc8xx_mdio_fec_pdata;
+
+ fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+ /* No PHY interrupt line here */
+ fmpi->irq[0xf] = -1;
+
/* Since either of the uarts could be used as console, they need to ready */
#ifdef CONFIG_SERIAL_CPM_SMC1
ppc_sys_device_enable(MPC8xx_CPM_SMC1);
@@ -381,6 +373,14 @@ int __init mpc866ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_SMC2);
ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
#endif
+ ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+ fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+ &mpc8xx_mdio_fec_pdata;
+
+ fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+ /* No PHY interrupt line here */
+ fmpi->irq[0xf] = -1;
return 0;
}
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index c1fc4a16fea9..5dfa4e6c2af0 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -38,7 +38,10 @@ extern unsigned char __res[];
static void setup_smc1_ioports(void);
static void setup_smc2_ioports(void);
-static void __init mpc885ads_scc_phy_init(char);
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
+static void setup_fec1_ioports(void);
+static void setup_fec2_ioports(void);
+static void setup_scc3_ioports(void);
static struct fs_uart_platform_info mpc885_uart_pdata[] = {
[fsid_smc1_uart] = {
@@ -61,23 +64,8 @@ static struct fs_uart_platform_info mpc885_uart_pdata[] = {
},
};
-static struct fs_mii_bus_info fec_mii_bus_info = {
- .method = fsmii_fec,
- .id = 0,
-};
-
-static struct fs_mii_bus_info scc_mii_bus_info = {
-#ifdef CONFIG_SCC_ENET_8xx_FIXED
- .method = fsmii_fixed,
-#else
- .method = fsmii_fec,
-#endif
-
- .id = 0,
-};
-
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
- {
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+ [fsid_fec1] = {
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
@@ -85,11 +73,12 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
.use_napi = 1,
.napi_weight = 17,
- .phy_addr = 0,
- .phy_irq = SIU_IRQ7,
+ .init_ioports = setup_fec1_ioports,
- .bus_info = &fec_mii_bus_info,
- }, {
+ .bus_id = "0:00",
+ .has_phy = 1,
+ },
+ [fsid_fec2] = {
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
@@ -97,35 +86,32 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
.use_napi = 1,
.napi_weight = 17,
- .phy_addr = 1,
- .phy_irq = SIU_IRQ7,
+ .init_ioports = setup_fec2_ioports,
- .bus_info = &fec_mii_bus_info,
- }
-};
+ .bus_id = "0:01",
+ .has_phy = 1,
+ },
+ [fsid_scc3] = {
+ .rx_ring = 64,
+ .tx_ring = 8,
+ .rx_copybreak = 240,
-static struct fs_platform_info mpc8xx_scc_pdata = {
- .rx_ring = 64,
- .tx_ring = 8,
- .rx_copybreak = 240,
+ .use_napi = 1,
+ .napi_weight = 17,
- .use_napi = 1,
- .napi_weight = 17,
-
- .phy_addr = 2,
-#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
- .phy_irq = -1,
+ .init_ioports = setup_scc3_ioports,
+#ifdef CONFIG_FIXED_MII_10_FDX
+ .bus_id = "fixed@100:1",
#else
- .phy_irq = SIU_IRQ7,
-#endif
-
- .bus_info = &scc_mii_bus_info,
+ .bus_id = "0:02",
+ #endif
+ },
};
void __init board_init(void)
{
- volatile cpm8xx_t *cp = cpmp;
- unsigned int *bcsr_io;
+ cpm8xx_t *cp = cpmp;
+ unsigned int *bcsr_io;
#ifdef CONFIG_FS_ENET
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -164,6 +150,14 @@ void __init board_init(void)
/* use MDC for MII (common) */
setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+ bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+ clrbits32(bcsr_io,BCSR5_MII1_EN);
+ clrbits32(bcsr_io,BCSR5_MII1_RST);
+#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+ clrbits32(bcsr_io,BCSR5_MII2_EN);
+ clrbits32(bcsr_io,BCSR5_MII2_RST);
+#endif
+ iounmap(bcsr_io);
#endif
}
@@ -194,8 +188,8 @@ static void setup_fec2_ioports(void)
/* configure FEC2 pins */
setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
- setbits32(&immap->im_cpm.cp_peso, 0x00037800);
clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+ setbits32(&immap->im_cpm.cp_peso, 0x00037800);
clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
}
@@ -213,6 +207,8 @@ static void setup_scc3_ioports(void)
/* Enable the PHY.
*/
+ clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+ udelay(1000);
setbits32(bcsr_io+4, BCSR4_ETH10_RST);
/* Configure port A pins for Txd and Rxd.
*/
@@ -254,37 +250,38 @@ static void setup_scc3_ioports(void)
clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
- setbits32(bcsr_io+1, BCSR1_ETHEN);
+ setbits32(bcsr_io+4, BCSR1_ETHEN);
iounmap(bcsr_io);
}
+static int mac_count = 0;
+
static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
{
- struct fs_platform_info *fpi = pdev->dev.platform_data;
-
- volatile cpm8xx_t *cp;
+ struct fs_platform_info *fpi;
bd_t *bd = (bd_t *) __res;
char *e;
int i;
- /* Get pointer to Communication Processor */
- cp = cpmp;
+ if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+ printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+ return;
+ }
+
+ fpi = &mpc8xx_enet_pdata[fs_no];
+
switch (fs_no) {
case fsid_fec1:
- fpi = &mpc8xx_fec_pdata[0];
fpi->init_ioports = &setup_fec1_ioports;
break;
case fsid_fec2:
- fpi = &mpc8xx_fec_pdata[1];
fpi->init_ioports = &setup_fec2_ioports;
break;
case fsid_scc3:
- fpi = &mpc8xx_scc_pdata;
fpi->init_ioports = &setup_scc3_ioports;
- mpc885ads_scc_phy_init(fpi->phy_addr);
break;
default:
- printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
+ printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
return;
}
@@ -295,7 +292,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
for (i = 0; i < 6; i++)
fpi->macaddr[i] = *e++;
- fpi->macaddr[5 - pdev->id]++;
+ fpi->macaddr[5] += mac_count++;
}
@@ -318,58 +315,6 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
-/* SCC ethernet controller does not have MII management channel. FEC1 MII
- * channel is used to communicate with the 10Mbit PHY.
- */
-
-#define MII_ECNTRL_PINMUX 0x4
-#define FEC_ECNTRL_PINMUX 0x00000004
-#define FEC_RCNTRL_MII_MODE 0x00000004
-
-/* Make MII read/write commands.
- */
-#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \
- ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
-
-static void mpc885ads_scc_phy_init(char phy_addr)
-{
- volatile immap_t *immap;
- volatile fec_t *fecp;
- bd_t *bd;
-
- bd = (bd_t *) __res;
- immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
- fecp = &(immap->im_cpm.cp_fec);
-
- /* Enable MII pins of the FEC1
- */
- setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
- clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
- /* Set MII speed to 2.5 MHz
- */
- out_be32(&fecp->fec_mii_speed,
- ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
-
- /* Enable FEC pin MUX
- */
- setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
- setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-
- out_be32(&fecp->fec_mii_data,
- mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
- udelay(100);
- out_be32(&fecp->fec_mii_data,
- mk_mii_write(MII_ADVERTISE,
- ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
- udelay(100);
-
- /* Disable FEC MII settings
- */
- clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
- clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
- out_be32(&fecp->fec_mii_speed, 0);
-}
-
static void setup_smc1_ioports(void)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -462,6 +407,9 @@ static int mpc885ads_platform_notify(struct device *dev)
int __init mpc885ads_init(void)
{
+ struct fs_mii_fec_platform_info* fmpi;
+ bd_t *bd = (bd_t *) __res;
+
printk(KERN_NOTICE "mpc885ads: Init\n");
platform_notify = mpc885ads_platform_notify;
@@ -471,8 +419,17 @@ int __init mpc885ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+ ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+ fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+ &mpc8xx_mdio_fec_pdata;
+
+ fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+
+ /* No PHY interrupt line here */
+ fmpi->irq[0xf] = SIU_IRQ7;
+
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
- ppc_sys_device_enable(MPC8xx_CPM_SCC1);
+ ppc_sys_device_enable(MPC8xx_CPM_SCC3);
#endif
#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
index 8f14a43eafec..672483df8079 100644
--- a/arch/ppc/platforms/pq2ads_pd.h
+++ b/arch/ppc/platforms/pq2ads_pd.h
@@ -29,86 +29,4 @@
#define F3_RXCLK 13
#define F3_TXCLK 14
-/* Automatically generates register configurations */
-#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
-
-#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
-#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
-#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
-#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
-#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
-#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
-
-#define PC_F1RXCLK PC_CLK(F1_RXCLK)
-#define PC_F1TXCLK PC_CLK(F1_TXCLK)
-#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
-#define CMX1_CLK_MASK ((uint)0xff000000)
-
-#define PC_F2RXCLK PC_CLK(F2_RXCLK)
-#define PC_F2TXCLK PC_CLK(F2_TXCLK)
-#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
-#define CMX2_CLK_MASK ((uint)0x00ff0000)
-
-#define PC_F3RXCLK PC_CLK(F3_RXCLK)
-#define PC_F3TXCLK PC_CLK(F3_TXCLK)
-#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
-#define CMX3_CLK_MASK ((uint)0x0000ff00)
-
-/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PA1_COL 0x00000001U
-#define PA1_CRS 0x00000002U
-#define PA1_TXER 0x00000004U
-#define PA1_TXEN 0x00000008U
-#define PA1_RXDV 0x00000010U
-#define PA1_RXER 0x00000020U
-#define PA1_TXDAT 0x00003c00U
-#define PA1_RXDAT 0x0003c000U
-#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
- PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
-
-
-/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB2_TXER 0x00000001U
-#define PB2_RXDV 0x00000002U
-#define PB2_TXEN 0x00000004U
-#define PB2_RXER 0x00000008U
-#define PB2_COL 0x00000010U
-#define PB2_CRS 0x00000020U
-#define PB2_TXDAT 0x000003c0U
-#define PB2_RXDAT 0x00003c00U
-#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
- PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1 (PB2_TXEN)
-#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
-
-
-/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB3_RXDV 0x00004000U
-#define PB3_RXER 0x00008000U
-#define PB3_TXER 0x00010000U
-#define PB3_TXEN 0x00020000U
-#define PB3_COL 0x00040000U
-#define PB3_CRS 0x00080000U
-#define PB3_TXDAT 0x0f000000U
-#define PB3_RXDAT 0x00f00000U
-#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
- PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1 0
-#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
-
-#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
-#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
-#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
-
#endif
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 2497bbc07e76..dca23f2ef851 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o
endif
obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \
- mpc83xx_sys.o mpc83xx_devices.o
+ mpc83xx_sys.o mpc83xx_devices.o ipic.o
ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += pci_auto.o
endif
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 000000000000..46801f5ec03f
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, 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.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+ [9] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 24,
+ .prio_mask = 0,
+ },
+ [10] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 25,
+ .prio_mask = 1,
+ },
+ [11] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 26,
+ .prio_mask = 2,
+ },
+ [14] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 29,
+ .prio_mask = 5,
+ },
+ [15] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 30,
+ .prio_mask = 6,
+ },
+ [16] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 31,
+ .prio_mask = 7,
+ },
+ [17] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 1,
+ .prio_mask = 5,
+ },
+ [18] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 2,
+ .prio_mask = 6,
+ },
+ [19] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 3,
+ .prio_mask = 7,
+ },
+ [20] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [21] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [22] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [23] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [32] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [33] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [34] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [35] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [36] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [37] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [38] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [39] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [48] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 0,
+ .prio_mask = 4,
+ },
+ [64] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [65] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [66] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [67] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [68] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 4,
+ .prio_mask = 0,
+ },
+ [69] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 5,
+ .prio_mask = 1,
+ },
+ [70] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 6,
+ .prio_mask = 2,
+ },
+ [71] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 7,
+ .prio_mask = 3,
+ },
+ [72] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 8,
+ },
+ [73] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 9,
+ },
+ [74] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 10,
+ },
+ [75] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 11,
+ },
+ [76] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 12,
+ },
+ [77] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 13,
+ },
+ [78] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 14,
+ },
+ [79] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 15,
+ },
+ [80] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 16,
+ },
+ [84] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 20,
+ },
+ [85] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 21,
+ },
+ [90] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 26,
+ },
+ [91] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 27,
+ },
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+ return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+ out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+ return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp &= ~(1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ ipic_disable_irq(irq);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].pend);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+ .typename = " IPIC ",
+ .enable = ipic_enable_irq,
+ .disable = ipic_disable_irq,
+ .ack = ipic_disable_irq_and_ack,
+ .end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+ unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses,
+ unsigned int senses_count)
+{
+ u32 i, temp = 0;
+
+ primary_ipic = &p_ipic;
+ primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+ primary_ipic->irq_offset = irq_offset;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+ /* default priority scheme is grouped. If spread mode is required
+ * configure SICFR accordingly */
+ if (flags & IPIC_SPREADMODE_GRP_A)
+ temp |= SICFR_IPSA;
+ if (flags & IPIC_SPREADMODE_GRP_D)
+ temp |= SICFR_IPSD;
+ if (flags & IPIC_SPREADMODE_MIX_A)
+ temp |= SICFR_MPSA;
+ if (flags & IPIC_SPREADMODE_MIX_B)
+ temp |= SICFR_MPSB;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+ /* handle MCP route */
+ temp = 0;
+ if (flags & IPIC_DISABLE_MCP_OUT)
+ temp = SERCR_MCPR;
+ ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+ /* handle routing of IRQ0 to MCP */
+ temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+ if (flags & IPIC_IRQ0_MCP)
+ temp |= SEMSR_SIRQ0;
+ else
+ temp &= ~SEMSR_SIRQ0;
+
+ ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+ for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+ irq_desc[i+irq_offset].chip = &ipic;
+ irq_desc[i+irq_offset].status = IRQ_LEVEL;
+ }
+
+ temp = 0;
+ for (i = 0 ; i < senses_count ; i++) {
+ if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+ temp |= 1 << (15 - i);
+ if (i != 0)
+ irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+ else
+ irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+ }
+ }
+ ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+ printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+ senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ if (priority > 7)
+ return -EINVAL;
+ if (src > 127)
+ return -EINVAL;
+ if (ipic_info[src].prio == 0)
+ return -EINVAL;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+ if (priority < 4) {
+ temp &= ~(0x7 << (20 + (3 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+ } else {
+ temp &= ~(0x7 << (4 + (7 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+ }
+
+ ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+ return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+ /* clear and set HPI */
+ temp &= 0x7f000000;
+ temp |= (src & 0x7f) << 24;
+
+ ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+ ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+ ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+ ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+ ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+ ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+ ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+ ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+ ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+ ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+ ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+ ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+ ipic_set_priority(MPC83xx_IRQ_MU, 1);
+ ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+ ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp |= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp &= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+ return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+ ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+ if (irq == 0) /* 0 --> no irq is pending */
+ irq = -1;
+
+ return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+ set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+ .id = 0,
+ .cls = &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+ int rc;
+
+ if (!primary_ipic->regs)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+ rc = sysdev_class_register(&ipic_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_ipic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys device\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 000000000000..a60c9d18bb7f
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,47 @@
+/*
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright 2005 Freescale Semiconductor, 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 __IPIC_H__
+#define __IPIC_H__
+
+#include
+
+#define MPC83xx_IPIC_SIZE (0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define SICFR_IPSA 0x00010000
+#define SICFR_IPSD 0x00080000
+#define SICFR_MPSA 0x00200000
+#define SICFR_MPSB 0x00400000
+
+/* System External Interrupt Mask Register */
+#define SEMSR_SIRQ0 0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR 0x00000001
+
+struct ipic {
+ volatile u32 __iomem *regs;
+ unsigned int irq_offset;
+};
+
+struct ipic_info {
+ u8 pend; /* pending register offset from base */
+ u8 mask; /* mask register offset from base */
+ u8 prio; /* priority register offset from base */
+ u8 force; /* force register offset from base */
+ u8 bit; /* register bit position (as per doc)
+ bit mask = 1 << (31 - bit) */
+ u8 prio_mask; /* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 7735336f5b8f..325136e5aee0 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -16,9 +16,11 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
/* We use offsets for IORESOURCE_MEM since we do not know at compile time
* what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
@@ -82,6 +84,60 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
};
+static struct fs_platform_info mpc85xx_fcc1_pdata = {
+ .fs_no = fsid_fcc1,
+ .cp_page = CPM_CR_FCC1_PAGE,
+ .cp_block = CPM_CR_FCC1_SBLOCK,
+
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+
+ .clk_mask = CMX1_CLK_MASK,
+ .clk_route = CMX1_CLK_ROUTE,
+ .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
+
+ .mem_offset = FCC1_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc2_pdata = {
+ .fs_no = fsid_fcc2,
+ .cp_page = CPM_CR_FCC2_PAGE,
+ .cp_block = CPM_CR_FCC2_SBLOCK,
+
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+
+ .clk_mask = CMX2_CLK_MASK,
+ .clk_route = CMX2_CLK_ROUTE,
+ .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
+
+ .mem_offset = FCC2_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc3_pdata = {
+ .fs_no = fsid_fcc3,
+ .cp_page = CPM_CR_FCC3_PAGE,
+ .cp_block = CPM_CR_FCC3_SBLOCK,
+
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+
+ .clk_mask = CMX3_CLK_MASK,
+ .clk_route = CMX3_CLK_ROUTE,
+ .clk_trx = (PC_F3RXCLK | PC_F3TXCLK),
+
+ .mem_offset = FCC3_MEM_OFFSET,
+};
+
static struct plat_serial8250_port serial_platform_data[] = {
[0] = {
.mapbase = 0x4500,
@@ -318,18 +374,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC1] = {
.name = "fsl-cpm-fcc",
.id = 1,
- .num_resources = 3,
+ .num_resources = 4,
+ .dev.platform_data = &mpc85xx_fcc1_pdata,
.resource = (struct resource[]) {
{
+ .name = "fcc_regs",
.start = 0x91300,
.end = 0x9131F,
.flags = IORESOURCE_MEM,
},
{
+ .name = "fcc_regs_c",
.start = 0x91380,
.end = 0x9139F,
.flags = IORESOURCE_MEM,
},
+ {
+ .name = "fcc_pram",
+ .start = 0x88400,
+ .end = 0x884ff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = SIU_INT_FCC1,
.end = SIU_INT_FCC1,
@@ -340,18 +405,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC2] = {
.name = "fsl-cpm-fcc",
.id = 2,
- .num_resources = 3,
+ .num_resources = 4,
+ .dev.platform_data = &mpc85xx_fcc2_pdata,
.resource = (struct resource[]) {
{
+ .name = "fcc_regs",
.start = 0x91320,
.end = 0x9133F,
.flags = IORESOURCE_MEM,
},
{
+ .name = "fcc_regs_c",
.start = 0x913A0,
.end = 0x913CF,
.flags = IORESOURCE_MEM,
},
+ {
+ .name = "fcc_pram",
+ .start = 0x88500,
+ .end = 0x885ff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = SIU_INT_FCC2,
.end = SIU_INT_FCC2,
@@ -362,18 +436,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC3] = {
.name = "fsl-cpm-fcc",
.id = 3,
- .num_resources = 3,
+ .num_resources = 4,
+ .dev.platform_data = &mpc85xx_fcc3_pdata,
.resource = (struct resource[]) {
{
+ .name = "fcc_regs",
.start = 0x91340,
.end = 0x9135F,
.flags = IORESOURCE_MEM,
},
{
+ .name = "fcc_regs_c",
.start = 0x913D0,
.end = 0x913FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .name = "fcc_pram",
+ .start = 0x88600,
+ .end = 0x886ff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = SIU_INT_FCC3,
.end = SIU_INT_FCC3,
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
index 6f536383866e..cf5ab47487a7 100644
--- a/arch/ppc/syslib/mpc8xx_devices.c
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -218,6 +218,14 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
+
+ [MPC8xx_MDIO_FEC] = {
+ .name = "fsl-cpm-fec-mdio",
+ .id = 0,
+ .num_resources = 0,
+
+ },
+
};
static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
index eee213284855..18ba1d7ff9f1 100644
--- a/arch/ppc/syslib/mpc8xx_sys.c
+++ b/arch/ppc/syslib/mpc8xx_sys.c
@@ -22,7 +22,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "MPC86X",
.mask = 0xFFFFFFFF,
.value = 0x00000000,
- .num_devices = 7,
+ .num_devices = 8,
.device_list = (enum ppc_sys_devices[])
{
MPC8xx_CPM_FEC1,
@@ -32,13 +32,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC8xx_CPM_SCC4,
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
+ MPC8xx_MDIO_FEC,
},
},
{
.ppc_sys_name = "MPC885",
.mask = 0xFFFFFFFF,
.value = 0x00000000,
- .num_devices = 8,
+ .num_devices = 9,
.device_list = (enum ppc_sys_devices[])
{
MPC8xx_CPM_FEC1,
@@ -49,6 +50,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC8xx_CPM_SCC4,
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
+ MPC8xx_MDIO_FEC,
},
},
{ /* default match */
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c
index 8692d00c08c4..fefbc217a56d 100644
--- a/arch/ppc/syslib/pq2_devices.c
+++ b/arch/ppc/syslib/pq2_devices.c
@@ -369,6 +369,11 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
+ [MPC82xx_MDIO_BB] = {
+ .name = "fsl-bb-mdio",
+ .id = 0,
+ .num_resources = 0,
+ },
};
static int __init mach_mpc82xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
index fee8948162b9..f52600c0db20 100644
--- a/arch/ppc/syslib/pq2_sys.c
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -139,13 +139,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8272",
.mask = 0x0000ff00,
.value = 0x00000c00,
- .num_devices = 12,
+ .num_devices = 13,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
+ MPC82xx_MDIO_BB,
},
},
/* below is a list of the 8280 family of processors */
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index d0f82c995af6..a0a94e0ef8d1 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -617,6 +617,7 @@ appldata_offline_cpu(int cpu)
spin_unlock(&appldata_timer_lock);
}
+#ifdef CONFIG_HOTPLUG_CPU
static int __cpuinit
appldata_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
@@ -625,20 +626,19 @@ appldata_cpu_notify(struct notifier_block *self,
case CPU_ONLINE:
appldata_online_cpu((long) hcpu);
break;
-#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
appldata_offline_cpu((long) hcpu);
break;
-#endif
default:
break;
}
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
+#endif
/*
* appldata_init()
@@ -662,7 +662,7 @@ static int __init appldata_init(void)
appldata_online_cpu(i);
/* Register cpu hotplug notifier */
- register_cpu_notifier(&appldata_nb);
+ register_hotcpu_notifier(&appldata_nb);
appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
#ifdef MODULE
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f4dfc10026d2..f1d4591eddbb 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,13 +1,16 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Mon Apr 3 14:34:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Thu Jul 27 13:51:07 2006
#
CONFIG_MMU=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_S390=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
@@ -25,6 +28,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
@@ -43,10 +47,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -94,7 +100,6 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_DEFAULT_MIGRATION_COST=1000000
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
-CONFIG_BINFMT_ELF32=y
#
# Code generation options
@@ -115,6 +120,7 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
#
# I/O subsystem configuration
@@ -142,6 +148,7 @@ CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_APPLDATA_BASE is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IDLE_HZ_INIT=y
+CONFIG_S390_HYPFS_FS=y
CONFIG_KEXEC=y
#
@@ -174,6 +181,8 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -186,7 +195,10 @@ CONFIG_IPV6=y
# CONFIG_INET6_IPCOMP is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -263,6 +275,7 @@ CONFIG_NET_ESTIMATOR=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
@@ -276,6 +289,7 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
#
# Connector - unified userspace <-> kernelspace linker
@@ -334,6 +348,7 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
@@ -359,9 +374,7 @@ CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=m
-# CONFIG_MD_RAID5_RESHAPE is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
@@ -419,7 +432,8 @@ CONFIG_S390_TAPE_34XX=m
#
# Cryptographic devices
#
-CONFIG_Z90CRYPT=m
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
#
# Network device support
@@ -509,6 +523,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -614,26 +629,36 @@ CONFIG_MSDOS_PARTITION=y
# Instrumentation Support
#
# CONFIG_PROFILING is not set
-# CONFIG_STATISTICS is not set
+CONFIG_STATISTICS=y
+CONFIG_KPROBES=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
@@ -688,3 +713,4 @@ CONFIG_CRYPTO=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index 5d59e2625048..837275284d9f 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -88,30 +88,31 @@ __copy_to_user_asm:
.globl __copy_in_user_asm
# %r2 = from, %r3 = n, %r4 = to
__copy_in_user_asm:
+ ahi %r3,-1
+ jo 6f
sacf 256
- bras 1,1f
- mvc 0(1,%r4),0(%r2)
-0: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-1: ahi %r3,-256
- jnm 0b
-2: ex %r3,0(%r1)
- sacf 0
- slr %r2,%r2
- br 14
-3: mvc 0(1,%r4),0(%r2)
+ bras %r1,4f
+0: ahi %r3,257
+1: mvc 0(1,%r4),0(%r2)
la %r2,1(%r2)
la %r4,1(%r4)
ahi %r3,-1
+ jnz 1b
+2: lr %r2,%r3
+ br %r14
+3: mvc 0(256,%r4),0(%r2)
+ la %r2,256(%r2)
+ la %r4,256(%r4)
+4: ahi %r3,-256
jnm 3b
-4: lr %r2,%r3
+5: ex %r3,4(%r1)
sacf 0
+6: slr %r2,%r2
br %r14
.section __ex_table,"a"
- .long 0b,3b
- .long 2b,3b
- .long 3b,4b
+ .long 1b,2b
+ .long 3b,0b
+ .long 5b,0b
.previous
.align 4
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
index 19b41a33c230..1f755be22f92 100644
--- a/arch/s390/lib/uaccess64.S
+++ b/arch/s390/lib/uaccess64.S
@@ -88,30 +88,31 @@ __copy_to_user_asm:
.globl __copy_in_user_asm
# %r2 = from, %r3 = n, %r4 = to
__copy_in_user_asm:
+ aghi %r3,-1
+ jo 6f
sacf 256
- bras 1,1f
- mvc 0(1,%r4),0(%r2)
-0: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-1: aghi %r3,-256
- jnm 0b
-2: ex %r3,0(%r1)
- sacf 0
- slgr %r2,%r2
- br 14
-3: mvc 0(1,%r4),0(%r2)
+ bras %r1,4f
+0: aghi %r3,257
+1: mvc 0(1,%r4),0(%r2)
la %r2,1(%r2)
la %r4,1(%r4)
aghi %r3,-1
- jnm 3b
-4: lgr %r2,%r3
- sacf 0
+ jnz 1b
+2: lgr %r2,%r3
br %r14
+3: mvc 0(256,%r4),0(%r2)
+ la %r2,256(%r2)
+ la %r4,256(%r4)
+4: aghi %r3,-256
+ jnm 3b
+5: ex %r3,4(%r1)
+ sacf 0
+6: slgr %r2,%r2
+ br 14
.section __ex_table,"a"
- .quad 0b,3b
- .quad 2b,3b
- .quad 3b,4b
+ .quad 1b,2b
+ .quad 3b,0b
+ .quad 5b,0b
.previous
.align 4
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index eb6ebfef134a..6e6b6de77770 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -129,7 +129,7 @@ void __init paging_init(void)
/*
* pg_table is physical at this point
*/
- pg_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
pg_dir->pgd0 = (_PAGE_TABLE | __pa(pg_table));
pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024));
@@ -219,7 +219,7 @@ void __init paging_init(void)
continue;
}
- pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
+ pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4);
pgd_populate(&init_mm, pg_dir, pm_dir);
for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
@@ -228,7 +228,7 @@ void __init paging_init(void)
continue;
}
- pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 781dbb11c038..b09805f3ee23 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -421,18 +421,22 @@ static struct miscdevice sq_dev = {
static int __init sq_api_init(void)
{
+ int ret;
printk(KERN_NOTICE "sq: Registering store queue API.\n");
-#ifdef CONFIG_PROC_FS
create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
-#endif
- return misc_register(&sq_dev);
+ ret = misc_register(&sq_dev);
+ if (ret)
+ remove_proc_entry("sq_mapping", NULL);
+
+ return ret;
}
static void __exit sq_api_exit(void)
{
misc_deregister(&sq_dev);
+ remove_proc_entry("sq_mapping", NULL);
}
module_init(sq_api_init);
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 35488d6c7457..0251cab4708b 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -348,9 +348,9 @@ void __init setup_arch(char **cmdline_p)
init_mm.context = (unsigned long) NO_CONTEXT;
init_task.thread.kregs = &fake_swapper_regs;
- smp_setup_cpu_possible_map();
-
paging_init();
+
+ smp_setup_cpu_possible_map();
}
static int __init set_preferred_console(void)
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index e311ade1b490..276f22881d0f 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -34,7 +34,6 @@
#include
#include
-volatile int smp_processors_ready = 0;
int smp_num_cpus = 1;
volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
unsigned char boot_cpu_id = 0;
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index ba843f6a2832..3ff4edd32815 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -42,7 +42,7 @@ extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void);
-extern volatile int smp_processors_ready;
+static volatile int smp_processors_ready = 0;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern cpuinfo_sparc cpu_data[NR_CPUS];
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 3b32096134aa..7d4a649138f6 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -39,7 +39,6 @@ extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void);
-extern volatile int smp_processors_ready;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
@@ -217,7 +216,6 @@ void __init smp4m_smp_done(void)
}
/* Ok, they are spinning and ready to go. */
- smp_processors_ready = 1;
}
/* At each hardware IRQ, we get this called to forward IRQ reception
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 04eb1eab6e3e..845081b01267 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -225,6 +225,32 @@ static __inline__ int has_low_battery(void)
return (data1 == data2); /* Was the write blocked? */
}
+static void __init mostek_set_system_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ struct mostek48t02 *mregs;
+
+ mregs = (struct mostek48t02 *)mstk48t02_regs;
+ if(!mregs) {
+ prom_printf("Something wrong, clock regs not mapped yet.\n");
+ prom_halt();
+ }
+ spin_lock_irq(&mostek_lock);
+ mregs->creg |= MSTK_CREG_READ;
+ sec = MSTK_REG_SEC(mregs);
+ min = MSTK_REG_MIN(mregs);
+ hour = MSTK_REG_HOUR(mregs);
+ day = MSTK_REG_DOM(mregs);
+ mon = MSTK_REG_MONTH(mregs);
+ year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
+ xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+ xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+ mregs->creg &= ~MSTK_CREG_READ;
+ spin_unlock_irq(&mostek_lock);
+}
+
/* Probe for the real time clock chip on Sun4 */
static __inline__ void sun4_clock_probe(void)
{
@@ -273,6 +299,7 @@ static __inline__ void sun4_clock_probe(void)
#endif
}
+#ifndef CONFIG_SUN4
static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match)
{
struct device_node *dp = op->node;
@@ -307,6 +334,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
kick_start_clock();
+ mostek_set_system_time();
+
return 0;
}
@@ -325,56 +354,37 @@ static struct of_platform_driver clock_driver = {
/* Probe for the mostek real time clock chip. */
-static void clock_init(void)
+static int __init clock_init(void)
{
- of_register_driver(&clock_driver, &of_bus_type);
+ return of_register_driver(&clock_driver, &of_bus_type);
}
+/* Must be after subsys_initcall() so that busses are probed. Must
+ * be before device_initcall() because things like the RTC driver
+ * need to see the clock registers.
+ */
+fs_initcall(clock_init);
+#endif /* !CONFIG_SUN4 */
+
void __init sbus_time_init(void)
{
- unsigned int year, mon, day, hour, min, sec;
- struct mostek48t02 *mregs;
-
-#ifdef CONFIG_SUN4
- int temp;
- struct intersil *iregs;
-#endif
BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
btfixup();
if (ARCH_SUN4)
sun4_clock_probe();
- else
- clock_init();
sparc_init_timers(timer_interrupt);
#ifdef CONFIG_SUN4
if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
-#endif
- mregs = (struct mostek48t02 *)mstk48t02_regs;
- if(!mregs) {
- prom_printf("Something wrong, clock regs not mapped yet.\n");
- prom_halt();
- }
- spin_lock_irq(&mostek_lock);
- mregs->creg |= MSTK_CREG_READ;
- sec = MSTK_REG_SEC(mregs);
- min = MSTK_REG_MIN(mregs);
- hour = MSTK_REG_HOUR(mregs);
- day = MSTK_REG_DOM(mregs);
- mon = MSTK_REG_MONTH(mregs);
- year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
- xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
- mregs->creg &= ~MSTK_CREG_READ;
- spin_unlock_irq(&mostek_lock);
-#ifdef CONFIG_SUN4
+ mostek_set_system_time();
} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
/* initialise the intersil on sun4 */
+ unsigned int year, mon, day, hour, min, sec;
+ int temp;
+ struct intersil *iregs;
iregs=intersil_clock;
if(!iregs) {
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index 8cb06205d265..af9d81db0b38 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -69,6 +69,8 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
} else
offset += PAGE_SIZE;
+ if (pte_write(entry))
+ entry = pte_mkdirty(entry);
do {
BUG_ON(!pte_none(*pte));
set_pte_at(mm, address, pte, entry);
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 2517ecb8bf27..68ed24df5c8f 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -26,6 +26,7 @@ SECTIONS
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 62bdb8d29fc0..1bf672a25692 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -1,8 +1,8 @@
/*
* arch/v850/kernel/setup.c -- Arch-dependent initialization functions
*
- * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,05 Miles Bader
+ * Copyright (C) 2001,02,03,05,06 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03,05,06 Miles Bader
*
* 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
@@ -190,7 +190,7 @@ void free_initmem (void)
for (addr = start; addr < end; addr += PAGE_SIZE) {
struct page *page = virt_to_page (addr);
ClearPageReserved (page);
- set_page_count (page, 1);
+ init_page_count (page);
__free_page (page);
total_ram_pages++;
}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index c03ad6ed61cc..67bc48e57c60 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -21,9 +21,6 @@ EXPORT_SYMBOL (trap_table);
/* platform dependent support */
EXPORT_SYMBOL (kernel_thread);
-EXPORT_SYMBOL (enable_irq);
-EXPORT_SYMBOL (disable_irq);
-EXPORT_SYMBOL (disable_irq_nosync);
EXPORT_SYMBOL (__bug);
/* Networking helper routines. */
@@ -33,22 +30,9 @@ EXPORT_SYMBOL (ip_compute_csum);
EXPORT_SYMBOL (ip_fast_csum);
/* string / mem functions */
-EXPORT_SYMBOL (strcpy);
-EXPORT_SYMBOL (strncpy);
-EXPORT_SYMBOL (strcat);
-EXPORT_SYMBOL (strncat);
-EXPORT_SYMBOL (strcmp);
-EXPORT_SYMBOL (strncmp);
-EXPORT_SYMBOL (strchr);
-EXPORT_SYMBOL (strlen);
-EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strrchr);
-EXPORT_SYMBOL (strstr);
EXPORT_SYMBOL (memset);
EXPORT_SYMBOL (memcpy);
EXPORT_SYMBOL (memmove);
-EXPORT_SYMBOL (memcmp);
-EXPORT_SYMBOL (memscan);
/* semaphores */
EXPORT_SYMBOL (__down);
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 83d389b8ebd8..5fb970715941 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-git22
-# Tue Jul 4 14:24:40 2006
+# Linux kernel version: 2.6.18-rc4
+# Thu Aug 24 21:05:55 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -37,6 +37,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
@@ -200,7 +201,7 @@ CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_ASUS is not set
# CONFIG_ACPI_IBM is not set
-CONFIG_ACPI_TOSHIBA=y
+# CONFIG_ACPI_TOSHIBA is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_EC=y
@@ -215,7 +216,7 @@ CONFIG_ACPI_CONTAINER=y
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
@@ -413,6 +414,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -493,8 +495,9 @@ CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not set
#
@@ -510,7 +513,7 @@ CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
#
# SCSI low-level drivers
@@ -536,7 +539,7 @@ CONFIG_MEGARAID_MAILBOX=y
CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_SATA=y
CONFIG_SCSI_SATA_AHCI=y
-# CONFIG_SCSI_SATA_SVW is not set
+CONFIG_SCSI_SATA_SVW=y
CONFIG_SCSI_ATA_PIIX=y
# CONFIG_SCSI_SATA_MV is not set
CONFIG_SCSI_SATA_NV=y
@@ -587,7 +590,7 @@ CONFIG_BLK_DEV_DM=y
CONFIG_FUSION=y
CONFIG_FUSION_SPI=y
# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_SAS=y
CONFIG_FUSION_MAX_SGE=128
# CONFIG_FUSION_CTL is not set
@@ -673,7 +676,7 @@ CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
+CONFIG_B44=y
CONFIG_FORCEDETH=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
@@ -710,7 +713,7 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
-# CONFIG_BNX2 is not set
+CONFIG_BNX2=y
#
# Ethernet (10000 Mbit)
@@ -840,44 +843,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_ALIM1535_WDT is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_IBMASR is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_I6300ESB_WDT is not set
-# CONFIG_I8XX_TCO is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_SBC8360_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_W83627HF_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_W83977F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SBC_EPX_C3_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_INTEL=y
CONFIG_HW_RANDOM_AMD=y
@@ -1054,6 +1020,7 @@ CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
CONFIG_VIDEO_SELECT=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -1195,7 +1162,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
@@ -1299,7 +1266,7 @@ CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set
@@ -1373,7 +1340,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1493,4 +1459,5 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 62bc5f56da9e..cdae36435e21 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -23,6 +23,7 @@ targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so)
# The DSO images are built using a special linker script
quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -m32 -nostdlib -shared -s \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv) \
-Wl,-soname=linux-gate.so.1 -o $@ \
-Wl,-T,$(filter-out FORCE,$^)
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index a9dc0f3b5b51..2fd5a67fd435 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -73,39 +73,44 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the vsyscall DSO was being used.
*/
-#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum)
+#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
+ (VSYSCALL32_EHDR->e_phnum) : 0)
#define ELF_CORE_WRITE_EXTRA_PHDRS \
do { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff); \
- int i; \
- Elf32_Off ofs = 0; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- struct elf32_phdr phdr = vsyscall_phdrs[i]; \
- if (phdr.p_type == PT_LOAD) { \
- BUG_ON(ofs != 0); \
- ofs = phdr.p_offset = offset; \
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
- phdr.p_filesz = phdr.p_memsz; \
- offset += phdr.p_filesz; \
+ if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+ const struct elf32_phdr *const vsyscall_phdrs = \
+ (const struct elf32_phdr *) (VSYSCALL32_BASE \
+ + VSYSCALL32_EHDR->e_phoff);\
+ int i; \
+ Elf32_Off ofs = 0; \
+ for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+ struct elf32_phdr phdr = vsyscall_phdrs[i]; \
+ if (phdr.p_type == PT_LOAD) { \
+ BUG_ON(ofs != 0); \
+ ofs = phdr.p_offset = offset; \
+ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
+ phdr.p_filesz = phdr.p_memsz; \
+ offset += phdr.p_filesz; \
+ } \
+ else \
+ phdr.p_offset += ofs; \
+ phdr.p_paddr = 0; /* match other core phdrs */ \
+ DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
} while (0)
#define ELF_CORE_WRITE_EXTRA_DATA \
do { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff); \
- int i; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
- DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \
- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+ const struct elf32_phdr *const vsyscall_phdrs = \
+ (const struct elf32_phdr *) (VSYSCALL32_BASE \
+ + VSYSCALL32_EHDR->e_phoff); \
+ int i; \
+ for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+ DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
+ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ } \
} \
} while (0)
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 9b5bb413a6e9..5d4a7d125ed0 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -103,7 +103,7 @@ ENTRY(ia32_sysenter_target)
pushq %rax
CFI_ADJUST_CFA_OFFSET 8
cld
- SAVE_ARGS 0,0,1
+ SAVE_ARGS 0,0,0
/* no need to do an access_ok check here because rbp has been
32bit zero extended */
1: movl (%rbp),%r9d
diff --git a/arch/x86_64/ia32/vsyscall.lds b/arch/x86_64/ia32/vsyscall.lds
index f2e75ed4c6c7..1dc86ff5bcb9 100644
--- a/arch/x86_64/ia32/vsyscall.lds
+++ b/arch/x86_64/ia32/vsyscall.lds
@@ -11,6 +11,7 @@ SECTIONS
. = VSYSCALL_BASE + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index e56c2adf57a4..764bf23c7103 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -71,7 +71,11 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
#endif
/* kernel code + 640k memory hole (later should not be needed, but
be paranoid for now) */
- if (last >= 640*1024 && addr < __pa_symbol(&_end)) {
+ if (last >= 640*1024 && addr < 1024*1024) {
+ *addrp = 1024*1024;
+ return 1;
+ }
+ if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
*addrp = __pa_symbol(&_end);
return 1;
}
@@ -104,35 +108,6 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
return 0;
}
-/*
- * This function checks if the entire range is mapped with type.
- *
- * Note: this function only works correct if the e820 table is sorted and
- * not-overlapping, which is the case
- */
-int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
-{
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- if (type && ei->type != type)
- continue;
- /* is the region (part) in overlap with the current region ?*/
- if (ei->addr >= end || ei->addr + ei->size <= start)
- continue;
-
- /* if the region is at the beginning of we move
- * start to the end of the region since it's ok until there
- */
- if (ei->addr <= start)
- start = ei->addr + ei->size;
- /* if start is now at or beyond end, we're done, full coverage */
- if (start >= end)
- return 1; /* we're done */
- }
- return 0;
-}
-
/*
* Find a free area in a specific range.
*/
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index d464dded68c0..aa8d8939abc1 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -513,6 +513,7 @@ END(stub_rt_sigreturn)
swapgs
1: incl %gs:pda_irqcount # RED-PEN should check preempt count
cmoveq %gs:pda_irqstackptr,%rsp
+ push %rbp # backlink for old unwinder
/*
* We entered an interrupt context - irqs are off:
*/
@@ -972,6 +973,8 @@ ENTRY(kernel_thread)
ENDPROC(kernel_thread)
child_rip:
+ pushq $0 # fake return address
+ CFI_STARTPROC
/*
* Here we are in the child and the registers are set as they were
* at kernel_thread() invocation in the parent.
@@ -982,6 +985,7 @@ child_rip:
# exit
xorl %edi, %edi
call do_exit
+ CFI_ENDPROC
ENDPROC(child_rip)
/*
@@ -1139,18 +1143,21 @@ ENTRY(machine_check)
END(machine_check)
#endif
+/* Call softirq on interrupt stack. Interrupts are off. */
ENTRY(call_softirq)
CFI_STARTPROC
- movq %gs:pda_irqstackptr,%rax
- movq %rsp,%rdx
- CFI_DEF_CFA_REGISTER rdx
+ push %rbp
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbp,0
+ mov %rsp,%rbp
+ CFI_DEF_CFA_REGISTER rbp
incl %gs:pda_irqcount
- cmove %rax,%rsp
- pushq %rdx
- /*todo CFI_DEF_CFA_EXPRESSION ...*/
+ cmove %gs:pda_irqstackptr,%rsp
+ push %rbp # backlink for old unwinder
call __do_softirq
- popq %rsp
+ leaveq
CFI_DEF_CFA_REGISTER rsp
+ CFI_ADJUST_CFA_OFFSET -8
decl %gs:pda_irqcount
ret
CFI_ENDPROC
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 6df05e6034fa..c9739ca81d06 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -191,6 +191,7 @@ startup_64:
* jump
*/
movq initial_code(%rip),%rax
+ pushq $0 # fake return address
jmp *%rax
/* SMP bootup changes these two */
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index ce31d904d601..3dc5854ba21e 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -46,4 +46,9 @@ EXPORT_SYMBOL(init_task);
*/
DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
+/* Copies of the original ist values from the tss are only accessed during
+ * debugging, no special alignment required.
+ */
+DEFINE_PER_CPU(struct orig_ist, orig_ist);
+
#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
index 83fb24a02821..106076b370fc 100644
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -207,14 +207,11 @@ NORET_TYPE void machine_kexec(struct kimage *image)
__flush_tlb();
- /* The segment registers are funny things, they are
- * automatically loaded from a table, in memory wherever you
- * set them to a specific selector, but this table is never
- * accessed again unless you set the segment to a different selector.
- *
- * The more common model are caches where the behide
- * the scenes work is done, but is also dropped at arbitrary
- * times.
+ /* The segment registers are funny things, they have both a
+ * visible and an invisible part. Whenever the visible part is
+ * set to a specific selector, the invisible part is loaded
+ * with from a table in memory. At no other time is the
+ * descriptor table in memory accessed.
*
* I take advantage of this here by force loading the
* segments, before I zap the gdt with an invalid value.
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 88845674c661..4e017fb30fb3 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -615,7 +615,7 @@ static __cpuinit int mce_create_device(unsigned int cpu)
}
#ifdef CONFIG_HOTPLUG_CPU
-static __cpuinit void mce_remove_device(unsigned int cpu)
+static void mce_remove_device(unsigned int cpu)
{
int i;
@@ -626,10 +626,9 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
sysdev_unregister(&per_cpu(device_mce,cpu));
}
-#endif
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
@@ -638,18 +637,17 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_ONLINE:
mce_create_device(cpu);
break;
-#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
mce_remove_device(cpu);
break;
-#endif
}
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata mce_cpu_notifier = {
+static struct notifier_block mce_cpu_notifier = {
.notifier_call = mce_cpu_callback,
};
+#endif
static __init int mce_init_device(void)
{
@@ -664,7 +662,7 @@ static __init int mce_init_device(void)
mce_create_device(i);
}
- register_cpu_notifier(&mce_cpu_notifier);
+ register_hotcpu_notifier(&mce_cpu_notifier);
misc_register(&mce_log_device);
return err;
}
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index db2acbf7ad28..883fe747f64c 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -558,7 +558,7 @@ out:
* of shared sysfs dir/files, and rest of the cores will be symlinked to it.
*/
-static __cpuinit void deallocate_threshold_block(unsigned int cpu,
+static void deallocate_threshold_block(unsigned int cpu,
unsigned int bank)
{
struct threshold_block *pos = NULL;
@@ -578,7 +578,7 @@ static __cpuinit void deallocate_threshold_block(unsigned int cpu,
per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
}
-static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank)
+static void threshold_remove_bank(unsigned int cpu, int bank)
{
int i = 0;
struct threshold_bank *b;
@@ -618,7 +618,7 @@ free_out:
per_cpu(threshold_banks, cpu)[bank] = NULL;
}
-static __cpuinit void threshold_remove_device(unsigned int cpu)
+static void threshold_remove_device(unsigned int cpu)
{
unsigned int bank;
@@ -629,14 +629,8 @@ static __cpuinit void threshold_remove_device(unsigned int cpu)
}
}
-#else /* !CONFIG_HOTPLUG_CPU */
-static void threshold_remove_device(unsigned int cpu)
-{
-}
-#endif
-
/* get notified when a cpu comes on/off */
-static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
/* cpu was unsigned int to begin with */
@@ -659,9 +653,10 @@ static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-static struct notifier_block threshold_cpu_notifier __cpuinitdata = {
+static struct notifier_block threshold_cpu_notifier = {
.notifier_call = threshold_cpu_callback,
};
+#endif /* CONFIG_HOTPLUG_CPU */
static __init int threshold_init_device(void)
{
@@ -673,7 +668,7 @@ static __init int threshold_init_device(void)
if (err)
return err;
}
- register_cpu_notifier(&threshold_cpu_notifier);
+ register_hotcpu_notifier(&threshold_cpu_notifier);
return 0;
}
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index e71ed53b08fb..146924ba5df5 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -85,7 +85,8 @@
#define CSR_AGENT_MASK 0xffe0ffff
#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
-#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */
+#define MAX_NUM_CHASSIS 8 /* max number of chassis */
+#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
#define PHBS_PER_CALGARY 4
/* register offsets in Calgary's internal register space */
@@ -110,7 +111,8 @@ static const unsigned long phb_offsets[] = {
0xB000 /* PHB3 */
};
-void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES];
+static char bus_to_phb[MAX_PHB_BUS_NUM];
+void* tce_table_kva[MAX_PHB_BUS_NUM];
unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
static int translate_empty_slots __read_mostly = 0;
static int calgary_detected __read_mostly = 0;
@@ -119,7 +121,7 @@ static int calgary_detected __read_mostly = 0;
* the bitmap of PHBs the user requested that we disable
* translation on.
*/
-static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM);
+static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
static void tce_cache_blast(struct iommu_table *tbl);
@@ -452,7 +454,7 @@ static struct dma_mapping_ops calgary_dma_ops = {
static inline int busno_to_phbid(unsigned char num)
{
- return bus_to_phb(num) % PHBS_PER_CALGARY;
+ return bus_to_phb[num];
}
static inline unsigned long split_queue_offset(unsigned char num)
@@ -812,7 +814,7 @@ static int __init calgary_init(void)
int i, ret = -ENODEV;
struct pci_dev *dev = NULL;
- for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) {
+ for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
dev = pci_get_device(PCI_VENDOR_ID_IBM,
PCI_DEVICE_ID_IBM_CALGARY,
dev);
@@ -822,7 +824,7 @@ static int __init calgary_init(void)
calgary_init_one_nontraslated(dev);
continue;
}
- if (!tce_table_kva[i] && !translate_empty_slots) {
+ if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
pci_dev_put(dev);
continue;
}
@@ -842,7 +844,7 @@ error:
pci_dev_put(dev);
continue;
}
- if (!tce_table_kva[i] && !translate_empty_slots)
+ if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
continue;
calgary_disable_translation(dev);
calgary_free_tar(dev);
@@ -876,9 +878,10 @@ static inline int __init determine_tce_table_size(u64 ram)
void __init detect_calgary(void)
{
u32 val;
- int bus, table_idx;
+ int bus;
void *tbl;
- int detected = 0;
+ int calgary_found = 0;
+ int phb = -1;
/*
* if the user specified iommu=off or iommu=soft or we found
@@ -889,38 +892,46 @@ void __init detect_calgary(void)
specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
- for (bus = 0, table_idx = 0;
- bus <= num_online_nodes() * MAX_PHB_BUS_NUM;
- bus++) {
- BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM);
+ for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+ int dev;
+
+ tce_table_kva[bus] = NULL;
+ bus_to_phb[bus] = -1;
+
if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
continue;
+
+ /*
+ * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3)
+ * it is connected to releative to the clagary chip.
+ */
+ phb = (phb + 1) % PHBS_PER_CALGARY;
+
if (test_bit(bus, translation_disabled)) {
printk(KERN_INFO "Calgary: translation is disabled for "
"PHB 0x%x\n", bus);
/* skip this phb, don't allocate a tbl for it */
- tce_table_kva[table_idx] = NULL;
- table_idx++;
continue;
}
/*
- * scan the first slot of the PCI bus to see if there
- * are any devices present
+ * Scan the slots of the PCI bus to see if there is a device present.
+ * The parent bus will be the zero-ith device, so start at 1.
*/
- val = read_pci_config(bus, 1, 0, 0);
- if (val != 0xffffffff || translate_empty_slots) {
- tbl = alloc_tce_table();
- if (!tbl)
- goto cleanup;
- detected = 1;
- } else
- tbl = NULL;
-
- tce_table_kva[table_idx] = tbl;
- table_idx++;
+ for (dev = 1; dev < 8; dev++) {
+ val = read_pci_config(bus, dev, 0, 0);
+ if (val != 0xffffffff || translate_empty_slots) {
+ tbl = alloc_tce_table();
+ if (!tbl)
+ goto cleanup;
+ tce_table_kva[bus] = tbl;
+ bus_to_phb[bus] = phb;
+ calgary_found = 1;
+ break;
+ }
+ }
}
- if (detected) {
+ if (calgary_found) {
iommu_detected = 1;
calgary_detected = 1;
printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
@@ -929,9 +940,9 @@ void __init detect_calgary(void)
return;
cleanup:
- for (--table_idx; table_idx >= 0; --table_idx)
- if (tce_table_kva[table_idx])
- free_tce_table(tce_table_kva[table_idx]);
+ for (--bus; bus >= 0; --bus)
+ if (tce_table_kva[bus])
+ free_tce_table(tce_table_kva[bus]);
}
int __init calgary_iommu_init(void)
@@ -1002,7 +1013,7 @@ static int __init calgary_parse_options(char *p)
if (p == endp)
break;
- if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) {
+ if (bridge < MAX_PHB_BUS_NUM) {
printk(KERN_INFO "Calgary: disabling "
"translation for PHB 0x%x\n", bridge);
set_bit(bridge, translation_disabled);
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index c4c3cc36ac5b..aad7609d8e92 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -92,5 +92,7 @@ void __init no_iommu_init(void)
{
if (dma_ops)
return;
+
+ force_iommu = 0; /* no HW IOMMU */
dma_ops = &nommu_dma_ops;
}
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index ebdb77fe2057..6a55f87ba97f 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -31,9 +31,10 @@ struct dma_mapping_ops swiotlb_dma_ops = {
void pci_swiotlb_init(void)
{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
- if (!iommu_detected && !no_iommu &&
- (end_pfn > MAX_DMA32_PFN || force_iommu))
+ if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN)
swiotlb = 1;
+ if (swiotlb_force)
+ swiotlb = 1;
if (swiotlb) {
printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
swiotlb_init();
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 8a099ff1f8bc..34afad704824 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -521,8 +521,6 @@ static void discover_ebda(void)
void __init setup_arch(char **cmdline_p)
{
- unsigned long kernel_end;
-
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
@@ -596,8 +594,8 @@ void __init setup_arch(char **cmdline_p)
(table_end - table_start) << PAGE_SHIFT);
/* reserve kernel */
- kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
- reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
+ reserve_bootmem_generic(__pa_symbol(&_text),
+ __pa_symbol(&_end) - __pa_symbol(&_text));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 6fe58a634b5f..417de564456e 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -189,6 +189,7 @@ void __cpuinit cpu_init (void)
{
int cpu = stack_smp_processor_id();
struct tss_struct *t = &per_cpu(init_tss, cpu);
+ struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
unsigned long v;
char *estacks = NULL;
struct task_struct *me;
@@ -256,7 +257,7 @@ void __cpuinit cpu_init (void)
estacks += EXCEPTION_STKSZ;
break;
}
- t->ist[v] = (unsigned long)estacks;
+ orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
}
t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 5a1c0a3bf872..06af6ca60129 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -203,7 +203,7 @@ int __cpuinit init_smp_flush(void)
{
int i;
for_each_cpu_mask(i, cpu_possible_map) {
- spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+ spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
}
return 0;
}
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
index d3a9e79e954c..5530dda3f27a 100644
--- a/arch/x86_64/kernel/tce.c
+++ b/arch/x86_64/kernel/tce.c
@@ -96,7 +96,6 @@ static inline unsigned int table_size_to_number_of_entries(unsigned char size)
static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
{
unsigned int bitmapsz;
- unsigned int tce_table_index;
unsigned long bmppages;
int ret;
@@ -105,8 +104,7 @@ static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
/* set the tce table size - measured in entries */
tbl->it_size = table_size_to_number_of_entries(specified_table_size);
- tce_table_index = bus_to_phb(tbl->it_busno);
- tbl->it_base = (unsigned long)tce_table_kva[tce_table_index];
+ tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
if (!tbl->it_base) {
printk(KERN_ERR "Calgary: iommu_table_setparms: "
"no table allocated?!\n");
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index b9ff75992c16..7a9b18224182 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -28,6 +28,7 @@
#include
#ifdef CONFIG_ACPI
#include /* for PM timer frequency */
+#include
#endif
#include
#include
@@ -193,7 +194,7 @@ unsigned long profile_pc(struct pt_regs *regs)
is just accounted to the spinlock function.
Better would be to write these functions in assembler again
and check exactly. */
- if (in_lock_functions(pc)) {
+ if (!user_mode(regs) && in_lock_functions(pc)) {
char *v = *(char **)regs->rsp;
if ((v >= _stext && v <= _etext) ||
(v >= _sinittext && v <= _einittext) ||
@@ -953,11 +954,18 @@ __cpuinit int unsynchronized_tsc(void)
#ifdef CONFIG_SMP
if (apic_is_clustered_box())
return 1;
- /* Intel systems are normally all synchronized. Exceptions
- are handled in the check above. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- return 0;
#endif
+ /* Most intel systems have synchronized TSCs except for
+ multi node systems */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+#ifdef CONFIG_ACPI
+ /* But TSC doesn't tick in C3 so don't use it there */
+ if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
+ return 1;
+#endif
+ return 0;
+ }
+
/* Assume multi socket systems are not synchronized */
return num_present_cpus() > 1;
}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index eb39a2775236..b1249774d1e8 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -107,7 +107,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
}
static int kstack_depth_to_print = 12;
+#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
#ifdef CONFIG_KALLSYMS
# include
@@ -174,7 +178,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
break;
#endif
default:
- end = per_cpu(init_tss, cpu).ist[k];
+ end = per_cpu(orig_ist, cpu).ist[k];
break;
}
/*
@@ -254,7 +258,6 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
{
const unsigned cpu = safe_smp_processor_id();
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
- int i = 11;
unsigned used = 0;
printk("\nCall Trace:\n");
@@ -276,11 +279,20 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
unw_ret = show_trace_unwind(&info, NULL);
}
if (unw_ret > 0) {
- if (call_trace > 0)
+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+ print_symbol("DWARF2 unwinder stuck at %s\n",
+ UNW_PC(&info));
+ if ((long)UNW_SP(&info) < 0) {
+ printk("Leftover inexact backtrace:\n");
+ stack = (unsigned long *)UNW_SP(&info);
+ } else
+ printk("Full inexact backtrace again:\n");
+ } else if (call_trace >= 1)
return;
- printk("Legacy call trace:");
- i = 18;
- }
+ else
+ printk("Full inexact backtrace again:\n");
+ } else
+ printk("Inexact backtrace:\n");
}
/*
@@ -521,7 +533,7 @@ void __kprobes oops_end(unsigned long flags)
/* Nest count reaches zero, release the lock. */
spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
- panic("Oops");
+ panic("Fatal exception");
}
void __kprobes __die(const char * str, struct pt_regs * regs, long err)
@@ -1112,14 +1124,18 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);
+#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
call_trace = -1;
else if (strcmp(s, "both") == 0)
call_trace = 0;
- else if (strcmp(s, "new") == 0)
+ else if (strcmp(s, "newfallback") == 0)
call_trace = 1;
+ else if (strcmp(s, "new") == 0)
+ call_trace = 2;
return 1;
}
__setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index b50a7c7c47f8..3acf60ded2a0 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -2,7 +2,6 @@
#include
#include
#include
-#include
/*
* This discovers the pcibus <-> node mapping on AMD K8.
@@ -19,6 +18,7 @@
#define NR_LDT_BUS_NUMBER_REGISTERS 3
#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
/**
* fill_mp_bus_to_cpumask()
@@ -28,7 +28,8 @@
__init static int
fill_mp_bus_to_cpumask(void)
{
- int i, j, k;
+ struct pci_dev *nb_dev = NULL;
+ int i, j;
u32 ldtbus, nid;
static int lbnr[3] = {
LDT_BUS_NUMBER_REGISTER_0,
@@ -36,9 +37,8 @@ fill_mp_bus_to_cpumask(void)
LDT_BUS_NUMBER_REGISTER_2
};
- cache_k8_northbridges();
- for (k = 0; k < num_k8_northbridges; k++) {
- struct pci_dev *nb_dev = k8_northbridges[k];
+ while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 3c55c76c6fd5..2d48a7941d48 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include "pci.h"
@@ -164,11 +165,33 @@ static __init void unreachable_devices(void)
}
}
+static int disable_mcfg(struct dmi_system_id *d)
+{
+ printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+ /* Has broken MCFG table that makes the system hang when used */
+ {
+ .callback = disable_mcfg,
+ .ident = "Intel D3C5105 SDV",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+ },
+ },
+ {}
+};
+
void __init pci_mmcfg_init(void)
{
int i;
- if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ dmi_check_system(dmi_bad_mcfg);
+
+ if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -177,15 +200,6 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
- pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
- E820_RESERVED)) {
- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
- pci_mmcfg_config[0].base_address);
- printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
- return;
- }
-
/* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 5064d9383963..9aea23cc0dc5 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -212,7 +212,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_KILL:
ret = 0;
- if (child->state == EXIT_ZOMBIE) /* already dead */
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
child->ptrace &= ~PT_SINGLESTEP;
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 27e409089a7b..ce077d6bf3a0 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -487,11 +487,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (in_interrupt())
panic("Fatal exception in interrupt");
- if (panic_on_oops) {
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
+ if (panic_on_oops)
panic("Fatal exception");
- }
+
do_exit(err);
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index aae3123bf3ee..3a3aee08ec5f 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1561,7 +1561,7 @@ restart:
/* ->key must be copied to avoid race with cfq_exit_queue() */
k = __cic->key;
if (unlikely(!k)) {
- cfq_drop_dead_cic(ioc, cic);
+ cfq_drop_dead_cic(ioc, __cic);
goto restart;
}
diff --git a/block/elevator.c b/block/elevator.c
index bc7baeec0d10..9b72dc7c8a5c 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -765,7 +765,8 @@ void elv_unregister(struct elevator_type *e)
read_lock(&tasklist_lock);
do_each_thread(g, p) {
task_lock(p);
- e->ops.trim(p->io_context);
+ if (p->io_context)
+ e->ops.trim(p->io_context);
task_unlock(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 61d6b3c65b66..ddd9253f9d55 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -3628,6 +3628,8 @@ struct io_context *current_io_context(gfp_t gfp_flags)
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
ret->cic_root.rb_node = NULL;
+ /* make sure set_task_ioprio() sees the settings above */
+ smp_wmb();
tsk->io_context = ret;
}
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 96309b9660da..11abc7bf777e 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -285,6 +285,8 @@ static int __init acpi_ac_init(void)
{
int result;
+ if (acpi_disabled)
+ return -ENODEV;
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 81e970adeab3..1dda370f402b 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -129,11 +129,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
struct acpi_memory_info *info, *n;
+ if (!list_empty(&mem_device->res_list))
+ return 0;
+
status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
acpi_memory_get_resource, mem_device);
if (ACPI_FAILURE(status)) {
list_for_each_entry_safe(info, n, &mem_device->res_list, list)
kfree(info);
+ INIT_LIST_HEAD(&mem_device->res_list);
return -EINVAL;
}
@@ -230,17 +234,10 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
* (i.e. memory-hot-remove function)
*/
list_for_each_entry(info, &mem_device->res_list, list) {
- u64 start_pfn, end_pfn;
-
- start_pfn = info->start_addr >> PAGE_SHIFT;
- end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT;
-
- if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) {
- /* already enabled. try next area */
+ if (info->enabled) { /* just sanity check...*/
num_enabled++;
continue;
}
-
result = add_memory(node, info->start_addr, info->length);
if (result)
continue;
@@ -487,10 +484,8 @@ acpi_memory_register_notify_handler(acpi_handle handle,
status = is_memory_device(handle);
- if (ACPI_FAILURE(status)){
- ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+ if (ACPI_FAILURE(status))
return AE_OK; /* continue */
- }
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
acpi_memory_device_notify, NULL);
@@ -506,10 +501,8 @@ acpi_memory_deregister_notify_handler(acpi_handle handle,
status = is_memory_device(handle);
- if (ACPI_FAILURE(status)){
- ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+ if (ACPI_FAILURE(status))
return AE_OK; /* continue */
- }
status = acpi_remove_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 6e5221707d97..9810e2a55d0a 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -757,6 +757,9 @@ static int __init acpi_battery_init(void)
{
int result;
+ if (acpi_disabled)
+ return -ENODEV;
+
acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir)
return -ENODEV;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b2977695e120..279c4bac92e5 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -68,7 +69,8 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
- ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+ handle));
return -ENODEV;
}
@@ -192,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
/* Make sure this is a valid target state */
if (!device->flags.power_manageable) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
device->kobj.name));
return -ENODEV;
}
@@ -738,7 +740,10 @@ static int __init acpi_init(void)
return -ENODEV;
}
- firmware_register(&acpi_subsys);
+ result = firmware_register(&acpi_subsys);
+ if (result < 0)
+ printk(KERN_WARNING "%s: firmware_register error: %d\n",
+ __FUNCTION__, result);
result = acpi_bus_init();
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 1c0a39d8b04e..578b99b71d9c 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -58,8 +58,8 @@ struct dock_dependent_device {
};
#define DOCK_DOCKING 0x00000001
-#define DOCK_EVENT KOBJ_DOCK
-#define UNDOCK_EVENT KOBJ_UNDOCK
+#define DOCK_EVENT 3
+#define UNDOCK_EVENT 2
static struct dock_station *dock_station;
@@ -322,11 +322,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
static void dock_event(struct dock_station *ds, u32 event, int num)
{
- struct acpi_device *device;
-
- device = dock_create_acpi_device(ds->handle);
- if (device)
- kobject_uevent(&device->kobj, num);
+ /*
+ * we don't do events until someone tells me that
+ * they would like to have them.
+ */
}
/**
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 32c9d88fd196..1ba2db671865 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -91,6 +91,14 @@ enum {
HK_EVENT_ENTERRING_S5,
};
+enum conf_entry_enum {
+ bus_handle = 0,
+ bus_method = 1,
+ action_handle = 2,
+ method = 3,
+ LAST_CONF_ENTRY
+};
+
/* procdir we use */
static struct proc_dir_entry *hotkey_proc_dir;
static struct proc_dir_entry *hotkey_config;
@@ -244,19 +252,15 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
static char *format_result(union acpi_object *object)
{
- char *buf = NULL;
-
- buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
- if (buf)
- memset(buf, 0, RESULT_STR_LEN);
- else
- goto do_fail;
+ char *buf;
+ buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
+ if (!buf)
+ return NULL;
/* Now, just support integer type */
if (object->type == ACPI_TYPE_INTEGER)
sprintf(buf, "%d\n", (u32) object->integer.value);
- do_fail:
- return (buf);
+ return buf;
}
static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
@@ -486,98 +490,102 @@ static void free_hotkey_device(union acpi_hotkey *key)
static void free_hotkey_buffer(union acpi_hotkey *key)
{
+ /* key would never be null, action method could be */
kfree(key->event_hotkey.action_method);
}
static void free_poll_hotkey_buffer(union acpi_hotkey *key)
{
+ /* key would never be null, others could be*/
kfree(key->poll_hotkey.action_method);
kfree(key->poll_hotkey.poll_method);
kfree(key->poll_hotkey.poll_result);
}
static int
-init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
- char *method, int std_num, int external_num)
+init_hotkey_device(union acpi_hotkey *key, char **config_entry,
+ int std_num, int external_num)
{
acpi_handle tmp_handle;
acpi_status status = AE_OK;
-
if (std_num < 0 || IS_POLL(std_num) || !key)
goto do_fail;
- if (!bus_str || !action_str || !method)
+ if (!config_entry[bus_handle] || !config_entry[action_handle]
+ || !config_entry[method])
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_EVENT;
key->link.hotkey_standard_num = std_num;
key->event_hotkey.flag = 0;
- key->event_hotkey.action_method = method;
+ key->event_hotkey.action_method = config_entry[method];
- status =
- acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle));
+ status = acpi_get_handle(NULL, config_entry[bus_handle],
+ &(key->event_hotkey.bus_handle));
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
key->event_hotkey.external_hotkey_num = external_num;
- status =
- acpi_get_handle(NULL, action_str,
+ status = acpi_get_handle(NULL, config_entry[action_handle],
&(key->event_hotkey.action_handle));
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
status = acpi_get_handle(key->event_hotkey.action_handle,
- method, &tmp_handle);
+ config_entry[method], &tmp_handle);
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
return AE_OK;
- do_fail:
+do_fail_zero:
+ key->event_hotkey.action_method = NULL;
+do_fail:
return -ENODEV;
}
static int
-init_poll_hotkey_device(union acpi_hotkey *key,
- char *poll_str,
- char *poll_method,
- char *action_str, char *action_method, int std_num)
+init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
+ int std_num)
{
acpi_status status = AE_OK;
acpi_handle tmp_handle;
-
if (std_num < 0 || IS_EVENT(std_num) || !key)
goto do_fail;
-
- if (!poll_str || !poll_method || !action_str || !action_method)
+ if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
+ !config_entry[action_handle] || !config_entry[method])
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_POLLING;
key->link.hotkey_standard_num = std_num;
key->poll_hotkey.flag = 0;
- key->poll_hotkey.poll_method = poll_method;
- key->poll_hotkey.action_method = action_method;
+ key->poll_hotkey.poll_method = config_entry[bus_method];
+ key->poll_hotkey.action_method = config_entry[method];
- status =
- acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle));
+ status = acpi_get_handle(NULL, config_entry[bus_handle],
+ &(key->poll_hotkey.poll_handle));
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
status = acpi_get_handle(key->poll_hotkey.poll_handle,
- poll_method, &tmp_handle);
+ config_entry[bus_method], &tmp_handle);
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
status =
- acpi_get_handle(NULL, action_str,
+ acpi_get_handle(NULL, config_entry[action_handle],
&(key->poll_hotkey.action_handle));
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
status = acpi_get_handle(key->poll_hotkey.action_handle,
- action_method, &tmp_handle);
+ config_entry[method], &tmp_handle);
if (ACPI_FAILURE(status))
- goto do_fail;
+ goto do_fail_zero;
key->poll_hotkey.poll_result =
(union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
if (!key->poll_hotkey.poll_result)
- goto do_fail;
+ goto do_fail_zero;
return AE_OK;
- do_fail:
+
+do_fail_zero:
+ key->poll_hotkey.poll_method = NULL;
+ key->poll_hotkey.action_method = NULL;
+do_fail:
return -ENODEV;
}
@@ -652,17 +660,18 @@ static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
}
static int
-get_parms(char *config_record,
- int *cmd,
- char **bus_handle,
- char **bus_method,
- char **action_handle,
- char **method, int *internal_event_num, int *external_event_num)
+get_parms(char *config_record, int *cmd, char **config_entry,
+ int *internal_event_num, int *external_event_num)
{
+/* the format of *config_record =
+ * "1:\d+:*" : "cmd:internal_event_num"
+ * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
+ * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
+ */
char *tmp, *tmp1, count;
+ int i;
sscanf(config_record, "%d", cmd);
-
if (*cmd == 1) {
if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
2)
@@ -674,59 +683,27 @@ get_parms(char *config_record,
if (!tmp)
goto do_fail;
tmp++;
- tmp1 = strchr(tmp, ':');
- if (!tmp1)
- goto do_fail;
-
- count = tmp1 - tmp;
- *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
- if (!*bus_handle)
- goto do_fail;
- strncpy(*bus_handle, tmp, count);
- *(*bus_handle + count) = 0;
-
- tmp = tmp1;
- tmp++;
- tmp1 = strchr(tmp, ':');
- if (!tmp1)
- goto do_fail;
- count = tmp1 - tmp;
- *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL);
- if (!*bus_method)
- goto do_fail;
- strncpy(*bus_method, tmp, count);
- *(*bus_method + count) = 0;
-
- tmp = tmp1;
- tmp++;
- tmp1 = strchr(tmp, ':');
- if (!tmp1)
- goto do_fail;
- count = tmp1 - tmp;
- *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
- if (!*action_handle)
- goto do_fail;
- strncpy(*action_handle, tmp, count);
- *(*action_handle + count) = 0;
-
- tmp = tmp1;
- tmp++;
- tmp1 = strchr(tmp, ':');
- if (!tmp1)
- goto do_fail;
- count = tmp1 - tmp;
- *method = (char *)kmalloc(count + 1, GFP_KERNEL);
- if (!*method)
- goto do_fail;
- strncpy(*method, tmp, count);
- *(*method + count) = 0;
-
- if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <=
- 0)
- goto do_fail;
-
- return 6;
- do_fail:
+ for (i = 0; i < LAST_CONF_ENTRY; i++) {
+ tmp1 = strchr(tmp, ':');
+ if (!tmp1) {
+ goto do_fail;
+ }
+ count = tmp1 - tmp;
+ config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
+ if (!config_entry[i])
+ goto handle_failure;
+ strncpy(config_entry[i], tmp, count);
+ tmp = tmp1 + 1;
+ }
+ if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
+ goto handle_failure;
+ if (!IS_OTHERS(*internal_event_num)) {
+ return 6;
+ }
+handle_failure:
+ while (i-- > 0)
+ kfree(config_entry[i]);
+do_fail:
return -1;
}
@@ -736,50 +713,34 @@ static ssize_t hotkey_write_config(struct file *file,
size_t count, loff_t * data)
{
char *config_record = NULL;
- char *bus_handle = NULL;
- char *bus_method = NULL;
- char *action_handle = NULL;
- char *method = NULL;
+ char *config_entry[LAST_CONF_ENTRY];
int cmd, internal_event_num, external_event_num;
int ret = 0;
- union acpi_hotkey *key = NULL;
+ union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-
- config_record = (char *)kmalloc(count + 1, GFP_KERNEL);
- if (!config_record)
+ if (!key)
return -ENOMEM;
+ config_record = kzalloc(count + 1, GFP_KERNEL);
+ if (!config_record) {
+ kfree(key);
+ return -ENOMEM;
+ }
+
if (copy_from_user(config_record, buffer, count)) {
kfree(config_record);
+ kfree(key);
printk(KERN_ERR PREFIX "Invalid data\n");
return -EINVAL;
}
- config_record[count] = 0;
-
- ret = get_parms(config_record,
- &cmd,
- &bus_handle,
- &bus_method,
- &action_handle,
- &method, &internal_event_num, &external_event_num);
-
+ ret = get_parms(config_record, &cmd, config_entry,
+ &internal_event_num, &external_event_num);
kfree(config_record);
- if (IS_OTHERS(internal_event_num))
- goto do_fail;
if (ret != 6) {
- do_fail:
- kfree(bus_handle);
- kfree(bus_method);
- kfree(action_handle);
- kfree(method);
printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
return -EINVAL;
}
- key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
- if (!key)
- goto do_fail;
- memset(key, 0, sizeof(union acpi_hotkey));
if (cmd == 1) {
union acpi_hotkey *tmp = NULL;
tmp = get_hotkey_by_event(&global_hotkey_list,
@@ -791,34 +752,19 @@ static ssize_t hotkey_write_config(struct file *file,
goto cont_cmd;
}
if (IS_EVENT(internal_event_num)) {
- kfree(bus_method);
- ret = init_hotkey_device(key, bus_handle, action_handle, method,
- internal_event_num,
- external_event_num);
- } else
- ret = init_poll_hotkey_device(key, bus_handle, bus_method,
- action_handle, method,
- internal_event_num);
- if (ret) {
- kfree(bus_handle);
- kfree(action_handle);
- if (IS_EVENT(internal_event_num))
- free_hotkey_buffer(key);
- else
- free_poll_hotkey_buffer(key);
- kfree(key);
- printk(KERN_ERR PREFIX "Invalid hotkey\n");
- return -EINVAL;
+ if (init_hotkey_device(key, config_entry,
+ internal_event_num, external_event_num))
+ goto init_hotkey_fail;
+ } else {
+ if (init_poll_hotkey_device(key, config_entry,
+ internal_event_num))
+ goto init_poll_hotkey_fail;
}
-
- cont_cmd:
- kfree(bus_handle);
- kfree(action_handle);
-
+cont_cmd:
switch (cmd) {
case 0:
- if (get_hotkey_by_event
- (&global_hotkey_list, key->link.hotkey_standard_num))
+ if (get_hotkey_by_event(&global_hotkey_list,
+ key->link.hotkey_standard_num))
goto fail_out;
else
hotkey_add(key);
@@ -827,6 +773,7 @@ static ssize_t hotkey_write_config(struct file *file,
hotkey_remove(key);
break;
case 2:
+ /* key is kfree()ed if matched*/
if (hotkey_update(key))
goto fail_out;
break;
@@ -835,11 +782,22 @@ static ssize_t hotkey_write_config(struct file *file,
break;
}
return count;
- fail_out:
- if (IS_EVENT(internal_event_num))
- free_hotkey_buffer(key);
- else
- free_poll_hotkey_buffer(key);
+
+init_poll_hotkey_fail: /* failed init_poll_hotkey_device */
+ kfree(config_entry[bus_method]);
+ config_entry[bus_method] = NULL;
+init_hotkey_fail: /* failed init_hotkey_device */
+ kfree(config_entry[method]);
+fail_out:
+ kfree(config_entry[bus_handle]);
+ kfree(config_entry[action_handle]);
+ /* No double free since elements =NULL for error cases */
+ if (IS_EVENT(internal_event_num)) {
+ if (config_entry[bus_method])
+ kfree(config_entry[bus_method]);
+ free_hotkey_buffer(key); /* frees [method] */
+ } else
+ free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */
kfree(key);
printk(KERN_ERR PREFIX "invalid key\n");
return -EINVAL;
@@ -923,10 +881,9 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
union acpi_hotkey *key;
- arg = (char *)kmalloc(count + 1, GFP_KERNEL);
+ arg = kzalloc(count + 1, GFP_KERNEL);
if (!arg)
return -ENOMEM;
- arg[count] = 0;
if (copy_from_user(arg, buffer, count)) {
kfree(arg);
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
index 84239d51dc0c..6809c283ec58 100644
--- a/drivers/acpi/i2c_ec.c
+++ b/drivers/acpi/i2c_ec.c
@@ -330,7 +330,7 @@ static int acpi_ec_hc_add(struct acpi_device *device)
status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
- kfree(ec_hc->smbus);
+ kfree(ec_hc);
kfree(smbus);
return -EIO;
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index b7d1514cd199..507f051d1cef 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -746,6 +746,16 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
handle, units, timeout));
+ /*
+ * This can be called during resume with interrupts off.
+ * Like boot-time, we should be single threaded and will
+ * always get the lock if we try -- timeout or not.
+ * If this doesn't succeed, then we will oops courtesy of
+ * might_sleep() in down().
+ */
+ if (!down_trylock(sem))
+ return AE_OK;
+
switch (timeout) {
/*
* No Wait:
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index db7b350a5035..62bef0b3b614 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1714,6 +1714,9 @@ static int __init acpi_sbs_init(void)
{
int result = 0;
+ if (acpi_disabled)
+ return -ENODEV;
+
init_MUTEX(&sbs_sem);
if (capacity_mode != DEF_CAPACITY_UNIT
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5fcb50c7b778..698a1540e303 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -4,6 +4,7 @@
#include
#include
+#include
#include
#include
@@ -113,6 +114,8 @@ static struct kset acpi_namespace_kset = {
static void acpi_device_register(struct acpi_device *device,
struct acpi_device *parent)
{
+ int err;
+
/*
* Linkage
* -------
@@ -138,7 +141,10 @@ static void acpi_device_register(struct acpi_device *device,
device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns;
device->kobj.kset = &acpi_namespace_kset;
- kobject_register(&device->kobj);
+ err = kobject_register(&device->kobj);
+ if (err < 0)
+ printk(KERN_WARNING "%s: kobject_register error: %d\n",
+ __FUNCTION__, err);
create_sysfs_device_files(device);
}
@@ -1450,7 +1456,9 @@ static int __init acpi_scan_init(void)
if (acpi_disabled)
return 0;
- kset_register(&acpi_namespace_kset);
+ result = kset_register(&acpi_namespace_kset);
+ if (result < 0)
+ printk(KERN_ERR PREFIX "kset_register error: %d\n", result);
result = bus_register(&acpi_bus_type);
if (result) {
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index f48227f4c8c9..d0d84c43a9d4 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -262,7 +262,7 @@ acpi_evaluate_integer(acpi_handle handle,
if (!data)
return AE_BAD_PARAMETER;
- element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+ element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
if (!element)
return AE_NO_MEMORY;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index d7de1753e094..e9b0957f15d1 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -64,7 +64,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
"Node %d Mapped: %8lu kB\n"
"Node %d AnonPages: %8lu kB\n"
"Node %d PageTables: %8lu kB\n"
- "Node %d NFS Unstable: %8lu kB\n"
+ "Node %d NFS_Unstable: %8lu kB\n"
"Node %d Bounce: %8lu kB\n"
"Node %d Slab: %8lu kB\n",
nid, K(i.totalram),
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index c2d621632383..3ef9d514b916 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -139,7 +139,7 @@ static int __cpuinit topology_sysfs_init(void)
(void *)(long)i);
}
- register_cpu_notifier(&topology_cpu_notifier);
+ register_hotcpu_notifier(&topology_cpu_notifier);
return 0;
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 5109fa37c662..ad1d7065a1b2 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4177,6 +4177,11 @@ static int __init floppy_init(void)
int i, unit, drive;
int err, dr;
+#if defined(CONFIG_PPC_MERGE)
+ if (check_legacy_ioport(FDC1))
+ return -ENODEV;
+#endif
+
raw_cmd = NULL;
for (dr = 0; dr < N_DRIVE; dr++) {
@@ -4234,13 +4239,6 @@ static int __init floppy_init(void)
}
use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC_MERGE)
- if (check_legacy_ioport(FDC1)) {
- del_timer(&fd_timeout);
- err = -ENODEV;
- goto out_unreg_region;
- }
-#endif
fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) {
del_timer(&fd_timeout);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0a1b1ea36ddc..bdbade9a5cf5 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -300,6 +300,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
lo->disk->disk_name, result);
goto harderror;
}
+
+ if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+ printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+ lo->disk->disk_name,
+ (unsigned long)ntohl(reply.magic));
+ result = -EPROTO;
+ goto harderror;
+ }
+
req = nbd_find_request(lo, reply.handle);
if (unlikely(IS_ERR(req))) {
result = PTR_ERR(req);
@@ -312,13 +321,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
- if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
- printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
- lo->disk->disk_name,
- (unsigned long)ntohl(reply.magic));
- result = -EPROTO;
- goto harderror;
- }
if (ntohl(reply.error)) {
printk(KERN_ERR "%s: Other side returned error (%d)\n",
lo->disk->disk_name, ntohl(reply.error));
@@ -339,7 +341,8 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
printk(KERN_ERR "%s: Receive data failed (result %d)\n",
lo->disk->disk_name,
result);
- goto harderror;
+ req->errors++;
+ return req;
}
dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
lo->disk->disk_name, req, bvec->bv_len);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index bde2c64b6346..451b996bba91 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2577,19 +2577,19 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
case PKT_CTRL_CMD_SETUP:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
ret = pkt_setup_dev(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
case PKT_CTRL_CMD_TEARDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
ret = pkt_remove_dev(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
case PKT_CTRL_CMD_STATUS:
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
pkt_get_status(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index b6ee50a2916d..fa7082489765 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -266,7 +266,7 @@ repeat:
goto out;
if (req->cmd != READ) {
- printk("GSCD: bad cmd %lu\n", rq_data_dir(req));
+ printk("GSCD: bad cmd %u\n", rq_data_dir(req));
end_request(req, 0);
goto repeat;
}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 5bb2234a9094..39a7f685e3fd 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -175,6 +175,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
}
break;
+ case R200_EMIT_VAP_CTL:{
+ RING_LOCALS;
+ BEGIN_RING(2);
+ OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+ ADVANCE_RING();
+ }
+ break;
+
case RADEON_EMIT_RB3D_COLORPITCH:
case RADEON_EMIT_RE_LINE_PATTERN:
case RADEON_EMIT_SE_LINE_WIDTH:
@@ -202,7 +210,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
case R200_EMIT_TFACTOR_0:
case R200_EMIT_VTX_FMT_0:
- case R200_EMIT_VAP_CTL:
case R200_EMIT_MATRIX_SELECT_0:
case R200_EMIT_TEX_PROC_CTL_2:
case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 41db8060e8f7..017f755632a3 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -311,7 +311,8 @@ static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
/* CD went away; no more connection */
pr_debug("hvsi%i: CD dropped\n", hp->index);
hp->mctrl &= TIOCM_CD;
- if (!(hp->tty->flags & CLOCAL))
+ /* If userland hasn't done an open(2) yet, hp->tty is NULL. */
+ if (hp->tty && !(hp->tty->flags & CLOCAL))
*to_hangup = hp->tty;
}
break;
@@ -986,10 +987,7 @@ static void hvsi_write_worker(void *arg)
start_j = 0;
#endif /* DEBUG */
wake_up_all(&hp->emptyq);
- if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
- && hp->tty->ldisc.write_wakeup)
- hp->tty->ldisc.write_wakeup(hp->tty);
- wake_up_interruptible(&hp->tty->write_wait);
+ tty_wakeup(hp->tty);
}
out:
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index be61f22ee7bb..d37ced0d132b 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -107,10 +107,14 @@ found:
if (err) {
printk(KERN_ERR PFX "RNG registering failed (%d)\n",
err);
- goto out;
+ goto err_unmap;
}
out:
return err;
+
+err_unmap:
+ iounmap(mem);
+ goto out;
}
static void __exit mod_exit(void)
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 6594bd5645f4..ccd7e7102234 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -164,7 +164,7 @@ static int __init mod_init(void)
if (err) {
printk(KERN_ERR PFX "RNG registering failed (%d)\n",
err);
- goto out;
+ goto err_unmap;
}
out:
return err;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 819516b35a79..a01d796d1eeb 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -25,12 +25,12 @@
#include
#include
#include
+#include
#include
-#include
+#include
#include
#include
-#include
#define RNG_OUT_REG 0x00 /* Output register */
#define RNG_STAT_REG 0x04 /* Status register
@@ -52,7 +52,7 @@
static void __iomem *rng_base;
static struct clk *rng_ick;
-static struct device *rng_dev;
+static struct platform_device *rng_dev;
static u32 omap_rng_read_reg(int reg)
{
@@ -83,9 +83,8 @@ static struct hwrng omap_rng_ops = {
.data_read = omap_rng_data_read,
};
-static int __init omap_rng_probe(struct device *dev)
+static int __init omap_rng_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct resource *res, *mem;
int ret;
@@ -95,16 +94,14 @@ static int __init omap_rng_probe(struct device *dev)
*/
BUG_ON(rng_dev);
- if (cpu_is_omap24xx()) {
+ if (cpu_is_omap24xx()) {
rng_ick = clk_get(NULL, "rng_ick");
if (IS_ERR(rng_ick)) {
- dev_err(dev, "Could not get rng_ick\n");
+ dev_err(&pdev->dev, "Could not get rng_ick\n");
ret = PTR_ERR(rng_ick);
return ret;
- }
- else {
- clk_use(rng_ick);
- }
+ } else
+ clk_enable(rng_ick);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -117,7 +114,7 @@ static int __init omap_rng_probe(struct device *dev)
if (mem == NULL)
return -EBUSY;
- dev_set_drvdata(dev, mem);
+ dev_set_drvdata(&pdev->dev, mem);
rng_base = (u32 __iomem *)io_p2v(res->start);
ret = hwrng_register(&omap_rng_ops);
@@ -127,25 +124,25 @@ static int __init omap_rng_probe(struct device *dev)
return ret;
}
- dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
+ dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
omap_rng_read_reg(RNG_REV_REG));
omap_rng_write_reg(RNG_MASK_REG, 0x1);
- rng_dev = dev;
+ rng_dev = pdev;
return 0;
}
-static int __exit omap_rng_remove(struct device *dev)
+static int __exit omap_rng_remove(struct platform_device *pdev)
{
- struct resource *mem = dev_get_drvdata(dev);
+ struct resource *mem = dev_get_drvdata(&pdev->dev);
hwrng_unregister(&omap_rng_ops);
omap_rng_write_reg(RNG_MASK_REG, 0x0);
if (cpu_is_omap24xx()) {
- clk_unuse(rng_ick);
+ clk_disable(rng_ick);
clk_put(rng_ick);
}
@@ -157,18 +154,16 @@ static int __exit omap_rng_remove(struct device *dev)
#ifdef CONFIG_PM
-static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
{
omap_rng_write_reg(RNG_MASK_REG, 0x0);
-
return 0;
}
-static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_resume(struct platform_device *pdev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x1);
-
- return 1;
+ return 0;
}
#else
@@ -179,9 +174,11 @@ static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
#endif
-static struct device_driver omap_rng_driver = {
- .name = "omap_rng",
- .bus = &platform_bus_type,
+static struct platform_driver omap_rng_driver = {
+ .driver = {
+ .name = "omap_rng",
+ .owner = THIS_MODULE,
+ },
.probe = omap_rng_probe,
.remove = __exit_p(omap_rng_remove),
.suspend = omap_rng_suspend,
@@ -193,12 +190,12 @@ static int __init omap_rng_init(void)
if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
return -ENODEV;
- return driver_register(&omap_rng_driver);
+ return platform_driver_register(&omap_rng_driver);
}
static void __exit omap_rng_exit(void)
{
- driver_unregister(&omap_rng_driver);
+ platform_driver_unregister(&omap_rng_driver);
}
module_init(omap_rng_init);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0aa5d608fe6f..843d34c8627c 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3428,6 +3428,7 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
if (rv) {
+ rv->user = NULL;
rv->done = free_recv_msg;
atomic_inc(&recv_msg_inuse_count);
}
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 056ebe84b81d..3e90aac37510 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
-static struct kbd_struct kbd0;
int spawnpid, spawnsig;
@@ -223,13 +222,13 @@ static void kd_nosound(unsigned long ignored)
{
struct list_head *node;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_TONE, 0);
+ input_inject_event(handle, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_BELL, 0);
+ input_inject_event(handle, EV_SND, SND_BELL, 0);
}
}
}
@@ -247,11 +246,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_TONE, hz);
+ input_inject_event(handle, EV_SND, SND_TONE, hz);
break;
}
if (test_bit(SND_BELL, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_BELL, 1);
+ input_inject_event(handle, EV_SND, SND_BELL, 1);
break;
}
}
@@ -272,15 +271,15 @@ int kbd_rate(struct kbd_repeat *rep)
unsigned int d = 0;
unsigned int p = 0;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
struct input_dev *dev = handle->dev;
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
- input_event(dev, EV_REP, REP_DELAY, rep->delay);
+ input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
- input_event(dev, EV_REP, REP_PERIOD, rep->period);
+ input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
@@ -988,7 +987,7 @@ static inline unsigned char getleds(void)
* interrupt routines for this thing allows us to easily mask
* this when we don't want any of the above to happen.
* This allows for easy and efficient race-condition prevention
- * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
+ * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
*/
static void kbd_bh(unsigned long dummy)
@@ -998,11 +997,11 @@ static void kbd_bh(unsigned long dummy)
if (leds != ledstate) {
list_for_each(node, &kbd_handler.h_list) {
- struct input_handle * handle = to_handle_h(node);
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
+ struct input_handle *handle = to_handle_h(node);
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
}
@@ -1011,23 +1010,6 @@ static void kbd_bh(unsigned long dummy)
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
-/*
- * This allows a newly plugged keyboard to pick the LED state.
- */
-static void kbd_refresh_leds(struct input_handle *handle)
-{
- unsigned char leds = ledstate;
-
- tasklet_disable(&keyboard_tasklet);
- if (leds != 0xff) {
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
- }
- tasklet_enable(&keyboard_tasklet);
-}
-
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
@@ -1043,7 +1025,7 @@ static const unsigned short x86_keycodes[256] =
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
- 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+ 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -1065,38 +1047,55 @@ extern void sun_do_break(void);
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
- if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ int code;
switch (keycode) {
case KEY_PAUSE:
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
- return 0;
+ break;
+
case KEY_HANGEUL:
if (!up_flag)
put_queue(vc, 0xf2);
- return 0;
+ break;
+
case KEY_HANJA:
if (!up_flag)
put_queue(vc, 0xf1);
- return 0;
- }
+ break;
- if (keycode == KEY_SYSRQ && sysrq_alt) {
- put_queue(vc, 0x54 | up_flag);
- return 0;
- }
+ case KEY_SYSRQ:
+ /*
+ * Real AT keyboards (that's what we're trying
+ * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
+ * pressing PrtSc/SysRq alone, but simply 0x54
+ * when pressing Alt+PrtSc/SysRq.
+ */
+ if (sysrq_alt) {
+ put_queue(vc, 0x54 | up_flag);
+ } else {
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x2a | up_flag);
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x37 | up_flag);
+ }
+ break;
- if (x86_keycodes[keycode] & 0x100)
- put_queue(vc, 0xe0);
+ default:
+ if (keycode > 255)
+ return -1;
- put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
+ code = x86_keycodes[keycode];
+ if (!code)
+ return -1;
- if (keycode == KEY_SYSRQ) {
- put_queue(vc, 0xe0);
- put_queue(vc, 0x37 | up_flag);
+ if (code & 0x100)
+ put_queue(vc, 0xe0);
+ put_queue(vc, (code & 0x7f) | up_flag);
+
+ break;
}
return 0;
@@ -1298,16 +1297,15 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!handle)
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
input_open_device(handle);
- kbd_refresh_leds(handle);
return handle;
}
@@ -1318,6 +1316,24 @@ static void kbd_disconnect(struct input_handle *handle)
kfree(handle);
}
+/*
+ * Start keyboard handler on the new keyboard by refreshing LED state to
+ * match the rest of the system.
+ */
+static void kbd_start(struct input_handle *handle)
+{
+ unsigned char leds = ledstate;
+
+ tasklet_disable(&keyboard_tasklet);
+ if (leds != 0xff) {
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
+ }
+ tasklet_enable(&keyboard_tasklet);
+}
+
static struct input_device_id kbd_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1338,6 +1354,7 @@ static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
+ .start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
@@ -1346,15 +1363,15 @@ int __init kbd_init(void)
{
int i;
- kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
- kbd0.ledmode = LED_SHOW_FLAGS;
- kbd0.lockstate = KBD_DEFLOCK;
- kbd0.slockstate = 0;
- kbd0.modeflags = KBD_DEFMODE;
- kbd0.kbdmode = VC_XLATE;
-
- for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
- kbd_table[i] = kbd0;
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ kbd_table[i].ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].ledmode = LED_SHOW_FLAGS;
+ kbd_table[i].lockstate = KBD_DEFLOCK;
+ kbd_table[i].slockstate = 0;
+ kbd_table[i].modeflags = KBD_DEFMODE;
+ kbd_table[i].kbdmode = VC_XLATE;
+ }
input_register_handler(&kbd_handler);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 4ea7bd5f4f56..a369dd6877d8 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -142,6 +142,7 @@ typedef struct _moxa_board_conf {
static moxa_board_conf moxa_boards[MAX_BOARDS];
static void __iomem *moxaBaseAddr[MAX_BOARDS];
+static int loadstat[MAX_BOARDS];
struct moxa_str {
int type;
@@ -1688,6 +1689,8 @@ int MoxaDriverPoll(void)
if (moxaCard == 0)
return (-1);
for (card = 0; card < MAX_BOARDS; card++) {
+ if (loadstat[card] == 0)
+ continue;
if ((ports = moxa_boards[card].numPorts) == 0)
continue;
if (readb(moxaIntPend[card]) == 0xff) {
@@ -2903,6 +2906,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
}
break;
}
+ loadstat[cardno] = 1;
return (0);
}
@@ -2920,7 +2924,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
len1 = len >> 1;
ptr = (ushort *) moxaBuff;
for (i = 0; i < len1; i++)
- usum += *(ptr + i);
+ usum += le16_to_cpu(*(ptr + i));
retry = 0;
do {
len1 = len >> 1;
@@ -2992,7 +2996,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
wlen = len >> 1;
uptr = (ushort *) moxaBuff;
for (i = 0; i < wlen; i++)
- usum += uptr[i];
+ usum += le16_to_cpu(uptr[i]);
retry = 0;
j = 0;
do {
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 645eb81cb5a9..84e5a68635f1 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -221,7 +221,6 @@ static struct nsc_gpio_ops pc8736x_gpio_ops = {
.gpio_change = pc8736x_gpio_change,
.gpio_current = pc8736x_gpio_current
};
-EXPORT_SYMBOL(pc8736x_gpio_ops);
static int pc8736x_gpio_open(struct inode *inode, struct file *file)
{
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index afc6eda602f7..07e0b75f2338 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -374,7 +374,12 @@ scdrv_init(void)
struct sysctl_data_s *scd;
void *salbuf;
dev_t first_dev, dev;
- nasid_t event_nasid = ia64_sn_get_console_nasid();
+ nasid_t event_nasid;
+
+ if (!ia64_platform_is("sn2"))
+ return -ENODEV;
+
+ event_nasid = ia64_sn_get_console_nasid();
if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
SYSCTL_BASENAME) < 0) {
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index b2dbbdb1bf81..2f07b085536b 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -391,8 +391,8 @@ static MGSL_PARAMS default_params = {
#define DESC_LIST_SIZE 4096
#define MASK_PARITY BIT1
-#define MASK_FRAMING BIT2
-#define MASK_BREAK BIT3
+#define MASK_FRAMING BIT0
+#define MASK_BREAK BIT14
#define MASK_OVERRUN BIT4
#define GSR 0x00 /* global status */
@@ -1800,17 +1800,17 @@ static void rx_async(struct slgt_info *info)
stat = 0;
- if ((status = *(p+1) & (BIT9 + BIT8))) {
- if (status & BIT9)
+ if ((status = *(p+1) & (BIT1 + BIT0))) {
+ if (status & BIT1)
icount->parity++;
- else if (status & BIT8)
+ else if (status & BIT0)
icount->frame++;
/* discard char if tty control flags say so */
if (status & info->ignore_status_mask)
continue;
- if (status & BIT9)
+ if (status & BIT1)
stat = TTY_PARITY;
- else if (status & BIT8)
+ else if (status & BIT0)
stat = TTY_FRAME;
}
if (tty) {
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index bfdb90242a90..bb0d9199e994 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -153,6 +153,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
static int tty_fasync(int fd, struct file * filp, int on);
static void release_mem(struct tty_struct *tty, int idx);
+/**
+ * alloc_tty_struct - allocate a tty object
+ *
+ * Return a new empty tty structure. The data fields have not
+ * been initialized in any way but has been zeroed
+ *
+ * Locking: none
+ * FIXME: use kzalloc
+ */
static struct tty_struct *alloc_tty_struct(void)
{
@@ -166,6 +175,15 @@ static struct tty_struct *alloc_tty_struct(void)
static void tty_buffer_free_all(struct tty_struct *);
+/**
+ * free_tty_struct - free a disused tty
+ * @tty: tty struct to free
+ *
+ * Free the write buffers, tty queue and tty memory itself.
+ *
+ * Locking: none. Must be called after tty is definitely unused
+ */
+
static inline void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
@@ -175,6 +193,17 @@ static inline void free_tty_struct(struct tty_struct *tty)
#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
+/**
+ * tty_name - return tty naming
+ * @tty: tty structure
+ * @buf: buffer for output
+ *
+ * Convert a tty structure into a name. The name reflects the kernel
+ * naming policy and if udev is in use may not reflect user space
+ *
+ * Locking: none
+ */
+
char *tty_name(struct tty_struct *tty, char *buf)
{
if (!tty) /* Hmm. NULL pointer. That's fun. */
@@ -235,6 +264,28 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
* Tty buffer allocation management
*/
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
static void tty_buffer_free_all(struct tty_struct *tty)
{
struct tty_buffer *thead;
@@ -247,19 +298,47 @@ static void tty_buffer_free_all(struct tty_struct *tty)
kfree(thead);
}
tty->buf.tail = NULL;
+ tty->buf.memory_used = 0;
}
+/**
+ * tty_buffer_init - prepare a tty buffer structure
+ * @tty: tty to initialise
+ *
+ * Set up the initial state of the buffer management for a tty device.
+ * Must be called before the other tty buffer functions are used.
+ *
+ * Locking: none
+ */
+
static void tty_buffer_init(struct tty_struct *tty)
{
spin_lock_init(&tty->buf.lock);
tty->buf.head = NULL;
tty->buf.tail = NULL;
tty->buf.free = NULL;
+ tty->buf.memory_used = 0;
}
-static struct tty_buffer *tty_buffer_alloc(size_t size)
+/**
+ * tty_buffer_alloc - allocate a tty buffer
+ * @tty: tty device
+ * @size: desired size (characters)
+ *
+ * Allocate a new tty buffer to hold the desired number of characters.
+ * Return NULL if out of memory or the allocation would exceed the
+ * per device queue
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
{
- struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ struct tty_buffer *p;
+
+ if (tty->buf.memory_used + size > 65536)
+ return NULL;
+ p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if(p == NULL)
return NULL;
p->used = 0;
@@ -269,17 +348,27 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-/* printk("Flip create %p\n", p); */
+ tty->buf.memory_used += size;
return p;
}
-/* Must be called with the tty_read lock held. This needs to acquire strategy
- code to decide if we should kfree or relink a given expired buffer */
+/**
+ * tty_buffer_free - free a tty buffer
+ * @tty: tty owning the buffer
+ * @b: the buffer to free
+ *
+ * Free a tty buffer, or add it to the free list according to our
+ * internal strategy
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
{
/* Dumb strategy for now - should keep some stats */
-/* printk("Flip dispose %p\n", b); */
+ tty->buf.memory_used -= b->size;
+ WARN_ON(tty->buf.memory_used < 0);
+
if(b->size >= 512)
kfree(b);
else {
@@ -288,6 +377,18 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
}
}
+/**
+ * tty_buffer_find - find a free tty buffer
+ * @tty: tty owning the buffer
+ * @size: characters wanted
+ *
+ * Locate an existing suitable tty buffer or if we are lacking one then
+ * allocate a new one. We round our buffers off in 256 character chunks
+ * to get better allocation behaviour.
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
{
struct tty_buffer **tbh = &tty->buf.free;
@@ -299,20 +400,28 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
- /* DEBUG ONLY */
-/* memset(t->data, '*', size); */
-/* printk("Flip recycle %p\n", t); */
+ tty->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~ 0xFF;
- return tty_buffer_alloc(size);
+ return tty_buffer_alloc(tty, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
+/**
+ * tty_buffer_request_room - grow tty buffer if needed
+ * @tty: tty structure
+ * @size: size desired
+ *
+ * Make at least size bytes of linear space available for the tty
+ * buffer. If we fail return the size we managed to find.
+ *
+ * Locking: Takes tty->buf.lock
+ */
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b, *n;
@@ -347,6 +456,18 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+/**
+ * tty_insert_flip_string - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. All the characters
+ * passed are marked as without error. Returns the number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
size_t size)
{
@@ -370,6 +491,20 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
}
EXPORT_SYMBOL(tty_insert_flip_string);
+/**
+ * tty_insert_flip_string_flags - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @flags: flag bytes
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. For each character
+ * the flags array indicates the status of the character. Returns the
+ * number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size)
{
@@ -394,6 +529,17 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
}
EXPORT_SYMBOL(tty_insert_flip_string_flags);
+/**
+ * tty_schedule_flip - push characters to ldisc
+ * @tty: tty to push from
+ *
+ * Takes any pending buffers and transfers their ownership to the
+ * ldisc side of the queue. It then schedules those characters for
+ * processing by the line discipline.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+
void tty_schedule_flip(struct tty_struct *tty)
{
unsigned long flags;
@@ -405,12 +551,19 @@ void tty_schedule_flip(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_schedule_flip);
-/*
+/**
+ * tty_prepare_flip_string - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @size: desired size
+ *
* Prepare a block of space in the buffer for data. Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for normal characters. This is used for drivers
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
*/
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
@@ -427,12 +580,20 @@ int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
-/*
+/**
+ * tty_prepare_flip_string_flags - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @flags: return pointer for status flag write area
+ * @size: desired size
+ *
* Prepare a block of space in the buffer for data. Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for characters. This is used for drivers
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
*/
int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
@@ -451,10 +612,16 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
-/*
+/**
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @num: line discipline number
+ *
* This is probably overkill for real world processors but
* they are not on hot paths so a little discipline won't do
* any harm.
+ *
+ * Locking: takes termios_sem
*/
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -474,6 +641,19 @@ static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+/**
+ * tty_register_ldisc - install a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Installs a new line discipline into the kernel. The discipline
+ * is set up as unreferenced and then made available to the kernel
+ * from this point onwards.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
unsigned long flags;
@@ -493,6 +673,18 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
}
EXPORT_SYMBOL(tty_register_ldisc);
+/**
+ * tty_unregister_ldisc - unload a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Remove a line discipline from the kernel providing it is not
+ * currently in use.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
int tty_unregister_ldisc(int disc)
{
unsigned long flags;
@@ -512,6 +704,19 @@ int tty_unregister_ldisc(int disc)
}
EXPORT_SYMBOL(tty_unregister_ldisc);
+/**
+ * tty_ldisc_get - take a reference to an ldisc
+ * @disc: ldisc number
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and
+ * module locking counts. Returns NULL if the discipline is not available.
+ * Returns a pointer to the discipline and bumps the ref count if it is
+ * available
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
struct tty_ldisc *tty_ldisc_get(int disc)
{
unsigned long flags;
@@ -540,6 +745,17 @@ struct tty_ldisc *tty_ldisc_get(int disc)
EXPORT_SYMBOL_GPL(tty_ldisc_get);
+/**
+ * tty_ldisc_put - drop ldisc reference
+ * @disc: ldisc number
+ *
+ * Drop a reference to a line discipline. Manage refcounts and
+ * module usage counts
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
void tty_ldisc_put(int disc)
{
struct tty_ldisc *ld;
@@ -557,6 +773,19 @@ void tty_ldisc_put(int disc)
EXPORT_SYMBOL_GPL(tty_ldisc_put);
+/**
+ * tty_ldisc_assign - set ldisc on a tty
+ * @tty: tty to assign
+ * @ld: line discipline
+ *
+ * Install an instance of a line discipline into a tty structure. The
+ * ldisc must have a reference count above zero to ensure it remains/
+ * The tty instance refcount starts at zero.
+ *
+ * Locking:
+ * Caller must hold references
+ */
+
static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
tty->ldisc = *ld;
@@ -571,6 +800,8 @@ static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
* the tty ldisc. Return 0 on failure or 1 on success. This is
* used to implement both the waiting and non waiting versions
* of tty_ldisc_ref
+ *
+ * Locking: takes tty_ldisc_lock
*/
static int tty_ldisc_try(struct tty_struct *tty)
@@ -602,6 +833,8 @@ static int tty_ldisc_try(struct tty_struct *tty)
* must also be careful not to hold other locks that will deadlock
* against a discipline change, such as an existing ldisc reference
* (which we check for)
+ *
+ * Locking: call functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
@@ -622,6 +855,8 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
* Dereference the line discipline for the terminal and take a
* reference to it. If the line discipline is in flux then
* return NULL. Can be called from IRQ and timer functions.
+ *
+ * Locking: called functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
@@ -639,6 +874,8 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
*
* Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
* be called in IRQ context.
+ *
+ * Locking: takes tty_ldisc_lock
*/
void tty_ldisc_deref(struct tty_ldisc *ld)
@@ -683,6 +920,9 @@ static void tty_ldisc_enable(struct tty_struct *tty)
*
* Set the discipline of a tty line. Must be called from a process
* context.
+ *
+ * Locking: takes tty_ldisc_lock.
+ * called functions take termios_sem
*/
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -846,9 +1086,17 @@ restart:
return retval;
}
-/*
- * This routine returns a tty driver structure, given a device number
+/**
+ * get_tty_driver - find device of a tty
+ * @dev_t: device identifier
+ * @index: returns the index of the tty
+ *
+ * This routine returns a tty driver structure, given a device number
+ * and also passes back the index number.
+ *
+ * Locking: caller must hold tty_mutex
*/
+
static struct tty_driver *get_tty_driver(dev_t device, int *index)
{
struct tty_driver *p;
@@ -863,11 +1111,17 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
return NULL;
}
-/*
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU. If the signal is blocked or
- * ignored, go ahead and perform the operation. (POSIX 7.2)
+/**
+ * tty_check_change - check for POSIX terminal changes
+ * @tty: tty to check
+ *
+ * If we try to write to, or set the state of, a terminal and we're
+ * not in the foreground, send a SIGTTOU. If the signal is blocked or
+ * ignored, go ahead and perform the operation. (POSIX 7.2)
+ *
+ * Locking: none
*/
+
int tty_check_change(struct tty_struct * tty)
{
if (current->signal->tty != tty)
@@ -1005,10 +1259,27 @@ void tty_ldisc_flush(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
-/*
- * This can be called by the "eventd" kernel thread. That is process synchronous,
- * but doesn't hold any locks, so we need to make sure we have the appropriate
- * locks for what we're doing..
+/**
+ * do_tty_hangup - actual handler for hangup events
+ * @data: tty device
+ *
+ * This can be called by the "eventd" kernel thread. That is process
+ * synchronous but doesn't hold any locks, so we need to make sure we
+ * have the appropriate locks for what we're doing.
+ *
+ * The hangup event clears any pending redirections onto the hung up
+ * device. It ensures future writes will error and it does the needed
+ * line discipline hangup and signal delivery. The tty object itself
+ * remains intact.
+ *
+ * Locking:
+ * BKL
+ * redirect lock for undoing redirection
+ * file list lock for manipulating list of ttys
+ * tty_ldisc_lock from called functions
+ * termios_sem resetting termios data
+ * tasklist_lock to walk task list for hangup event
+ *
*/
static void do_tty_hangup(void *data)
{
@@ -1133,6 +1404,14 @@ static void do_tty_hangup(void *data)
fput(f);
}
+/**
+ * tty_hangup - trigger a hangup event
+ * @tty: tty to hangup
+ *
+ * A carrier loss (virtual or otherwise) has occurred on this like
+ * schedule a hangup sequence to run after this event.
+ */
+
void tty_hangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -1145,6 +1424,15 @@ void tty_hangup(struct tty_struct * tty)
EXPORT_SYMBOL(tty_hangup);
+/**
+ * tty_vhangup - process vhangup
+ * @tty: tty to hangup
+ *
+ * The user has asked via system call for the terminal to be hung up.
+ * We do this synchronously so that when the syscall returns the process
+ * is complete. That guarantee is neccessary for security reasons.
+ */
+
void tty_vhangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -1156,6 +1444,14 @@ void tty_vhangup(struct tty_struct * tty)
}
EXPORT_SYMBOL(tty_vhangup);
+/**
+ * tty_hung_up_p - was tty hung up
+ * @filp: file pointer of tty
+ *
+ * Return true if the tty has been subject to a vhangup or a carrier
+ * loss
+ */
+
int tty_hung_up_p(struct file * filp)
{
return (filp->f_op == &hung_up_tty_fops);
@@ -1163,19 +1459,28 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
-/*
- * This function is typically called only by the session leader, when
- * it wants to disassociate itself from its controlling tty.
+/**
+ * disassociate_ctty - disconnect controlling tty
+ * @on_exit: true if exiting so need to "hang up" the session
*
- * It performs the following functions:
+ * This function is typically called only by the session leader, when
+ * it wants to disassociate itself from its controlling tty.
+ *
+ * It performs the following functions:
* (1) Sends a SIGHUP and SIGCONT to the foreground process group
* (2) Clears the tty from being controlling the session
* (3) Clears the controlling tty for all processes in the
* session group.
*
- * The argument on_exit is set to 1 if called when a process is
- * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ * The argument on_exit is set to 1 if called when a process is
+ * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *
+ * Locking: tty_mutex is taken to protect current->signal->tty
+ * BKL is taken for hysterical raisins
+ * Tasklist lock is taken (under tty_mutex) to walk process
+ * lists for the session.
*/
+
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
@@ -1222,6 +1527,25 @@ void disassociate_ctty(int on_exit)
unlock_kernel();
}
+
+/**
+ * stop_tty - propogate flow control
+ * @tty: tty to stop
+ *
+ * Perform flow control to the driver. For PTY/TTY pairs we
+ * must also propogate the TIOCKPKT status. May be called
+ * on an already stopped device and will not re-call the driver
+ * method.
+ *
+ * This functionality is used by both the line disciplines for
+ * halting incoming flow and by the driver. It may therefore be
+ * called from any context, may be under the tty atomic_write_lock
+ * but not always.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void stop_tty(struct tty_struct *tty)
{
if (tty->stopped)
@@ -1238,6 +1562,19 @@ void stop_tty(struct tty_struct *tty)
EXPORT_SYMBOL(stop_tty);
+/**
+ * start_tty - propogate flow control
+ * @tty: tty to start
+ *
+ * Start a tty that has been stopped if at all possible. Perform
+ * any neccessary wakeups and propogate the TIOCPKT status. If this
+ * is the tty was previous stopped and is being started then the
+ * driver start method is invoked and the line discipline woken.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void start_tty(struct tty_struct *tty)
{
if (!tty->stopped || tty->flow_stopped)
@@ -1258,6 +1595,23 @@ void start_tty(struct tty_struct *tty)
EXPORT_SYMBOL(start_tty);
+/**
+ * tty_read - read method for tty device files
+ * @file: pointer to tty file
+ * @buf: user buffer
+ * @count: size of user buffer
+ * @ppos: unused
+ *
+ * Perform the read system call function on this terminal device. Checks
+ * for hung up devices before calling the line discipline method.
+ *
+ * Locking:
+ * Locks the line discipline internally while needed
+ * For historical reasons the line discipline read method is
+ * invoked under the BKL. This will go away in time so do not rely on it
+ * in new code. Multiple read calls may be outstanding in parallel.
+ */
+
static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
loff_t *ppos)
{
@@ -1302,6 +1656,7 @@ static inline ssize_t do_tty_write(
ssize_t ret = 0, written = 0;
unsigned int chunk;
+ /* FIXME: O_NDELAY ... */
if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
return -ERESTARTSYS;
}
@@ -1318,6 +1673,9 @@ static inline ssize_t do_tty_write(
* layer has problems with bigger chunks. It will
* claim to be able to handle more characters than
* it actually does.
+ *
+ * FIXME: This can probably go away now except that 64K chunks
+ * are too likely to fail unless switched to vmalloc...
*/
chunk = 2048;
if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
@@ -1375,6 +1733,24 @@ static inline ssize_t do_tty_write(
}
+/**
+ * tty_write - write method for tty device file
+ * @file: tty file pointer
+ * @buf: user data to write
+ * @count: bytes to write
+ * @ppos: unused
+ *
+ * Write data to a tty device via the line discipline.
+ *
+ * Locking:
+ * Locks the line discipline as required
+ * Writes to the tty driver are serialized by the atomic_write_lock
+ * and are then processed in chunks to the device. The line discipline
+ * write method will not be involked in parallel for each device
+ * The line discipline write method is called under the big
+ * kernel lock for historical reasons. New code should not rely on this.
+ */
+
static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
loff_t *ppos)
{
@@ -1422,7 +1798,18 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t
static char ptychar[] = "pqrstuvwxyzabcde";
-static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a pty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 6 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void pty_line_name(struct tty_driver *driver, int index, char *p)
{
int i = index + driver->name_base;
/* ->name is initialized to "ttyp", but "tty" is expected */
@@ -1431,24 +1818,53 @@ static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
ptychar[i >> 4 & 0xf], i & 0xf);
}
-static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a tty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 7 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
{
sprintf(p, "%s%d", driver->name, index + driver->name_base);
}
-/*
+/**
+ * init_dev - initialise a tty device
+ * @driver: tty driver we are opening a device on
+ * @idx: device index
+ * @tty: returned tty structure
+ *
+ * Prepare a tty device. This may not be a "new" clean device but
+ * could also be an active device. The pty drivers require special
+ * handling because of this.
+ *
+ * Locking:
+ * The function is called under the tty_mutex, which
+ * protects us from the tty struct or driver itself going away.
+ *
+ * On exit the tty device has the line discipline attached and
+ * a reference count of 1. If a pair was created for pty/tty use
+ * and the other was a pty master then it too has a reference count of 1.
+ *
* WSH 06/09/97: Rewritten to remove races and properly clean up after a
* failed open. The new code protects the open with a mutex, so it's
* really quite straightforward. The mutex locking can probably be
* relaxed for the (most common) case of reopening a tty.
*/
+
static int init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty)
{
struct tty_struct *tty, *o_tty;
struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
- int retval=0;
+ int retval = 0;
/* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -1662,10 +2078,20 @@ release_mem_out:
goto end_init;
}
-/*
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots.
+/**
+ * release_mem - release tty structure memory
+ *
+ * Releases memory associated with a tty structure, and clears out the
+ * driver table slots. This function is called when a device is no longer
+ * in use. It also gets called when setup of a device fails.
+ *
+ * Locking:
+ * tty_mutex - sometimes only
+ * takes the file list lock internally when working on the list
+ * of ttys that the driver keeps.
+ * FIXME: should we require tty_mutex is held here ??
*/
+
static void release_mem(struct tty_struct *tty, int idx)
{
struct tty_struct *o_tty;
@@ -2006,18 +2432,27 @@ static void release_dev(struct file * filp)
}
-/*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
+/**
+ * tty_open - open a tty device
+ * @inode: inode of device file
+ * @filp: file pointer to tty
*
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ * tty_open and tty_release keep up the tty count that contains the
+ * number of opens done on a tty. We cannot use the inode-count, as
+ * different inodes might point to the same tty.
*
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
+ * Open-counting is needed for pty masters, as well as for keeping
+ * track of serial lines: DTR is dropped when the last close happens.
+ * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ *
+ * The termios state of a pty is reset on first open so that
+ * settings don't persist across reuse.
+ *
+ * Locking: tty_mutex protects current->signal->tty, get_tty_driver and
+ * init_dev work. tty->count should protect the rest.
+ * task_lock is held to update task details for sessions
*/
+
static int tty_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -2132,6 +2567,18 @@ got_driver:
}
#ifdef CONFIG_UNIX98_PTYS
+/**
+ * ptmx_open - open a unix 98 pty master
+ * @inode: inode of device file
+ * @filp: file pointer to tty
+ *
+ * Allocate a unix98 pty master device from the ptmx driver.
+ *
+ * Locking: tty_mutex protects theinit_dev work. tty->count should
+ protect the rest.
+ * allocated_ptys_lock handles the list of free pty numbers
+ */
+
static int ptmx_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -2191,6 +2638,18 @@ out:
}
#endif
+/**
+ * tty_release - vfs callback for close
+ * @inode: inode of tty
+ * @filp: file pointer for handle to tty
+ *
+ * Called the last time each file handle is closed that references
+ * this tty. There may however be several such references.
+ *
+ * Locking:
+ * Takes bkl. See release_dev
+ */
+
static int tty_release(struct inode * inode, struct file * filp)
{
lock_kernel();
@@ -2199,7 +2658,18 @@ static int tty_release(struct inode * inode, struct file * filp)
return 0;
}
-/* No kernel lock held - fine */
+/**
+ * tty_poll - check tty status
+ * @filp: file being polled
+ * @wait: poll wait structures to update
+ *
+ * Call the line discipline polling method to obtain the poll
+ * status of the device.
+ *
+ * Locking: locks called line discipline but ldisc poll method
+ * may be re-entered freely by other callers.
+ */
+
static unsigned int tty_poll(struct file * filp, poll_table * wait)
{
struct tty_struct * tty;
@@ -2243,6 +2713,21 @@ static int tty_fasync(int fd, struct file * filp, int on)
return 0;
}
+/**
+ * tiocsti - fake input character
+ * @tty: tty to fake input into
+ * @p: pointer to character
+ *
+ * Fake input to a tty device. Does the neccessary locking and
+ * input management.
+ *
+ * FIXME: does not honour flow control ??
+ *
+ * Locking:
+ * Called functions take tty_ldisc_lock
+ * current->signal->tty check is safe without locks
+ */
+
static int tiocsti(struct tty_struct *tty, char __user *p)
{
char ch, mbz = 0;
@@ -2258,6 +2743,18 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
return 0;
}
+/**
+ * tiocgwinsz - implement window query ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the kernel idea of the window size into the user buffer. No
+ * locking is done.
+ *
+ * FIXME: Returning random values racing a window size set is wrong
+ * should lock here against that
+ */
+
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
{
if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
@@ -2265,6 +2762,24 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
return 0;
}
+/**
+ * tiocswinsz - implement window size set ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the user idea of the window size to the kernel. Traditionally
+ * this is just advisory information but for the Linux console it
+ * actually has driver level meaning and triggers a VC resize.
+ *
+ * Locking:
+ * The console_sem is used to ensure we do not try and resize
+ * the console twice at once.
+ * FIXME: Two racing size sets may leave the console and kernel
+ * parameters disagreeing. Is this exploitable ?
+ * FIXME: Random values racing a window size get is wrong
+ * should lock here against that
+ */
+
static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize __user * arg)
{
@@ -2294,6 +2809,15 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
return 0;
}
+/**
+ * tioccons - allow admin to move logical console
+ * @file: the file to become console
+ *
+ * Allow the adminstrator to move the redirected console device
+ *
+ * Locking: uses redirect_lock to guard the redirect information
+ */
+
static int tioccons(struct file *file)
{
if (!capable(CAP_SYS_ADMIN))
@@ -2319,6 +2843,17 @@ static int tioccons(struct file *file)
return 0;
}
+/**
+ * fionbio - non blocking ioctl
+ * @file: file to set blocking value
+ * @p: user parameter
+ *
+ * Historical tty interfaces had a blocking control ioctl before
+ * the generic functionality existed. This piece of history is preserved
+ * in the expected tty API of posix OS's.
+ *
+ * Locking: none, the open fle handle ensures it won't go away.
+ */
static int fionbio(struct file *file, int __user *p)
{
@@ -2334,6 +2869,23 @@ static int fionbio(struct file *file, int __user *p)
return 0;
}
+/**
+ * tiocsctty - set controlling tty
+ * @tty: tty structure
+ * @arg: user argument
+ *
+ * This ioctl is used to manage job control. It permits a session
+ * leader to set this tty as the controlling tty for the session.
+ *
+ * Locking:
+ * Takes tasklist lock internally to walk sessions
+ * Takes task_lock() when updating signal->tty
+ *
+ * FIXME: tty_mutex is needed to protect signal->tty references.
+ * FIXME: why task_lock on the signal->tty reference ??
+ *
+ */
+
static int tiocsctty(struct tty_struct *tty, int arg)
{
struct task_struct *p;
@@ -2374,6 +2926,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
return 0;
}
+/**
+ * tiocgpgrp - get process group
+ * @tty: tty passed by user
+ * @real_tty: tty side of the tty pased by the user if a pty else the tty
+ * @p: returned pid
+ *
+ * Obtain the process group of the tty. If there is no process group
+ * return an error.
+ *
+ * Locking: none. Reference to ->signal->tty is safe.
+ */
+
static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
/*
@@ -2385,6 +2949,20 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return put_user(real_tty->pgrp, p);
}
+/**
+ * tiocspgrp - attempt to set process group
+ * @tty: tty passed by user
+ * @real_tty: tty side device matching tty passed by user
+ * @p: pid pointer
+ *
+ * Set the process group of the tty to the session passed. Only
+ * permitted where the tty session is our session.
+ *
+ * Locking: None
+ *
+ * FIXME: current->signal->tty referencing is unsafe.
+ */
+
static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
pid_t pgrp;
@@ -2408,6 +2986,18 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return 0;
}
+/**
+ * tiocgsid - get session id
+ * @tty: tty passed by user
+ * @real_tty: tty side of the tty pased by the user if a pty else the tty
+ * @p: pointer to returned session id
+ *
+ * Obtain the session id of the tty. If there is no session
+ * return an error.
+ *
+ * Locking: none. Reference to ->signal->tty is safe.
+ */
+
static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
/*
@@ -2421,6 +3011,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
return put_user(real_tty->session, p);
}
+/**
+ * tiocsetd - set line discipline
+ * @tty: tty device
+ * @p: pointer to user data
+ *
+ * Set the line discipline according to user request.
+ *
+ * Locking: see tty_set_ldisc, this function is just a helper
+ */
+
static int tiocsetd(struct tty_struct *tty, int __user *p)
{
int ldisc;
@@ -2430,6 +3030,21 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
return tty_set_ldisc(tty, ldisc);
}
+/**
+ * send_break - performed time break
+ * @tty: device to break on
+ * @duration: timeout in mS
+ *
+ * Perform a timed break on hardware that lacks its own driver level
+ * timed break functionality.
+ *
+ * Locking:
+ * None
+ *
+ * FIXME:
+ * What if two overlap
+ */
+
static int send_break(struct tty_struct *tty, unsigned int duration)
{
tty->driver->break_ctl(tty, -1);
@@ -2442,8 +3057,19 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
return 0;
}
-static int
-tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
+/**
+ * tiocmget - get modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @p: pointer to result
+ *
+ * Obtain the modem status bits from the tty driver if the feature
+ * is supported. Return -EINVAL if it is not available.
+ *
+ * Locking: none (up to the driver)
+ */
+
+static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
{
int retval = -EINVAL;
@@ -2456,8 +3082,20 @@ tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
return retval;
}
-static int
-tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
+/**
+ * tiocmset - set modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @cmd: command - clear bits, set bits or set all
+ * @p: pointer to desired bits
+ *
+ * Set the modem status bits from the tty driver if the feature
+ * is supported. Return -EINVAL if it is not available.
+ *
+ * Locking: none (up to the driver)
+ */
+
+static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
unsigned __user *p)
{
int retval = -EINVAL;
@@ -2573,6 +3211,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
clear_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCNOTTY:
+ /* FIXME: taks lock or tty_mutex ? */
if (current->signal->tty != tty)
return -ENOTTY;
if (current->signal->leader)
@@ -2753,9 +3392,16 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
-/*
- * This routine is called out of the software interrupt to flush data
- * from the buffer chain to the line discipline.
+/**
+ * flush_to_ldisc
+ * @private_: tty structure passed from work queue.
+ *
+ * This routine is called out of the software interrupt to flush data
+ * from the buffer chain to the line discipline.
+ *
+ * Locking: holds tty->buf.lock to guard buffer list. Drops the lock
+ * while invoking the line discipline receive_buf method. The
+ * receive_buf method is single threaded for each tty instance.
*/
static void flush_to_ldisc(void *private_)
@@ -2831,6 +3477,8 @@ static int n_baud_table = ARRAY_SIZE(baud_table);
* Convert termios baud rate data into a speed. This should be called
* with the termios lock held if this termios is a terminal termios
* structure. May change the termios data.
+ *
+ * Locking: none
*/
int tty_termios_baud_rate(struct termios *termios)
@@ -2859,6 +3507,8 @@ EXPORT_SYMBOL(tty_termios_baud_rate);
* Returns the baud rate as an integer for this terminal. The
* termios lock must be held by the caller and the terminal bit
* flags may be updated.
+ *
+ * Locking: none
*/
int tty_get_baud_rate(struct tty_struct *tty)
@@ -2888,6 +3538,8 @@ EXPORT_SYMBOL(tty_get_baud_rate);
*
* In the event of the queue being busy for flipping the work will be
* held off and retried later.
+ *
+ * Locking: tty buffer lock. Driver locks in low latency mode.
*/
void tty_flip_buffer_push(struct tty_struct *tty)
@@ -2907,9 +3559,16 @@ void tty_flip_buffer_push(struct tty_struct *tty)
EXPORT_SYMBOL(tty_flip_buffer_push);
-/*
- * This subroutine initializes a tty structure.
+/**
+ * initialize_tty_struct
+ * @tty: tty to initialize
+ *
+ * This subroutine initializes a tty structure that has been newly
+ * allocated.
+ *
+ * Locking: none - tty in question must not be exposed at this point
*/
+
static void initialize_tty_struct(struct tty_struct *tty)
{
memset(tty, 0, sizeof(struct tty_struct));
@@ -2935,6 +3594,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
/*
* The default put_char routine if the driver did not define one.
*/
+
static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
{
tty->driver->write(tty, &ch, 1);
@@ -2943,19 +3603,23 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
static struct class *tty_class;
/**
- * tty_register_device - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- * This field is optional, if there is no known struct device for this
- * tty device it can be set to NULL safely.
+ * tty_register_device - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device
+ * for this tty device it can be set to NULL safely.
*
- * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
+ * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
*
- * This call is required to be made to register an individual tty device if
- * the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If that
- * bit is not set, this function should not be called by a tty driver.
+ * This call is required to be made to register an individual tty device
+ * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
+ * that bit is not set, this function should not be called by a tty
+ * driver.
+ *
+ * Locking: ??
*/
+
struct class_device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *device)
{
@@ -2977,13 +3641,16 @@ struct class_device *tty_register_device(struct tty_driver *driver,
}
/**
- * tty_unregister_device - unregister a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
+ * tty_unregister_device - unregister a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
*
- * If a tty device is registered with a call to tty_register_device() then
- * this function must be made when the tty device is gone.
+ * If a tty device is registered with a call to tty_register_device() then
+ * this function must be called when the tty device is gone.
+ *
+ * Locking: ??
*/
+
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
@@ -3094,7 +3761,6 @@ int tty_register_driver(struct tty_driver *driver)
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
if (error) {
- cdev_del(&driver->cdev);
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = driver->termios_locked = NULL;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index f19cf9d7792d..4ad47d321bd4 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -36,6 +36,18 @@
#define TERMIOS_WAIT 2
#define TERMIOS_TERMIO 4
+
+/**
+ * tty_wait_until_sent - wait for I/O to finish
+ * @tty: tty we are waiting for
+ * @timeout: how long we will wait
+ *
+ * Wait for characters pending in a tty driver to hit the wire, or
+ * for a timeout to occur (eg due to flow control)
+ *
+ * Locking: none
+ */
+
void tty_wait_until_sent(struct tty_struct * tty, long timeout)
{
DECLARE_WAITQUEUE(wait, current);
@@ -94,6 +106,18 @@ static void unset_locked_termios(struct termios *termios,
old->c_cc[i] : termios->c_cc[i];
}
+/**
+ * change_termios - update termios values
+ * @tty: tty to update
+ * @new_termios: desired new value
+ *
+ * Perform updates to the termios values set on this terminal. There
+ * is a bit of layering violation here with n_tty in terms of the
+ * internal knowledge of this function.
+ *
+ * Locking: termios_sem
+ */
+
static void change_termios(struct tty_struct * tty, struct termios * new_termios)
{
int canon_change;
@@ -155,6 +179,19 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
up(&tty->termios_sem);
}
+/**
+ * set_termios - set termios values for a tty
+ * @tty: terminal device
+ * @arg: user data
+ * @opt: option information
+ *
+ * Helper function to prepare termios data and run neccessary other
+ * functions before using change_termios to do the actual changes.
+ *
+ * Locking:
+ * Called functions take ldisc and termios_sem locks
+ */
+
static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
{
struct termios tmp_termios;
@@ -284,6 +321,17 @@ static void set_sgflags(struct termios * termios, int flags)
}
}
+/**
+ * set_sgttyb - set legacy terminal values
+ * @tty: tty structure
+ * @sgttyb: pointer to old style terminal structure
+ *
+ * Updates a terminal from the legacy BSD style terminal information
+ * structure.
+ *
+ * Locking: termios_sem
+ */
+
static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
{
int retval;
@@ -369,9 +417,16 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
}
#endif
-/*
- * Send a high priority character to the tty.
+/**
+ * send_prio_char - send priority character
+ *
+ * Send a high priority character to the tty even if stopped
+ *
+ * Locking: none
+ *
+ * FIXME: overlapping calls with start/stop tty lose state of tty
*/
+
static void send_prio_char(struct tty_struct *tty, char ch)
{
int was_stopped = tty->stopped;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index eccffaf26faa..a5628a8b6620 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1011,6 +1011,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EPERM;
vt_dont_switch = 0;
return 0;
+ case VT_GETHIFONTMASK:
+ return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index d53f664a4dd8..fff89c2d88fd 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -45,7 +45,7 @@ config WATCHDOG_NOWAYOUT
comment "Watchdog Device Drivers"
depends on WATCHDOG
-# Architecture Independant
+# Architecture Independent
config SOFT_WATCHDOG
tristate "Software watchdog"
@@ -127,7 +127,7 @@ config S3C2410_WATCHDOG
enabled.
The driver is limited by the speed of the system's PCLK
- signal, so with reasonbaly fast systems (PCLK around 50-66MHz)
+ signal, so with reasonably fast systems (PCLK around 50-66MHz)
then watchdog intervals of over approximately 20seconds are
unavailable.
@@ -423,7 +423,7 @@ config SBC_EPX_C3_WATCHDOG
is no way to know if writing to its IO address will corrupt
your system or have any real effect. The only way to be sure
that this driver does what you want is to make sure you
- are runnning it on an EPX-C3 from Winsystems with the watchdog
+ are running it on an EPX-C3 from Winsystems with the watchdog
timer at IO address 0x1ee and 0x1ef. It will write to both those
IO ports. Basically, the assumption is made that if you compile
this driver into your kernel and/or load it as a module, that you
@@ -472,7 +472,7 @@ config INDYDOG
tristate "Indy/I2 Hardware Watchdog"
depends on WATCHDOG && SGI_IP22
help
- Hardwaredriver for the Indy's/I2's watchdog. This is a
+ Hardware driver for the Indy's/I2's watchdog. This is a
watchdog timer that will reboot the machine after a 60 second
timer expired and no process has written to /dev/watchdog during
that time.
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
index 1035be5b5019..41fc6f80c493 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/char/watchdog/sbc8360.c
@@ -200,7 +200,7 @@ static int wd_margin = 0xB;
static int wd_multiplier = 2;
static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(timeout, int, 27);
+module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout,
@@ -407,7 +407,7 @@ module_exit(sbc8360_exit);
MODULE_AUTHOR("Ian E. Morgan ");
MODULE_DESCRIPTION("SBC8360 watchdog driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("1.01");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
/* end of sbc8360.c */
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 498aa37bca22..3ece69231343 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -51,6 +51,7 @@ void proc_fork_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -58,7 +59,8 @@ void proc_fork_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_FORK;
ev->event_data.fork.parent_pid = task->real_parent->pid;
ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -76,6 +78,7 @@ void proc_exec_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
+ struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE];
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -84,7 +87,8 @@ void proc_exec_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -100,6 +104,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -118,7 +123,8 @@ void proc_id_connector(struct task_struct *task, int which_id)
} else
return;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -131,6 +137,7 @@ void proc_exit_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -138,7 +145,8 @@ void proc_exit_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -164,6 +172,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -171,7 +180,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
msg->seq = rcvd_seq;
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index bc1088d9b379..b3df613ae4ec 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -284,39 +284,69 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
* SYSFS INTERFACE *
*********************************************************************/
+static struct cpufreq_governor *__find_governor(const char *str_governor)
+{
+ struct cpufreq_governor *t;
+
+ list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+ if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN))
+ return t;
+
+ return NULL;
+}
+
/**
* cpufreq_parse_governor - parse a governor string
*/
static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor)
{
+ int err = -EINVAL;
+
if (!cpufreq_driver)
- return -EINVAL;
+ goto out;
+
if (cpufreq_driver->setpolicy) {
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
- return 0;
+ err = 0;
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
- return 0;
+ err = 0;
}
- return -EINVAL;
- } else {
+ } else if (cpufreq_driver->target) {
struct cpufreq_governor *t;
+
mutex_lock(&cpufreq_governor_mutex);
- if (!cpufreq_driver || !cpufreq_driver->target)
- goto out;
- list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
- if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
- *governor = t;
+
+ t = __find_governor(str_governor);
+
+ if (t == NULL) {
+ char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+
+ if (name) {
+ int ret;
+
mutex_unlock(&cpufreq_governor_mutex);
- return 0;
+ ret = request_module(name);
+ mutex_lock(&cpufreq_governor_mutex);
+
+ if (ret == 0)
+ t = __find_governor(str_governor);
}
+
+ kfree(name);
}
-out:
+
+ if (t != NULL) {
+ *governor = t;
+ err = 0;
+ }
+
mutex_unlock(&cpufreq_governor_mutex);
}
- return -EINVAL;
+ out:
+ return err;
}
@@ -1265,23 +1295,21 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
int cpufreq_register_governor(struct cpufreq_governor *governor)
{
- struct cpufreq_governor *t;
+ int err;
if (!governor)
return -EINVAL;
mutex_lock(&cpufreq_governor_mutex);
- list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
- if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
- mutex_unlock(&cpufreq_governor_mutex);
- return -EBUSY;
- }
+ err = -EBUSY;
+ if (__find_governor(governor->name) == NULL) {
+ err = 0;
+ list_add(&governor->governor_list, &cpufreq_governor_list);
}
- list_add(&governor->governor_list, &cpufreq_governor_list);
mutex_unlock(&cpufreq_governor_mutex);
- return 0;
+ return err;
}
EXPORT_SYMBOL_GPL(cpufreq_register_governor);
@@ -1343,6 +1371,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+ if (policy->min > data->min && policy->min > policy->max) {
+ ret = -EINVAL;
+ goto error_out;
+ }
+
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(policy);
if (ret)
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index bf6ab8a8d5ed..a1cfd4e3c97d 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#define EDAC_MC_LABEL_LEN 31
#define MC_PROC_NAME_MAX_LEN 7
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index cc15c4f2e9ec..35ad1b032726 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -64,17 +65,17 @@
#define ABIT_UGURU_IN_SENSOR 0
#define ABIT_UGURU_TEMP_SENSOR 1
#define ABIT_UGURU_NC 2
-/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
- convert them to params. */
-/* 250 was determined by trial and error, 200 works most of the time, but not
- always. I assume this is cpu-speed independent, since the ISA-bus and not
- the CPU should be the bottleneck. Note that 250 sometimes is still not
- enough (only reported on AN7 mb) this is handled by a higher layer. */
-#define ABIT_UGURU_WAIT_TIMEOUT 250
+/* In many cases we need to wait for the uGuru to reach a certain status, most
+ of the time it will reach this status within 30 - 90 ISA reads, and thus we
+ can best busy wait. This define gives the total amount of reads to try. */
+#define ABIT_UGURU_WAIT_TIMEOUT 125
+/* However sometimes older versions of the uGuru seem to be distracted and they
+ do not respond for a long time. To handle this we sleep before each of the
+ last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */
+#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP 5
/* Normally all expected status in abituguru_ready, are reported after the
- first read, but sometimes not and we need to poll, 5 polls was not enough
- 50 sofar is. */
-#define ABIT_UGURU_READY_TIMEOUT 50
+ first read, but sometimes not and we need to poll. */
+#define ABIT_UGURU_READY_TIMEOUT 5
/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
#define ABIT_UGURU_MAX_RETRIES 3
#define ABIT_UGURU_RETRY_DELAY (HZ/5)
@@ -226,6 +227,10 @@ static int abituguru_wait(struct abituguru_data *data, u8 state)
timeout--;
if (timeout == 0)
return -EBUSY;
+ /* sleep a bit before our last few tries, see the comment on
+ this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */
+ if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP)
+ msleep(0);
}
return 0;
}
@@ -256,6 +261,7 @@ static int abituguru_ready(struct abituguru_data *data)
"CMD reg does not hold 0xAC after ready command\n");
return -EIO;
}
+ msleep(0);
}
/* After this the ABIT_UGURU_DATA port should contain
@@ -268,6 +274,7 @@ static int abituguru_ready(struct abituguru_data *data)
"state != more input after ready command\n");
return -EIO;
}
+ msleep(0);
}
data->uguru_ready = 1;
@@ -331,7 +338,8 @@ static int abituguru_read(struct abituguru_data *data,
/* And read the data */
for (i = 0; i < count; i++) {
if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
- ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+ ABIT_UGURU_DEBUG(retries ? 1 : 3,
+ "timeout exceeded waiting for "
"read state (bank: %d, sensor: %d)\n",
(int)bank_addr, (int)sensor_addr);
break;
@@ -350,7 +358,9 @@ static int abituguru_read(struct abituguru_data *data,
static int abituguru_write(struct abituguru_data *data,
u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
{
- int i;
+ /* We use the ready timeout as we have to wait for 0xAC just like the
+ ready function */
+ int i, timeout = ABIT_UGURU_READY_TIMEOUT;
/* Send the address */
i = abituguru_send_address(data, bank_addr, sensor_addr,
@@ -370,7 +380,8 @@ static int abituguru_write(struct abituguru_data *data,
}
/* Now we need to wait till the chip is ready to be read again,
- don't ask why */
+ so that we can read 0xAC as confirmation that our write has
+ succeeded. */
if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state "
"after write (bank: %d, sensor: %d)\n", (int)bank_addr,
@@ -379,11 +390,15 @@ static int abituguru_write(struct abituguru_data *data,
}
/* Cmd port MUST be read now and should contain 0xAC */
- if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
- ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write "
- "(bank: %d, sensor: %d)\n", (int)bank_addr,
- (int)sensor_addr);
- return -EIO;
+ while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+ timeout--;
+ if (timeout == 0) {
+ ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after "
+ "write (bank: %d, sensor: %d)\n",
+ (int)bank_addr, (int)sensor_addr);
+ return -EIO;
+ }
+ msleep(0);
}
/* Last put the chip back in ready state */
@@ -403,7 +418,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
u8 sensor_addr)
{
u8 val, buf[3];
- int ret = ABIT_UGURU_NC;
+ int i, ret = -ENODEV; /* error is the most common used retval :| */
/* If overriden by the user return the user selected type */
if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR &&
@@ -439,7 +454,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
buf[2] = 250;
if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
buf, 3) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
/* Now we need 20 ms to give the uguru time to read the sensors
and raise a voltage alarm */
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -447,21 +462,16 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
/* Check for alarm and check the alarm is a volt low alarm. */
if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
ABIT_UGURU_MAX_RETRIES) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
sensor_addr, buf, 3,
ABIT_UGURU_MAX_RETRIES) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
- /* Restore original settings */
- if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
- sensor_addr,
- data->bank1_settings[sensor_addr],
- 3) != 3)
- return -ENODEV;
ABIT_UGURU_DEBUG(2, " found volt sensor\n");
- return ABIT_UGURU_IN_SENSOR;
+ ret = ABIT_UGURU_IN_SENSOR;
+ goto abituguru_detect_bank1_sensor_type_exit;
} else
ABIT_UGURU_DEBUG(2, " alarm raised during volt "
"sensor test, but volt low flag not set\n");
@@ -477,7 +487,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
buf[2] = 10;
if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
buf, 3) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
/* Now we need 50 ms to give the uguru time to read the sensors
and raise a temp alarm */
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -485,15 +495,16 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
/* Check for alarm and check the alarm is a temp high alarm. */
if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
ABIT_UGURU_MAX_RETRIES) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
sensor_addr, buf, 3,
ABIT_UGURU_MAX_RETRIES) != 3)
- return -ENODEV;
+ goto abituguru_detect_bank1_sensor_type_exit;
if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) {
- ret = ABIT_UGURU_TEMP_SENSOR;
ABIT_UGURU_DEBUG(2, " found temp sensor\n");
+ ret = ABIT_UGURU_TEMP_SENSOR;
+ goto abituguru_detect_bank1_sensor_type_exit;
} else
ABIT_UGURU_DEBUG(2, " alarm raised during temp "
"sensor test, but temp high flag not set\n");
@@ -501,11 +512,23 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor "
"test\n");
- /* Restore original settings */
- if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
- data->bank1_settings[sensor_addr], 3) != 3)
+ ret = ABIT_UGURU_NC;
+abituguru_detect_bank1_sensor_type_exit:
+ /* Restore original settings, failing here is really BAD, it has been
+ reported that some BIOS-es hang when entering the uGuru menu with
+ invalid settings present in the uGuru, so we try this 3 times. */
+ for (i = 0; i < 3; i++)
+ if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+ sensor_addr, data->bank1_settings[sensor_addr],
+ 3) == 3)
+ break;
+ if (i == 3) {
+ printk(KERN_ERR ABIT_UGURU_NAME
+ ": Fatal error could not restore original settings. "
+ "This should never happen please report this to the "
+ "abituguru maintainer (see MAINTAINERS)\n");
return -ENODEV;
-
+ }
return ret;
}
@@ -1305,7 +1328,7 @@ static struct abituguru_data *abituguru_update_device(struct device *dev)
data->update_timeouts = 0;
LEAVE_UPDATE:
/* handle timeout condition */
- if (err == -EBUSY) {
+ if (!success && (err == -EBUSY || err >= 0)) {
/* No overflow please */
if (data->update_timeouts < 255u)
data->update_timeouts++;
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index ced309ff056f..eae9e81be375 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
unsigned long timeout;
timeout = jiffies + POLL_TIMEOUT;
- while (time_before(jiffies, timeout)) {
+ while (1) {
status = inb(ACBST);
/* Reset the status register to avoid the hang */
@@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
scx200_acb_machine(iface, status);
return;
}
- yield();
+ if (time_after(jiffies, timeout))
+ break;
+ cpu_relax();
+ cond_resched();
}
dev_err(&iface->adapter.dev, "timeout in state %s\n",
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index e7e27049fbfa..0be6fd6a267d 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -43,13 +43,12 @@
/*-------------------------------------------------------------------------*/
#define DRIVER_VERSION "2 May 2005"
-#define DRIVER_NAME (tps65010_driver.name)
+#define DRIVER_NAME (tps65010_driver.driver.name)
MODULE_DESCRIPTION("TPS6501x Power Management Driver");
MODULE_LICENSE("GPL");
static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
@@ -100,7 +99,7 @@ struct tps65010 {
/* not currently tracking GPIO state */
};
-#define POWER_POLL_DELAY msecs_to_jiffies(800)
+#define POWER_POLL_DELAY msecs_to_jiffies(5000)
/*-------------------------------------------------------------------------*/
@@ -520,8 +519,11 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
goto fail1;
}
+ /* the IRQ is active low, but many gpio lines can't support that
+ * so this driver can use falling-edge triggers instead.
+ */
+ irqflags = IRQF_SAMPLE_RANDOM;
#ifdef CONFIG_ARM
- irqflags = IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_LOW;
if (machine_is_omap_h2()) {
tps->model = TPS65010;
omap_cfg_reg(W4_GPIO58);
@@ -543,8 +545,6 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
// FIXME set up this board's IRQ ...
}
-#else
- irqflags = IRQF_SAMPLE_RANDOM;
#endif
if (tps->irq > 0) {
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d1266fe2d1ab..b6fb167e20f6 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -682,6 +682,7 @@ config BLK_DEV_SVWKS
config BLK_DEV_SGIIOC4
tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
+ select IDEPCI_SHARE_IRQ
help
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
chipset, which has one channel and can support two devices.
@@ -773,20 +774,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_PMAC_BLINK
- bool "Blink laptop LED on drive activity (DEPRECATED)"
- depends on BLK_DEV_IDE_PMAC && ADB_PMU
- select ADB_PMU_LED
- select LEDS_TRIGGERS
- select LEDS_TRIGGER_IDE_DISK
- help
- This option enables the use of the sleep LED as a hard drive
- activity LED.
- This option is deprecated, it only selects ADB_PMU_LED and
- LEDS_TRIGGER_IDE_DISK and changes the code in the new led class
- device to default to the ide-disk trigger (which should be set
- from userspace via sysfs).
-
config BLK_DEV_IDE_SWARM
tristate "IDE for Sibyte evaluation boards"
depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f712e4cfd9dc..7cf3eb023521 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -776,7 +776,7 @@ static void update_ordered(ide_drive_t *drive)
* not available so we don't need to recheck that.
*/
capacity = idedisk_capacity(drive);
- barrier = ide_id_has_flush_cache(id) &&
+ barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
(drive->addressing == 0 || capacity <= (1ULL << 28) ||
ide_id_has_flush_cache_ext(id));
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 98918fb6b2ce..7c3a13e1cf64 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -750,7 +750,7 @@ void ide_dma_verbose(ide_drive_t *drive)
goto bug_dma_off;
printk(", DMA");
} else if (id->field_valid & 1) {
- printk(", BUG");
+ goto bug_dma_off;
}
return;
bug_dma_off:
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 657165297dc7..77703acaec17 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
@@ -1243,6 +1244,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
if (stat == 0xff)
return -ENODEV;
touch_softlockup_watchdog();
+ touch_nmi_watchdog();
}
return -EBUSY;
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 05fbd9298db7..defd4b4bd374 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1539,7 +1539,7 @@ static int __init ide_setup(char *s)
const char *hd_words[] = {
"none", "noprobe", "nowerr", "cdrom", "serialize",
"autotune", "noautotune", "minus8", "swapdata", "bswap",
- "minus11", "remap", "remap63", "scsi", NULL };
+ "noflush", "remap", "remap63", "scsi", NULL };
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
@@ -1578,6 +1578,9 @@ static int __init ide_setup(char *s)
case -10: /* "bswap" */
drive->bswap = 1;
goto done;
+ case -11: /* noflush */
+ drive->noflush = 1;
+ goto done;
case -12: /* "remap" */
drive->remap_0_to_1 = 1;
goto done;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 2f962cfa3f7f..78810ba982e9 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -180,6 +180,36 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
+ },{ /* 15 */
+ .name = "JMB361",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
+ },{ /* 16 */
+ .name = "JMB363",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
+ },{ /* 17 */
+ .name = "JMB365",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
+ },{ /* 18 */
+ .name = "JMB366",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
+ },{ /* 19 */
+ .name = "JMB368",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
}
};
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3cb04424d351..e9bad185968a 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -498,9 +498,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, it821x_ratemask(drive));
- config_it821x_chipset_for_pio(drive, !speed);
- it821x_tune_chipset(drive, speed);
- return ide_dma_enable(drive);
+ if (speed) {
+ config_it821x_chipset_for_pio(drive, 0);
+ it821x_tune_chipset(drive, speed);
+
+ return ide_dma_enable(drive);
+ }
+
+ return 0;
}
/**
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index e125032bb403..d8a0d87df734 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -367,12 +367,13 @@ sgiioc4_INB(unsigned long port)
static void __devinit
ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
{
+ void __iomem *virt_dma_base;
int num_ports = sizeof (ioc4_dma_regs_t);
printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
dma_base, dma_base + num_ports - 1);
- if (!request_region(dma_base, num_ports, hwif->name)) {
+ if (!request_mem_region(dma_base, num_ports, hwif->name)) {
printk(KERN_ERR
"%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
"ALREADY in use\n",
@@ -381,13 +382,21 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
goto dma_alloc_failure;
}
- hwif->dma_base = dma_base;
+ virt_dma_base = ioremap(dma_base, num_ports);
+ if (virt_dma_base == NULL) {
+ printk(KERN_ERR
+ "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
+ __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
+ goto dma_remap_failure;
+ }
+ hwif->dma_base = (unsigned long) virt_dma_base;
+
hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
&hwif->dmatable_dma);
if (!hwif->dmatable_cpu)
- goto dma_alloc_failure;
+ goto dma_pci_alloc_failure;
hwif->sg_max_nents = IOC4_PRD_ENTRIES;
@@ -411,6 +420,12 @@ dma_base2alloc_failure:
printk(KERN_INFO
"Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+dma_pci_alloc_failure:
+ iounmap(virt_dma_base);
+
+dma_remap_failure:
+ release_mem_region(dma_base, num_ports);
+
dma_alloc_failure:
/* Disable DMA because we couldnot allocate any DMA maps */
hwif->autodma = 0;
@@ -607,18 +622,15 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
- /*
- * The IOC4 uses MMIO rather than Port IO.
- * It also needs special workarounds for INB.
- */
- default_hwif_mmiops(hwif);
hwif->INB = &sgiioc4_INB;
}
static int __devinit
sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
{
- unsigned long base, ctl, dma_base, irqport;
+ unsigned long cmd_base, dma_base, irqport;
+ unsigned long bar0, cmd_phys_base, ctl;
+ void __iomem *virt_base;
ide_hwif_t *hwif;
int h;
@@ -636,23 +648,32 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
}
/* Get the CmdBlk and CtrlBlk Base Registers */
- base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
- ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
- irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
+ bar0 = pci_resource_start(dev, 0);
+ virt_base = ioremap(bar0, pci_resource_len(dev, 0));
+ if (virt_base == NULL) {
+ printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
+ d->name, bar0);
+ return -ENOMEM;
+ }
+ cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
+ ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
+ irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
- if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
+ cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
+ if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+ hwif->name)) {
printk(KERN_ERR
- "%s : %s -- ERROR, Port Addresses "
+ "%s : %s -- ERROR, Addresses "
"0x%p to 0x%p ALREADY in use\n",
- __FUNCTION__, hwif->name, (void *) base,
- (void *) base + IOC4_CMD_CTL_BLK_SIZE);
+ __FUNCTION__, hwif->name, (void *) cmd_phys_base,
+ (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
return -ENOMEM;
}
- if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
+ if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
/* Initialize the IO registers */
- sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
+ sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
memcpy(hwif->io_ports, hwif->hw.io_ports,
sizeof (hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
@@ -665,6 +686,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
hwif->cds = (struct ide_pci_device_s *) d;
hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
+ /* The IOC4 uses MMIO rather than Port IO. */
+ default_hwif_mmiops(hwif);
+
/* Initializing chipset IRQ Registers */
hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index afdaee3c15c9..9b7589e8e93e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -6,7 +6,7 @@
*
* vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
* vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a,
- * vt8235, vt8237
+ * vt8235, vt8237, vt8237a
*
* Copyright (c) 2000-2002 Vojtech Pavlik
*
@@ -81,6 +81,7 @@ static struct via_isa_bridge {
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+ { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index d4bad6704bbe..448df2773377 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -3552,6 +3552,8 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
+ pci_save_state(pdev);
+
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
struct device_node *of_node;
@@ -3563,8 +3565,6 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
}
#endif
- pci_save_state(pdev);
-
return 0;
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index aaa74f293aaf..b08755e2e68f 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2515,6 +2515,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
sdev->skip_ms_page_8 = 1;
if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
sdev->fix_capacity = 1;
+ if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
+ (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
+ sdev->allow_restart = 1;
return 0;
}
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index d294bbc42f09..1205e8027829 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
MODULE_AUTHOR("Sean Hefty");
@@ -326,25 +327,22 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
}
EXPORT_SYMBOL(rdma_addr_cancel);
-static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pkt, struct net_device *orig_dev)
+static int netevent_callback(struct notifier_block *self, unsigned long event,
+ void *ctx)
{
- struct arphdr *arp_hdr;
+ if (event == NETEVENT_NEIGH_UPDATE) {
+ struct neighbour *neigh = ctx;
- arp_hdr = (struct arphdr *) skb->nh.raw;
-
- if (arp_hdr->ar_op == htons(ARPOP_REQUEST) ||
- arp_hdr->ar_op == htons(ARPOP_REPLY))
- set_timeout(jiffies);
-
- kfree_skb(skb);
+ if (neigh->dev->type == ARPHRD_INFINIBAND &&
+ (neigh->nud_state & NUD_VALID)) {
+ set_timeout(jiffies);
+ }
+ }
return 0;
}
-static struct packet_type addr_arp = {
- .type = __constant_htons(ETH_P_ARP),
- .func = addr_arp_recv,
- .af_packet_priv = (void*) 1,
+static struct notifier_block nb = {
+ .notifier_call = netevent_callback
};
static int addr_init(void)
@@ -353,13 +351,13 @@ static int addr_init(void)
if (!addr_wq)
return -ENOMEM;
- dev_add_pack(&addr_arp);
+ register_netevent_notifier(&nb);
return 0;
}
static void addr_cleanup(void)
{
- dev_remove_pack(&addr_arp);
+ unregister_netevent_notifier(&nb);
destroy_workqueue(addr_wq);
}
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index e05ca2cdc73f..75313ade2e0d 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -301,7 +301,8 @@ static void ib_cache_event(struct ib_event_handler *handler,
event->event == IB_EVENT_PORT_ACTIVE ||
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
- event->event == IB_EVENT_SM_CHANGE) {
+ event->event == IB_EVENT_SM_CHANGE ||
+ event->event == IB_EVENT_CLIENT_REREGISTER) {
work = kmalloc(sizeof *work, GFP_ATOMIC);
if (work) {
INIT_WORK(&work->work, ib_cache_task, work);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index f85c97f7500a..0de335b7bfc2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -975,8 +975,10 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
id.local_id);
- if (IS_ERR(cm_id_priv->timewait_info))
+ if (IS_ERR(cm_id_priv->timewait_info)) {
+ ret = PTR_ERR(cm_id_priv->timewait_info);
goto out;
+ }
ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);
if (ret)
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index aeda484ffd82..d6b84226bba7 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -405,7 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
event->event == IB_EVENT_PORT_ACTIVE ||
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
- event->event == IB_EVENT_SM_CHANGE) {
+ event->event == IB_EVENT_SM_CHANGE ||
+ event->event == IB_EVENT_CLIENT_REREGISTER) {
struct ib_sa_device *sa_dev;
sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index bb9bee56a824..102a59c033ff 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include
#include
@@ -69,6 +70,7 @@
struct ib_uverbs_device {
struct kref ref;
+ struct completion comp;
int devnum;
struct cdev *dev;
struct class_device *class_dev;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index e725cccc7cde..4e16314e8e6d 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref)
struct ib_uverbs_device *dev =
container_of(ref, struct ib_uverbs_device, ref);
- kfree(dev);
+ complete(&dev->comp);
}
void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
@@ -740,6 +740,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
return;
kref_init(&uverbs_dev->ref);
+ init_completion(&uverbs_dev->comp);
spin_lock(&map_lock);
uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -793,6 +794,8 @@ err_cdev:
err:
kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ wait_for_completion(&uverbs_dev->comp);
+ kfree(uverbs_dev);
return;
}
@@ -812,7 +815,10 @@ static void ib_uverbs_remove_one(struct ib_device *device)
spin_unlock(&map_lock);
clear_bit(uverbs_dev->devnum, dev_map);
+
kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ wait_for_completion(&uverbs_dev->comp);
+ kfree(uverbs_dev);
}
static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index 9ba3211cef7c..f930e55b58fc 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -41,9 +41,11 @@
/* Trivial bitmap-based allocator */
u32 mthca_alloc(struct mthca_alloc *alloc)
{
+ unsigned long flags;
u32 obj;
- spin_lock(&alloc->lock);
+ spin_lock_irqsave(&alloc->lock, flags);
+
obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
if (obj >= alloc->max) {
alloc->top = (alloc->top + alloc->max) & alloc->mask;
@@ -56,19 +58,24 @@ u32 mthca_alloc(struct mthca_alloc *alloc)
} else
obj = -1;
- spin_unlock(&alloc->lock);
+ spin_unlock_irqrestore(&alloc->lock, flags);
return obj;
}
void mthca_free(struct mthca_alloc *alloc, u32 obj)
{
+ unsigned long flags;
+
obj &= alloc->max - 1;
- spin_lock(&alloc->lock);
+
+ spin_lock_irqsave(&alloc->lock, flags);
+
clear_bit(obj, alloc->table);
alloc->last = min(alloc->last, obj);
alloc->top = (alloc->top + alloc->max) & alloc->mask;
- spin_unlock(&alloc->lock);
+
+ spin_unlock_irqrestore(&alloc->lock, flags);
}
int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask,
@@ -108,14 +115,15 @@ void mthca_alloc_cleanup(struct mthca_alloc *alloc)
* serialize access to the array.
*/
+#define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1)
+
void *mthca_array_get(struct mthca_array *array, int index)
{
int p = (index * sizeof (void *)) >> PAGE_SHIFT;
- if (array->page_list[p].page) {
- int i = index & (PAGE_SIZE / sizeof (void *) - 1);
- return array->page_list[p].page[i];
- } else
+ if (array->page_list[p].page)
+ return array->page_list[p].page[index & MTHCA_ARRAY_MASK];
+ else
return NULL;
}
@@ -130,8 +138,7 @@ int mthca_array_set(struct mthca_array *array, int index, void *value)
if (!array->page_list[p].page)
return -ENOMEM;
- array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] =
- value;
+ array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value;
++array->page_list[p].used;
return 0;
@@ -144,7 +151,8 @@ void mthca_array_clear(struct mthca_array *array, int index)
if (--array->page_list[p].used == 0) {
free_page((unsigned long) array->page_list[p].page);
array->page_list[p].page = NULL;
- }
+ } else
+ array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL;
if (array->page_list[p].used < 0)
pr_debug("Array %p index %d page %d with ref count %d < 0\n",
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 557cde3a4563..7b82c1907f04 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -967,12 +967,12 @@ static struct {
} mthca_hca_table[] = {
[TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 4, 0),
.flags = 0 },
- [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 400),
+ [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 600),
.flags = MTHCA_FLAG_PCIE },
- [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0),
+ [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 400),
.flags = MTHCA_FLAG_MEMFREE |
MTHCA_FLAG_PCIE },
- [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 800),
+ [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 1, 0),
.flags = MTHCA_FLAG_MEMFREE |
MTHCA_FLAG_PCIE |
MTHCA_FLAG_SINAI_OPT }
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 230ae21db8fd..265b1d1c4a62 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1287,11 +1287,7 @@ int mthca_register_device(struct mthca_dev *dev)
(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
- (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
- (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
- (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
- (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
- (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+ (1ull << IB_USER_VERBS_CMD_DETACH_MCAST);
dev->ib_dev.node_type = IB_NODE_CA;
dev->ib_dev.phys_port_cnt = dev->limits.num_ports;
dev->ib_dev.dma_device = &dev->pdev->dev;
@@ -1316,6 +1312,11 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.modify_srq = mthca_modify_srq;
dev->ib_dev.query_srq = mthca_query_srq;
dev->ib_dev.destroy_srq = mthca_destroy_srq;
+ dev->ib_dev.uverbs_cmd_mask |=
+ (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
if (mthca_is_memfree(dev))
dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 8de2887ba15c..9a5bece3fa5c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -136,8 +136,8 @@ struct mthca_ah {
* We have one global lock that protects dev->cq/qp_table. Each
* struct mthca_cq/qp also has its own lock. An individual qp lock
* may be taken inside of an individual cq lock. Both cqs attached to
- * a qp may be locked, with the send cq locked first. No other
- * nesting should be done.
+ * a qp may be locked, with the cq with the lower cqn locked first.
+ * No other nesting should be done.
*
* Each struct mthca_cq/qp also has an ref count, protected by the
* corresponding table lock. The pointer from the cq/qp_table to the
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index cd8b6721ac9c..2e8f6f36e0a5 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -99,6 +99,10 @@ enum {
MTHCA_QP_BIT_RSC = 1 << 3
};
+enum {
+ MTHCA_SEND_DOORBELL_FENCE = 1 << 5
+};
+
struct mthca_qp_path {
__be32 port_pkey;
u8 rnr_retry;
@@ -1259,6 +1263,32 @@ int mthca_alloc_qp(struct mthca_dev *dev,
return 0;
}
+static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_lock_irq(&send_cq->lock);
+ else if (send_cq->cqn < recv_cq->cqn) {
+ spin_lock_irq(&send_cq->lock);
+ spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
+ } else {
+ spin_lock_irq(&recv_cq->lock);
+ spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
+ }
+}
+
+static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_unlock_irq(&send_cq->lock);
+ else if (send_cq->cqn < recv_cq->cqn) {
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
+ } else {
+ spin_unlock(&send_cq->lock);
+ spin_unlock_irq(&recv_cq->lock);
+ }
+}
+
int mthca_alloc_sqp(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
@@ -1311,17 +1341,13 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- spin_lock_irq(&send_cq->lock);
- if (send_cq != recv_cq)
- spin_lock(&recv_cq->lock);
+ mthca_lock_cqs(send_cq, recv_cq);
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp, mqpn);
spin_unlock(&dev->qp_table.lock);
- if (send_cq != recv_cq)
- spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ mthca_unlock_cqs(send_cq, recv_cq);
err_out:
dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
@@ -1355,9 +1381,7 @@ void mthca_free_qp(struct mthca_dev *dev,
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- spin_lock_irq(&send_cq->lock);
- if (send_cq != recv_cq)
- spin_lock(&recv_cq->lock);
+ mthca_lock_cqs(send_cq, recv_cq);
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp,
@@ -1365,9 +1389,7 @@ void mthca_free_qp(struct mthca_dev *dev,
--qp->refcount;
spin_unlock(&dev->qp_table.lock);
- if (send_cq != recv_cq)
- spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ mthca_unlock_cqs(send_cq, recv_cq);
wait_event(qp->wait, !get_qp_refcount(dev, qp));
@@ -1502,7 +1524,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int i;
int size;
int size0 = 0;
- u32 f0 = 0;
+ u32 f0;
int ind;
u8 op0 = 0;
@@ -1686,6 +1708,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
if (!size0) {
size0 = size;
op0 = mthca_opcode[wr->opcode];
+ f0 = wr->send_flags & IB_SEND_FENCE ?
+ MTHCA_SEND_DOORBELL_FENCE : 0;
}
++ind;
@@ -1843,7 +1867,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int i;
int size;
int size0 = 0;
- u32 f0 = 0;
+ u32 f0;
int ind;
u8 op0 = 0;
@@ -2051,6 +2075,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
if (!size0) {
size0 = size;
op0 = mthca_opcode[wr->opcode];
+ f0 = wr->send_flags & IB_SEND_FENCE ?
+ MTHCA_SEND_DOORBELL_FENCE : 0;
}
++ind;
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 13d6d01c72c0..d74653d7de1c 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -6,8 +6,7 @@ config INFINIBAND_IPOIB
transports IP packets over InfiniBand so you can use your IB
device as a fancy NIC.
- The IPoIB protocol is defined by the IETF ipoib working
- group: .
+ See Documentation/infiniband/ipoib.txt for more information
config INFINIBAND_IPOIB_DEBUG
bool "IP-over-InfiniBand debugging" if EMBEDDED
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 34b0da5cfa0a..1437d7ee3b19 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -378,21 +378,6 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
return iser_conn_set_full_featured_mode(conn);
}
-static void
-iscsi_iser_conn_terminate(struct iscsi_conn *conn)
-{
- struct iscsi_iser_conn *iser_conn = conn->dd_data;
- struct iser_conn *ib_conn = iser_conn->ib_conn;
-
- BUG_ON(!ib_conn);
- /* starts conn teardown process, waits until all previously *
- * posted buffers get flushed, deallocates all conn resources */
- iser_conn_terminate(ib_conn);
- iser_conn->ib_conn = NULL;
- conn->recv_lock = NULL;
-}
-
-
static struct iscsi_transport iscsi_iser_transport;
static struct iscsi_cls_session *
@@ -555,13 +540,13 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
static void
iscsi_iser_ep_disconnect(__u64 ep_handle)
{
- struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+ struct iser_conn *ib_conn;
+ ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
if (!ib_conn)
return;
iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
-
iser_conn_terminate(ib_conn);
}
@@ -614,9 +599,6 @@ static struct iscsi_transport iscsi_iser_transport = {
.get_session_param = iscsi_session_get_param,
.start_conn = iscsi_iser_conn_start,
.stop_conn = iscsi_conn_stop,
- /* these are called as part of conn recovery */
- .suspend_conn_recv = NULL, /* FIXME is/how this relvant to iser? */
- .terminate_conn = iscsi_iser_conn_terminate,
/* IO */
.send_pdu = iscsi_conn_send_pdu,
.get_stats = iscsi_iser_conn_get_stats,
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 8f472e7113b4..8257d5a2c8f8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -77,6 +77,14 @@ MODULE_PARM_DESC(topspin_workarounds,
static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
+static int mellanox_workarounds = 1;
+
+module_param(mellanox_workarounds, int, 0444);
+MODULE_PARM_DESC(mellanox_workarounds,
+ "Enable workarounds for Mellanox SRP target bugs if != 0");
+
+static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 };
+
static void srp_add_one(struct ib_device *device);
static void srp_remove_one(struct ib_device *device);
static void srp_completion(struct ib_cq *cq, void *target_ptr);
@@ -526,8 +534,10 @@ static int srp_reconnect_target(struct srp_target_port *target)
while (ib_poll_cq(target->cq, 1, &wc) > 0)
; /* nothing */
+ spin_lock_irq(target->scsi_host->host_lock);
list_for_each_entry_safe(req, tmp, &target->req_queue, list)
srp_reset_req(target, req);
+ spin_unlock_irq(target->scsi_host->host_lock);
target->rx_head = 0;
target->tx_head = 0;
@@ -567,7 +577,7 @@ err:
return ret;
}
-static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
+static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
int sg_cnt, struct srp_request *req,
struct srp_direct_buf *buf)
{
@@ -577,10 +587,15 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
int page_cnt;
int i, j;
int ret;
+ struct srp_device *dev = target->srp_host->dev;
if (!dev->fmr_pool)
return -ENODEV;
+ if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) &&
+ mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3))
+ return -EINVAL;
+
len = page_cnt = 0;
for (i = 0; i < sg_cnt; ++i) {
if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
@@ -683,7 +698,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
buf->va = cpu_to_be64(sg_dma_address(scat));
buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
buf->len = cpu_to_be32(sg_dma_len(scat));
- } else if (srp_map_fmr(target->srp_host->dev, scat, count, req,
+ } else if (srp_map_fmr(target, scat, count, req,
(void *) cmd->add_data)) {
/*
* FMR mapping failed, and the scatterlist has more
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a29d5ceb00cf..4bf48188cc91 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -127,14 +127,10 @@ static int evdev_open(struct inode * inode, struct file * file)
{
struct evdev_list *list;
int i = iminor(inode) - EVDEV_MINOR_BASE;
- int accept_err;
if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
return -ENODEV;
- if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
- return accept_err;
-
if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
@@ -260,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
if (evdev_event_from_user(buffer + retval, &event))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+ input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
retval += evdev_event_size();
}
@@ -428,8 +424,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
if (get_user(v, ip + 1))
return -EFAULT;
- input_event(dev, EV_REP, REP_DELAY, u);
- input_event(dev, EV_REP, REP_PERIOD, v);
+ input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+ input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
return 0;
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 47e93daa0fa7..90de5afe03c2 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
gp->gameport = port;
gp->res_port = request_region(port->io, 0x10, "FM801 GP");
if (!gp->res_port) {
- kfree(gp);
- gameport_free_port(port);
printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
port->io, port->io + 0x0f);
+ gameport_free_port(port);
+ kfree(gp);
return -EBUSY;
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 36644bff379d..3f47ae55c6f3 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -53,6 +53,7 @@ static LIST_HEAD(gameport_list);
static struct bus_type gameport_bus;
+static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
static void gameport_reconnect_port(struct gameport *gameport);
@@ -211,8 +212,14 @@ static void gameport_release_driver(struct gameport *gameport)
static void gameport_find_driver(struct gameport *gameport)
{
+ int error;
+
down_write(&gameport_bus.subsys.rwsem);
- device_attach(&gameport->dev);
+ error = device_attach(&gameport->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "gameport: device_attach() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
up_write(&gameport_bus.subsys.rwsem);
}
@@ -316,7 +323,6 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
spin_unlock_irqrestore(&gameport_event_lock, flags);
}
-
static struct gameport_event *gameport_get_event(void)
{
struct gameport_event *event;
@@ -342,7 +348,6 @@ static struct gameport_event *gameport_get_event(void)
static void gameport_handle_event(void)
{
struct gameport_event *event;
- struct gameport_driver *gameport_drv;
mutex_lock(&gameport_mutex);
@@ -369,8 +374,7 @@ static void gameport_handle_event(void)
break;
case GAMEPORT_REGISTER_DRIVER:
- gameport_drv = event->object;
- driver_register(&gameport_drv->driver);
+ gameport_add_driver(event->object);
break;
default:
@@ -532,6 +536,7 @@ static void gameport_init_port(struct gameport *gameport)
if (gameport->parent)
gameport->dev.parent = &gameport->parent->dev;
+ INIT_LIST_HEAD(&gameport->node);
spin_lock_init(&gameport->timer_lock);
init_timer(&gameport->poll_timer);
gameport->poll_timer.function = gameport_run_poll_handler;
@@ -544,6 +549,8 @@ static void gameport_init_port(struct gameport *gameport)
*/
static void gameport_add_port(struct gameport *gameport)
{
+ int error;
+
if (gameport->parent)
gameport->parent->child = gameport;
@@ -558,8 +565,13 @@ static void gameport_add_port(struct gameport *gameport)
printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
gameport->name, gameport->phys, gameport->speed);
- device_add(&gameport->dev);
- gameport->registered = 1;
+ error = device_add(&gameport->dev);
+ if (error)
+ printk(KERN_ERR
+ "gameport: device_add() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
+ else
+ gameport->registered = 1;
}
/*
@@ -583,10 +595,11 @@ static void gameport_destroy_port(struct gameport *gameport)
if (gameport->registered) {
device_del(&gameport->dev);
- list_del_init(&gameport->node);
gameport->registered = 0;
}
+ list_del_init(&gameport->node);
+
gameport_remove_pending_events(gameport);
put_device(&gameport->dev);
}
@@ -704,11 +717,22 @@ static int gameport_driver_remove(struct device *dev)
}
static struct bus_type gameport_bus = {
- .name = "gameport",
- .probe = gameport_driver_probe,
- .remove = gameport_driver_remove,
+ .name = "gameport",
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
};
+static void gameport_add_driver(struct gameport_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "gameport: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
drv->driver.bus = &gameport_bus;
@@ -778,16 +802,24 @@ void gameport_close(struct gameport *gameport)
static int __init gameport_init(void)
{
- gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
- if (IS_ERR(gameport_task)) {
- printk(KERN_ERR "gameport: Failed to start kgameportd\n");
- return PTR_ERR(gameport_task);
- }
+ int error;
gameport_bus.dev_attrs = gameport_device_attrs;
gameport_bus.drv_attrs = gameport_driver_attrs;
gameport_bus.match = gameport_bus_match;
- bus_register(&gameport_bus);
+ error = bus_register(&gameport_bus);
+ if (error) {
+ printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
+ return error;
+ }
+
+ gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
+ if (IS_ERR(gameport_task)) {
+ bus_unregister(&gameport_bus);
+ error = PTR_ERR(gameport_task);
+ printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a90486f5e491..9cb4b9a54f01 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -35,6 +35,16 @@ static LIST_HEAD(input_handler_list);
static struct input_handler *input_table[8];
+/**
+ * input_event() - report new input event
+ * @handle: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
@@ -183,6 +193,23 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
}
EXPORT_SYMBOL(input_event);
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+ if (!handle->dev->grab || handle->dev->grab == handle)
+ input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
@@ -197,15 +224,6 @@ static void input_repeat_key(unsigned long data)
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
- if (handle->dev->accept)
- return handle->dev->accept(handle->dev, file);
-
- return 0;
-}
-EXPORT_SYMBOL(input_accept_process);
-
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
@@ -218,8 +236,15 @@ EXPORT_SYMBOL(input_grab_device);
void input_release_device(struct input_handle *handle)
{
- if (handle->dev->grab == handle)
- handle->dev->grab = NULL;
+ struct input_dev *dev = handle->dev;
+
+ if (dev->grab == handle) {
+ dev->grab = NULL;
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ if (handle->handler->start)
+ handle->handler->start(handle);
+ }
}
EXPORT_SYMBOL(input_release_device);
@@ -963,8 +988,11 @@ int input_register_device(struct input_dev *dev)
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
@@ -1028,8 +1056,11 @@ void input_register_handler(struct input_handler *handler)
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 6d99e3c37884..b4914e7231f8 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -79,6 +79,7 @@ static struct iforce_device iforce_device[] = {
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
+ { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
@@ -222,22 +223,22 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id)
int err = 0;
struct iforce_core_effect* core_effect;
- /* Check who is trying to erase this effect */
- if (iforce->core_effects[effect_id].owner != current->pid) {
- printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
- return -EACCES;
- }
-
if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
return -EINVAL;
- core_effect = iforce->core_effects + effect_id;
+ core_effect = &iforce->core_effects[effect_id];
+
+ /* Check who is trying to erase this effect */
+ if (core_effect->owner != current->pid) {
+ printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner);
+ return -EACCES;
+ }
if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
+ err = release_resource(&core_effect->mod1_chunk);
if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
+ err = release_resource(&core_effect->mod2_chunk);
/*TODO: remember to change that if more FF_MOD* bits are added */
core_effect->flags[0] = 0;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 75eb5ca59992..7a19ee052972 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
*/
#define SPACEBALL_MAX_LENGTH 128
-#define SPACEBALL_MAX_ID 8
+#define SPACEBALL_MAX_ID 9
#define SPACEBALL_1003 1
#define SPACEBALL_2003B 3
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ce1f10e8984b..a86afd0a5ef1 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -482,6 +482,55 @@ out:
return IRQ_HANDLED;
}
+static int atkbd_set_repeat_rate(struct atkbd *atkbd)
+{
+ const short period[32] =
+ { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
+ 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
+ const short delay[4] =
+ { 250, 500, 750, 1000 };
+
+ struct input_dev *dev = atkbd->dev;
+ unsigned char param;
+ int i = 0, j = 0;
+
+ while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
+ i++;
+ dev->rep[REP_PERIOD] = period[i];
+
+ while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY])
+ j++;
+ dev->rep[REP_DELAY] = delay[j];
+
+ param = i | (j << 5);
+ return ps2_command(&atkbd->ps2dev, ¶m, ATKBD_CMD_SETREP);
+}
+
+static int atkbd_set_leds(struct atkbd *atkbd)
+{
+ struct input_dev *dev = atkbd->dev;
+ unsigned char param[2];
+
+ param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
+ return -1;
+
+ if (atkbd->extra) {
+ param[0] = 0;
+ param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
+ | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
+ | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
+ | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
+ | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* atkbd_event_work() is used to complete processing of events that
* can not be processed by input_event() which is often called from
@@ -490,47 +539,15 @@ out:
static void atkbd_event_work(void *data)
{
- const short period[32] =
- { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
- 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
- const short delay[4] =
- { 250, 500, 750, 1000 };
-
struct atkbd *atkbd = data;
- struct input_dev *dev = atkbd->dev;
- unsigned char param[2];
- int i, j;
mutex_lock(&atkbd->event_mutex);
- if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
- param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_leds(atkbd);
- if (atkbd->extra) {
- param[0] = 0;
- param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
- | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
- | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
- | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
- | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
- }
- }
-
- if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {
- i = j = 0;
- while (i < 31 && period[i] < dev->rep[REP_PERIOD])
- i++;
- while (j < 3 && delay[j] < dev->rep[REP_DELAY])
- j++;
- dev->rep[REP_PERIOD] = period[i];
- dev->rep[REP_DELAY] = delay[j];
- param[0] = i | (j << 5);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
- }
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_repeat_rate(atkbd);
mutex_unlock(&atkbd->event_mutex);
}
@@ -975,7 +992,6 @@ static int atkbd_reconnect(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
- unsigned char param[1];
if (!atkbd || !drv) {
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
@@ -985,10 +1001,6 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd);
if (atkbd->write) {
- param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
-
if (atkbd_probe(atkbd))
return -1;
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
@@ -996,8 +1008,13 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_activate(atkbd);
- if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
- return -1;
+/*
+ * Restore repeat rate and LEDs (that were reset by atkbd_activate)
+ * to pre-resume state
+ */
+ if (!atkbd->softrepeat)
+ atkbd_set_repeat_rate(atkbd);
+ atkbd_set_leds(atkbd);
}
atkbd_enable(atkbd);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index ccf0faeee5c1..de0f46dd9692 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -94,7 +94,7 @@ static void call_bios(struct regs *regs)
static ssize_t __init locate_wistron_bios(void __iomem *base)
{
- static const unsigned char __initdata signature[] =
+ static unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
ssize_t offset;
@@ -343,7 +343,7 @@ static struct key_entry keymap_aopen_1559as[] = {
* a list of buttons and their key codes (reported when loading this module
* with force=1) and the output of dmidecode to $MODULE_AUTHOR.
*/
-static struct dmi_system_id dmi_ids[] = {
+static struct dmi_system_id dmi_ids[] __initdata = {
{
.callback = dmi_matched,
.ident = "Fujitsu-Siemens Amilo Pro V2000",
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 2f0d28840810..54b696cfe1e3 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -238,8 +238,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
- { 111, PS2PP_KIND_MX, /* MX300 */
- PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+ { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */
{ 112, PS2PP_KIND_MX, /* MX500 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 8bc9f51ae6c2..343afa38f4c2 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -485,13 +485,6 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties)
param[0] = 40;
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
- param[0] = 200;
- ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
- param[0] = 200;
- ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
- param[0] = 60;
- ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
-
if (set_properties) {
set_bit(BTN_MIDDLE, psmouse->dev->keybit);
set_bit(REL_WHEEL, psmouse->dev->relbit);
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 6d9ec9ab1b90..ae5871a0e060 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -183,21 +183,26 @@ static struct attribute_group trackpoint_attr_group = {
.attrs = trackpoint_attrs,
};
-static void trackpoint_disconnect(struct psmouse *psmouse)
+static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id)
{
- sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+ unsigned char param[2] = { 0 };
- kfree(psmouse->private);
- psmouse->private = NULL;
+ if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+ return -1;
+
+ if (param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ if (firmware_id)
+ *firmware_id = param[1];
+
+ return 0;
}
static int trackpoint_sync(struct psmouse *psmouse)
{
- unsigned char toggle;
struct trackpoint_data *tp = psmouse->private;
-
- if (!tp)
- return -1;
+ unsigned char toggle;
/* Disable features that may make device unusable with this driver */
trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
@@ -263,27 +268,38 @@ static void trackpoint_defaults(struct trackpoint_data *tp)
tp->ext_dev = TP_DEF_EXT_DEV;
}
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+ kfree(psmouse->private);
+ psmouse->private = NULL;
+}
+
+static int trackpoint_reconnect(struct psmouse *psmouse)
+{
+ if (trackpoint_start_protocol(psmouse, NULL))
+ return -1;
+
+ if (trackpoint_sync(psmouse))
+ return -1;
+
+ return 0;
+}
+
int trackpoint_detect(struct psmouse *psmouse, int set_properties)
{
struct trackpoint_data *priv;
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char firmware_id;
unsigned char button_info;
- unsigned char param[2];
- param[0] = param[1] = 0;
-
- if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
- return -1;
-
- if (param[0] != TP_MAGIC_IDENT)
+ if (trackpoint_start_protocol(psmouse, &firmware_id))
return -1;
if (!set_properties)
return 0;
- firmware_id = param[1];
-
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
button_info = 0;
@@ -296,7 +312,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
psmouse->vendor = "IBM";
psmouse->name = "TrackPoint";
- psmouse->reconnect = trackpoint_sync;
+ psmouse->reconnect = trackpoint_reconnect;
psmouse->disconnect = trackpoint_disconnect;
trackpoint_defaults(priv);
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 61a6f977846f..ed202f2f251a 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -177,6 +177,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
return -1;
}
+ if (send && !param) {
+ WARN_ON(1);
+ return -1;
+ }
+
mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING);
serio_pause_rx(ps2dev->serio);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 6521034bc933..3e76ad71c9a0 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -62,6 +62,7 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus;
+static void serio_add_driver(struct serio_driver *drv);
static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
@@ -140,8 +141,14 @@ static void serio_release_driver(struct serio *serio)
static void serio_find_driver(struct serio *serio)
{
+ int error;
+
down_write(&serio_bus.subsys.rwsem);
- device_attach(&serio->dev);
+ error = device_attach(&serio->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "serio: device_attach() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
up_write(&serio_bus.subsys.rwsem);
}
@@ -272,7 +279,6 @@ static struct serio_event *serio_get_event(void)
static void serio_handle_event(void)
{
struct serio_event *event;
- struct serio_driver *serio_drv;
mutex_lock(&serio_mutex);
@@ -304,8 +310,7 @@ static void serio_handle_event(void)
break;
case SERIO_REGISTER_DRIVER:
- serio_drv = event->object;
- driver_register(&serio_drv->driver);
+ serio_add_driver(event->object);
break;
default:
@@ -525,6 +530,7 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE);
+ INIT_LIST_HEAD(&serio->node);
spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
@@ -542,6 +548,8 @@ static void serio_init_port(struct serio *serio)
*/
static void serio_add_port(struct serio *serio)
{
+ int error;
+
if (serio->parent) {
serio_pause_rx(serio->parent);
serio->parent->child = serio;
@@ -551,9 +559,19 @@ static void serio_add_port(struct serio *serio)
list_add_tail(&serio->node, &serio_list);
if (serio->start)
serio->start(serio);
- device_add(&serio->dev);
- sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
- serio->registered = 1;
+ error = device_add(&serio->dev);
+ if (error)
+ printk(KERN_ERR
+ "serio: device_add() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ else {
+ serio->registered = 1;
+ error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
+ if (error)
+ printk(KERN_ERR
+ "serio: sysfs_create_group() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ }
}
/*
@@ -583,10 +601,10 @@ static void serio_destroy_port(struct serio *serio)
if (serio->registered) {
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev);
- list_del_init(&serio->node);
serio->registered = 0;
}
+ list_del_init(&serio->node);
serio_remove_pending_events(serio);
put_device(&serio->dev);
}
@@ -756,6 +774,17 @@ static struct bus_type serio_bus = {
.remove = serio_driver_remove,
};
+static void serio_add_driver(struct serio_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "serio: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
@@ -903,18 +932,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void)
{
- serio_task = kthread_run(serio_thread, NULL, "kseriod");
- if (IS_ERR(serio_task)) {
- printk(KERN_ERR "serio: Failed to start kseriod\n");
- return PTR_ERR(serio_task);
- }
+ int error;
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
serio_bus.match = serio_bus_match;
serio_bus.uevent = serio_uevent;
serio_bus.resume = serio_resume;
- bus_register(&serio_bus);
+ error = bus_register(&serio_bus);
+ if (error) {
+ printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
+ return error;
+ }
+
+ serio_task = kthread_run(serio_thread, NULL, "kseriod");
+ if (IS_ERR(serio_task)) {
+ bus_unregister(&serio_bus);
+ error = PTR_ERR(serio_task);
+ printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
index 0a5be7f969f2..af3eb9e795b5 100644
--- a/drivers/isdn/hardware/eicon/divasync.h
+++ b/drivers/isdn/hardware/eicon/divasync.h
@@ -256,7 +256,6 @@ typedef struct
#define NO_ORDER_CHECK_MASK 0x00000010
#define LOW_CHANNEL_MASK 0x00000020
#define NO_HSCX30_MASK 0x00000040
-#define MODE_MASK 0x00000080
#define SET_BOARD 0x00001000
#define SET_CRC4 0x00030000
#define SET_L1_TRISTATE 0x00040000
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index f5fe7fb4b3ad..d5d649f5ccdb 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -90,6 +90,15 @@ config ADB_PMU_LED
and the ide-disk LED trigger and configure appropriately through
sysfs.
+config ADB_PMU_LED_IDE
+ bool "Use front LED as IDE LED by default"
+ depends on ADB_PMU_LED
+ select LEDS_TRIGGERS
+ select LEDS_TRIGGER_IDE_DISK
+ help
+ This option makes the front LED default to the IDE trigger
+ so that it blinks on IDE activity.
+
config PMAC_SMU
bool "Support for SMU based PowerMacs"
depends on PPC_PMAC64
@@ -100,7 +109,7 @@ config PMAC_SMU
config PMAC_APM_EMU
tristate "APM emulation"
- depends on PPC_PMAC && PPC32 && PM
+ depends on PPC_PMAC && PPC32 && PM && ADB_PMU
config PMAC_MEDIABAY
bool "Support PowerBook hotswap media bay"
@@ -115,8 +124,6 @@ config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
depends on ADB_PMU && FB = y && (BROKEN || !PPC64)
select FB_BACKLIGHT
- select BACKLIGHT_CLASS_DEVICE
- select BACKLIGHT_LCD_SUPPORT
help
Say Y here to enable Macintosh specific extensions of the generic
backlight code. With this enabled, the brightness keys on older
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 545be1ed6927..c69d23bb255e 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -45,14 +45,11 @@
#include
#include
+#include
#ifdef CONFIG_PPC_PMAC
#include
#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include
-#endif
-
MODULE_AUTHOR("Franz Sirl ");
#define KEYB_KEYREG 0 /* register # for key up/down data */
@@ -237,11 +234,6 @@ static struct adb_ids keyboard_ids;
static struct adb_ids mouse_ids;
static struct adb_ids buttons_ids;
-#ifdef CONFIG_PMAC_BACKLIGHT
-/* Exported to via-pmu.c */
-int disable_kernel_backlight = 0;
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
/* Kind of keyboard, see Apple technote 1152 */
#define ADB_KEYBOARD_UNKNOWN 0
#define ADB_KEYBOARD_ANSI 0x0100
@@ -527,7 +519,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0xa: /* brightness decrease */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight && down)
+ if (down)
pmac_backlight_key_down();
#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
@@ -535,7 +527,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0x9: /* brightness increase */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight && down)
+ if (down)
pmac_backlight_key_up();
#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index c1fe0b368f76..20bf67244e2c 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -95,6 +95,17 @@
* - Use min/max macros here or there
* - Latest darwin updated U3H min fan speed to 20% PWM
*
+ * July. 06, 2006 : 1.3
+ * - Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ * - Add missing slots fan control loop for Xserve G5
+ * - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ * still can't properly implement the control loop for these, so let's
+ * reduce the noise a little bit, it appears that 40% still gives us
+ * a pretty good air flow
+ * - Add code to "tickle" the FCU regulary so it doesn't think that
+ * we are gone while in fact, the machine just didn't need any fan
+ * speed change lately
+ *
*/
#include
@@ -121,7 +132,7 @@
#include "therm_pm72.h"
-#define VERSION "1.2b2"
+#define VERSION "1.3"
#undef DEBUG
@@ -146,6 +157,7 @@ static struct basckside_pid_params backside_params;
static struct backside_pid_state backside_state;
static struct drives_pid_state drives_state;
static struct dimm_pid_state dimms_state;
+static struct slots_pid_state slots_state;
static int state;
static int cpu_count;
static int cpu_pid_type;
@@ -154,7 +166,8 @@ static struct completion ctrl_complete;
static int critical_state;
static int rackmac;
static s32 dimm_output_clamp;
-
+static int fcu_rpm_shift;
+static int fcu_tickle_ticks;
static DECLARE_MUTEX(driver_lock);
/*
@@ -495,13 +508,20 @@ static int start_fcu(void)
rc = fan_write_reg(0x2e, &buf, 1);
if (rc < 0)
return -EIO;
+ rc = fan_read_reg(0, &buf, 1);
+ if (rc < 0)
+ return -EIO;
+ fcu_rpm_shift = (buf == 1) ? 2 : 3;
+ printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+ fcu_rpm_shift);
+
return 0;
}
static int set_rpm_fan(int fan_index, int rpm)
{
unsigned char buf[2];
- int rc, id;
+ int rc, id, min, max;
if (fcu_fans[fan_index].type != FCU_FAN_RPM)
return -EINVAL;
@@ -509,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm)
if (id == FCU_FAN_ABSENT_ID)
return -EINVAL;
- if (rpm < 300)
- rpm = 300;
- else if (rpm > 8191)
- rpm = 8191;
- buf[0] = rpm >> 5;
- buf[1] = rpm << 3;
+ min = 2400 >> fcu_rpm_shift;
+ max = 56000 >> fcu_rpm_shift;
+
+ if (rpm < min)
+ rpm = min;
+ else if (rpm > max)
+ rpm = max;
+ buf[0] = rpm >> (8 - fcu_rpm_shift);
+ buf[1] = rpm << fcu_rpm_shift;
rc = fan_write_reg(0x10 + (id * 2), buf, 2);
if (rc < 0)
return -EIO;
@@ -551,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed)
if (rc != 2)
return -EIO;
- return (buf[0] << 5) | buf[1] >> 3;
+ return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
}
static int set_pwm_fan(int fan_index, int pwm)
@@ -609,6 +632,26 @@ static int get_pwm_fan(int fan_index)
return (buf[0] * 1000) / 2559;
}
+static void tickle_fcu(void)
+{
+ int pwm;
+
+ pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+
+ DBG("FCU Tickle, slots fan is: %d\n", pwm);
+ if (pwm < 0)
+ pwm = 100;
+
+ if (!rackmac) {
+ pwm = SLOTS_FAN_DEFAULT_PWM;
+ } else if (pwm < SLOTS_PID_OUTPUT_MIN)
+ pwm = SLOTS_PID_OUTPUT_MIN;
+
+ /* That is hopefully enough to make the FCU happy */
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
+}
+
+
/*
* Utility routine to read the CPU calibration EEPROM data
* from the device-tree
@@ -715,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
/*
@@ -1076,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
fan_min = dimm_output_clamp;
fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
+ DBG(" CPU min mpu = %d, min dimm = %d\n",
+ state->mpu.rminn_intake_fan, dimm_output_clamp);
+
state->rpm = max(state->rpm, (int)fan_min);
state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
state->intake_rpm = state->rpm;
@@ -1374,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state)
DBG(" current rpm: %d\n", state->rpm);
/* Get some sensor readings */
- temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+ temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+ DS1775_TEMP)) << 8;
state->last_temp = temp;
DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
}
/*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
*/
static void dispose_dimms_state(struct dimm_pid_state *state)
{
@@ -1588,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
state->monitor = NULL;
}
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+ s32 temp, integral, derivative;
+ s64 integ_p, deriv_p, prop_p, sum;
+ int i, rc;
+
+ if (--state->ticks != 0)
+ return;
+ state->ticks = SLOTS_PID_INTERVAL;
+
+ DBG("slots:\n");
+
+ /* Check fan status */
+ rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+ if (rc < 0) {
+ printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+ /* XXX What do we do now ? */
+ } else
+ state->pwm = rc;
+ DBG(" current pwm: %d\n", state->pwm);
+
+ /* Get some sensor readings */
+ temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+ DS1775_TEMP)) << 8;
+ state->last_temp = temp;
+ DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+ FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+ /* Store temperature and error in history array */
+ state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+ /* If first loop, fill the history table */
+ if (state->first) {
+ for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+ state->cur_sample = (state->cur_sample + 1) %
+ SLOTS_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] =
+ temp - SLOTS_PID_INPUT_TARGET;
+ }
+ state->first = 0;
+ }
+
+ /* Calculate the integral term */
+ sum = 0;
+ integral = 0;
+ for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+ integral += state->error_history[i];
+ integral *= SLOTS_PID_INTERVAL;
+ DBG(" integral: %08x\n", integral);
+ integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+ DBG(" integ_p: %d\n", (int)(integ_p >> 36));
+ sum += integ_p;
+
+ /* Calculate the derivative term */
+ derivative = state->error_history[state->cur_sample] -
+ state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+ % SLOTS_PID_HISTORY_SIZE];
+ derivative /= SLOTS_PID_INTERVAL;
+ deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+ DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
+ sum += deriv_p;
+
+ /* Calculate the proportional term */
+ prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+ DBG(" prop_p: %d\n", (int)(prop_p >> 36));
+ sum += prop_p;
+
+ /* Scale sum */
+ sum >>= 36;
+
+ DBG(" sum: %d\n", (int)sum);
+ state->pwm = (s32)sum;
+
+ state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+ state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+ DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+ state->ticks = 1;
+ state->first = 1;
+ state->pwm = 50;
+
+ state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+ if (state->monitor == NULL)
+ return -ENODEV;
+
+ device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+ device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+ return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+ if (state->monitor == NULL)
+ return;
+
+ device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+ device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+ detach_i2c_chip(state->monitor);
+ state->monitor = NULL;
+}
+
+
static int call_critical_overtemp(void)
{
char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,14 +1791,17 @@ static int main_control_loop(void *x)
goto out;
}
- /* Set the PCI fan once for now */
- set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+ /* Set the PCI fan once for now on non-RackMac */
+ if (!rackmac)
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
/* Initialize ADCs */
initialize_adc(&cpu_state[0]);
if (cpu_state[1].monitor != NULL)
initialize_adc(&cpu_state[1]);
+ fcu_tickle_ticks = FCU_TICKLE_TICKS;
+
up(&driver_lock);
while (state == state_attached) {
@@ -1634,6 +1811,12 @@ static int main_control_loop(void *x)
down(&driver_lock);
+ /* Tickle the FCU just in case */
+ if (--fcu_tickle_ticks < 0) {
+ fcu_tickle_ticks = FCU_TICKLE_TICKS;
+ tickle_fcu();
+ }
+
/* First, we always calculate the new DIMMs state on an Xserve */
if (rackmac)
do_monitor_dimms(&dimms_state);
@@ -1654,7 +1837,9 @@ static int main_control_loop(void *x)
}
/* Then, the rest */
do_monitor_backside(&backside_state);
- if (!rackmac)
+ if (rackmac)
+ do_monitor_slots(&slots_state);
+ else
do_monitor_drives(&drives_state);
up(&driver_lock);
@@ -1696,6 +1881,7 @@ static void dispose_control_loops(void)
dispose_cpu_state(&cpu_state[1]);
dispose_backside_state(&backside_state);
dispose_drives_state(&drives_state);
+ dispose_slots_state(&slots_state);
dispose_dimms_state(&dimms_state);
}
@@ -1745,6 +1931,8 @@ static int create_control_loops(void)
goto fail;
if (rackmac && init_dimms_state(&dimms_state))
goto fail;
+ if (rackmac && init_slots_state(&slots_state))
+ goto fail;
if (!rackmac && init_drives_state(&drives_state))
goto fail;
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h
index fc7e9b7ecaf2..393cc9df94e1 100644
--- a/drivers/macintosh/therm_pm72.h
+++ b/drivers/macintosh/therm_pm72.h
@@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
#define DRIVES_DALLAS_ID 0x94
#define BACKSIDE_MAX_ID 0x98
#define XSERVE_DIMMS_LM87 0x25a
+#define XSERVE_SLOTS_LM75 0x290
/*
* Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@ struct drives_pid_state
#define SLOTS_FAN_PWM_DEFAULT_ID 2
#define SLOTS_FAN_PWM_INDEX 2
-#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */
+#define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */
/*
@@ -206,7 +207,7 @@ struct drives_pid_state
*/
#define DIMM_PID_G_d 0
#define DIMM_PID_G_p 0
-#define DIMM_PID_G_r 0x6553600
+#define DIMM_PID_G_r 0x06553600
#define DIMM_PID_INPUT_TARGET 3276800
#define DIMM_PID_INTERVAL 1
#define DIMM_PID_OUTPUT_MAX 14000
@@ -226,6 +227,31 @@ struct dimm_pid_state
};
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d 0
+#define SLOTS_PID_G_p 0
+#define SLOTS_PID_G_r 0x00100000
+#define SLOTS_PID_INPUT_TARGET 3200000
+#define SLOTS_PID_INTERVAL 1
+#define SLOTS_PID_OUTPUT_MAX 100
+#define SLOTS_PID_OUTPUT_MIN 20
+#define SLOTS_PID_HISTORY_SIZE 20
+
+struct slots_pid_state
+{
+ int ticks;
+ struct i2c_client * monitor;
+ s32 sample_history[SLOTS_PID_HISTORY_SIZE];
+ s32 error_history[SLOTS_PID_HISTORY_SIZE];
+ int cur_sample;
+ s32 last_temp;
+ int first;
+ int pwm;
+};
+
+
/* Desktops */
@@ -283,6 +309,9 @@ struct cpu_pid_state
s32 pump_max;
};
+/* Tickle FCU every 10 seconds */
+#define FCU_TICKLE_TICKS 10
+
/*
* Driver state
*/
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index b42d05f2aaff..a82f313d9dc9 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -15,19 +15,51 @@
#define MAX_PMU_LEVEL 0xFF
-static struct device_node *vias;
static struct backlight_properties pmu_backlight_data;
+static spinlock_t pmu_backlight_lock;
+static int sleeping;
+static u8 bl_curve[FB_BACKLIGHT_LEVELS];
-static int pmu_backlight_get_level_brightness(struct fb_info *info,
- int level)
+static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
+{
+ unsigned int i, flat, count, range = (max - min);
+
+ bl_curve[0] = off;
+
+ for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+ bl_curve[flat] = min;
+
+ count = FB_BACKLIGHT_LEVELS * 15 / 16;
+ for (i = 0; i < count; ++i)
+ bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+
+static int pmu_backlight_curve_lookup(int value)
+{
+ int level = (FB_BACKLIGHT_LEVELS - 1);
+ int i, max = 0;
+
+ /* Look for biggest value */
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
+ max = max((int)bl_curve[i], max);
+
+ /* Look for nearest value */
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
+ int diff = abs(bl_curve[i] - value);
+ if (diff < max) {
+ max = diff;
+ level = i;
+ }
+ }
+ return level;
+}
+
+static int pmu_backlight_get_level_brightness(int level)
{
int pmulevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
- pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
- mutex_unlock(&info->bl_mutex);
-
+ pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
if (pmulevel < 0)
pmulevel = 0;
else if (pmulevel > MAX_PMU_LEVEL)
@@ -38,25 +70,37 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info,
static int pmu_backlight_update_status(struct backlight_device *bd)
{
- struct fb_info *info = class_get_devdata(&bd->class_dev);
struct adb_request req;
- int pmulevel, level = bd->props->brightness;
+ unsigned long flags;
+ int level = bd->props->brightness;
- if (vias == NULL)
- return -ENODEV;
+ spin_lock_irqsave(&pmu_backlight_lock, flags);
+
+ /* Don't update brightness when sleeping */
+ if (sleeping)
+ goto out;
if (bd->props->power != FB_BLANK_UNBLANK ||
bd->props->fb_blank != FB_BLANK_UNBLANK)
level = 0;
- pmulevel = pmu_backlight_get_level_brightness(info, level);
+ if (level > 0) {
+ int pmulevel = pmu_backlight_get_level_brightness(level);
- pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
- pmu_wait_complete(&req);
+ pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+ pmu_wait_complete(&req);
- pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
- PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
- pmu_wait_complete(&req);
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_BACKLIGHT | PMU_POW_ON);
+ pmu_wait_complete(&req);
+ } else {
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_BACKLIGHT | PMU_POW_OFF);
+ pmu_wait_complete(&req);
+ }
+
+out:
+ spin_unlock_irqrestore(&pmu_backlight_lock, flags);
return 0;
}
@@ -73,15 +117,23 @@ static struct backlight_properties pmu_backlight_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
-void __init pmu_backlight_init(struct device_node *in_vias)
+#ifdef CONFIG_PM
+void pmu_backlight_set_sleep(int sleep)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmu_backlight_lock, flags);
+ sleeping = sleep;
+ spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+}
+#endif /* CONFIG_PM */
+
+void __init pmu_backlight_init()
{
struct backlight_device *bd;
- struct fb_info *info;
char name[10];
int level, autosave;
- vias = in_vias;
-
/* Special case for the old PowerBook since I can't test on it */
autosave =
machine_is_compatible("AAPL,3400/2400") ||
@@ -93,27 +145,14 @@ void __init pmu_backlight_init(struct device_node *in_vias)
!machine_is_compatible("PowerBook1,1"))
return;
- /* Actually, this is a hack, but I don't know of a better way
- * to get the first framebuffer device.
- */
- info = registered_fb[0];
- if (!info) {
- printk("pmubl: No framebuffer found\n");
- goto error;
- }
+ snprintf(name, sizeof(name), "pmubl");
- snprintf(name, sizeof(name), "pmubl%d", info->node);
-
- bd = backlight_device_register(name, info, &pmu_backlight_data);
+ bd = backlight_device_register(name, NULL, &pmu_backlight_data);
if (IS_ERR(bd)) {
printk("pmubl: Backlight registration failed\n");
goto error;
}
-
- mutex_lock(&info->bl_mutex);
- info->bl_dev = bd;
- fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
- mutex_unlock(&info->bl_mutex);
+ pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
level = pmu_backlight_data.max_brightness;
@@ -123,18 +162,16 @@ void __init pmu_backlight_init(struct device_node *in_vias)
pmu_request(&req, NULL, 2, 0xd9, 0);
pmu_wait_complete(&req);
- mutex_lock(&info->bl_mutex);
- level = pmac_backlight_curve_lookup(info,
+ level = pmu_backlight_curve_lookup(
(req.reply[0] >> 4) *
pmu_backlight_data.max_brightness / 15);
- mutex_unlock(&info->bl_mutex);
}
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = level;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
mutex_lock(&pmac_backlight_mutex);
if (!pmac_backlight)
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index af8375ed0f5e..5189d5454b1f 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
static struct led_classdev pmu_led = {
.name = "pmu-front-led",
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
+#ifdef CONFIG_ADB_PMU_LED_IDE
.default_trigger = "ide-disk",
#endif
.brightness_set = pmu_led_set,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 06ca80bfd6b9..14610a63f580 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -16,7 +16,6 @@
* a sleep or a freq. switch
* - Move sleep code out of here to pmac_pm, merge into new
* common PM infrastructure
- * - Move backlight code out as well
* - Save/Restore PCI space properly
*
*/
@@ -60,9 +59,7 @@
#include
#include
#include
-#ifdef CONFIG_PMAC_BACKLIGHT
#include
-#endif
#include "via-pmu-event.h"
@@ -177,10 +174,6 @@ static int query_batt_timer = BATTERY_POLLING_COUNT;
static struct adb_request batt_req;
static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
-#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
-extern int disable_kernel_backlight;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
-
int __fake_sleep;
int asleep;
BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
@@ -466,7 +459,7 @@ static int __init via_pmu_dev_init(void)
#ifdef CONFIG_PMAC_BACKLIGHT
/* Initialize backlight */
- pmu_backlight_init(vias);
+ pmu_backlight_init();
#endif
#ifdef CONFIG_PPC32
@@ -1403,11 +1396,8 @@ next:
else if ((1 << pirq) & PMU_INT_SNDBRT) {
#ifdef CONFIG_PMAC_BACKLIGHT
if (len == 3)
-#ifdef CONFIG_INPUT_ADBHID
- if (!disable_kernel_backlight)
-#endif /* CONFIG_INPUT_ADBHID */
- pmac_backlight_set_legacy_brightness(data[1] >> 4);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4);
+#endif
}
/* Tick interrupt */
else if ((1 << pirq) & PMU_INT_TICK) {
@@ -2005,6 +1995,8 @@ restore_via_state(void)
out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
}
+extern void pmu_backlight_set_sleep(int sleep);
+
static int
pmac_suspend_devices(void)
{
@@ -2042,6 +2034,11 @@ pmac_suspend_devices(void)
return -EBUSY;
}
+#ifdef CONFIG_PMAC_BACKLIGHT
+ /* Tell backlight code not to muck around with the chip anymore */
+ pmu_backlight_set_sleep(1);
+#endif
+
/* Call platform functions marked "on sleep" */
pmac_pfunc_i2c_suspend();
pmac_pfunc_base_suspend();
@@ -2100,6 +2097,11 @@ pmac_wakeup_devices(void)
{
mdelay(100);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ /* Tell backlight code it can use the chip again */
+ pmu_backlight_set_sleep(0);
+#endif
+
/* Power back up system devices (including the PIC) */
device_power_up();
@@ -2414,7 +2416,7 @@ struct pmu_private {
spinlock_t lock;
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
int backlight_locker;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+#endif
};
static LIST_HEAD(all_pmu_pvt);
@@ -2464,7 +2466,7 @@ pmu_open(struct inode *inode, struct file *file)
spin_lock_irqsave(&all_pvt_lock, flags);
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
pp->backlight_locker = 0;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+#endif
list_add(&pp->list, &all_pmu_pvt);
spin_unlock_irqrestore(&all_pvt_lock, flags);
file->private_data = pp;
@@ -2559,13 +2561,12 @@ pmu_release(struct inode *inode, struct file *file)
spin_lock_irqsave(&all_pvt_lock, flags);
list_del(&pp->list);
spin_unlock_irqrestore(&all_pvt_lock, flags);
+
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
- if (pp->backlight_locker) {
- spin_lock_irqsave(&pmu_lock, flags);
- disable_kernel_backlight--;
- spin_unlock_irqrestore(&pmu_lock, flags);
- }
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+ if (pp->backlight_locker)
+ pmac_backlight_enable();
+#endif
+
kfree(pp);
}
unlock_kernel();
@@ -2642,18 +2643,18 @@ pmu_ioctl(struct inode * inode, struct file *filp,
#ifdef CONFIG_INPUT_ADBHID
case PMU_IOC_GRAB_BACKLIGHT: {
struct pmu_private *pp = filp->private_data;
- unsigned long flags;
if (pp->backlight_locker)
return 0;
+
pp->backlight_locker = 1;
- spin_lock_irqsave(&pmu_lock, flags);
- disable_kernel_backlight++;
- spin_unlock_irqrestore(&pmu_lock, flags);
+ pmac_backlight_disable();
+
return 0;
}
#endif /* CONFIG_INPUT_ADBHID */
#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
+
case PMU_IOC_GET_MODEL:
return put_user(pmu_kind, argp);
case PMU_IOC_HAS_ADB:
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 217615b33223..93f701ea87bc 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -710,6 +710,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
return -EINVAL;
}
+ m->ti = ti;
+
r = parse_features(&as, m, ti);
if (r)
goto bad;
@@ -751,7 +753,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
}
ti->private = m;
- m->ti = ti;
return 0;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index be48cedf986b..c54de989eb00 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -255,7 +255,9 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region)
struct region *reg, *nreg;
read_unlock(&rh->hash_lock);
- nreg = mempool_alloc(rh->region_pool, GFP_NOIO);
+ nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
+ if (unlikely(!nreg))
+ nreg = kmalloc(sizeof(struct region), GFP_NOIO);
nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
RH_CLEAN : RH_NOSYNC;
nreg->rh = rh;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ff83c9b5979e..b99c19c7eb22 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -162,7 +162,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
goto out;
}
- min_spacing = mddev->array_size;
+ min_spacing = conf->array_size;
sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
/* min_spacing is the minimum spacing that will fit the hash
@@ -171,7 +171,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
* that is larger than min_spacing as use the size of that as
* the actual spacing
*/
- conf->hash_spacing = mddev->array_size;
+ conf->hash_spacing = conf->array_size;
for (i=0; i < cnt-1 ; i++) {
sector_t sz = 0;
int j;
@@ -228,7 +228,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
curr_offset = 0;
i = 0;
for (curr_offset = 0;
- curr_offset < mddev->array_size;
+ curr_offset < conf->array_size;
curr_offset += conf->hash_spacing) {
while (i < mddev->raid_disks-1 &&
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b6d16022a53e..8dbab2ef3885 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1597,6 +1597,19 @@ void md_update_sb(mddev_t * mddev)
repeat:
spin_lock_irq(&mddev->write_lock);
+
+ if (mddev->degraded && mddev->sb_dirty == 3)
+ /* If the array is degraded, then skipping spares is both
+ * dangerous and fairly pointless.
+ * Dangerous because a device that was removed from the array
+ * might have a event_count that still looks up-to-date,
+ * so it can be re-added without a resync.
+ * Pointless because if there are any spares to skip,
+ * then a recovery will happen and soon that array won't
+ * be degraded any more and the spare can go back to sleep then.
+ */
+ mddev->sb_dirty = 1;
+
sync_req = mddev->in_sync;
mddev->utime = get_seconds();
if (mddev->sb_dirty == 3)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1efe22a2d041..3b4d69c05623 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -930,10 +930,13 @@ static void status(struct seq_file *seq, mddev_t *mddev)
seq_printf(seq, " [%d/%d] [", conf->raid_disks,
conf->working_disks);
- for (i = 0; i < conf->raid_disks; i++)
+ rcu_read_lock();
+ for (i = 0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
seq_printf(seq, "%s",
- conf->mirrors[i].rdev &&
- test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_");
+ rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
+ }
+ rcu_read_unlock();
seq_printf(seq, "]");
}
@@ -975,7 +978,6 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
static void print_conf(conf_t *conf)
{
int i;
- mirror_info_t *tmp;
printk("RAID1 conf printout:\n");
if (!conf) {
@@ -985,14 +987,17 @@ static void print_conf(conf_t *conf)
printk(" --- wd:%d rd:%d\n", conf->working_disks,
conf->raid_disks);
+ rcu_read_lock();
for (i = 0; i < conf->raid_disks; i++) {
char b[BDEVNAME_SIZE];
- tmp = conf->mirrors + i;
- if (tmp->rdev)
+ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (rdev)
printk(" disk %d, wo:%d, o:%d, dev:%s\n",
- i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags),
- bdevname(tmp->rdev->bdev,b));
+ i, !test_bit(In_sync, &rdev->flags),
+ !test_bit(Faulty, &rdev->flags),
+ bdevname(rdev->bdev,b));
}
+ rcu_read_unlock();
}
static void close_sync(conf_t *conf)
@@ -1008,20 +1013,20 @@ static int raid1_spare_active(mddev_t *mddev)
{
int i;
conf_t *conf = mddev->private;
- mirror_info_t *tmp;
/*
* Find all failed disks within the RAID1 configuration
- * and mark them readable
+ * and mark them readable.
+ * Called under mddev lock, so rcu protection not needed.
*/
for (i = 0; i < conf->raid_disks; i++) {
- tmp = conf->mirrors + i;
- if (tmp->rdev
- && !test_bit(Faulty, &tmp->rdev->flags)
- && !test_bit(In_sync, &tmp->rdev->flags)) {
+ mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+ if (rdev
+ && !test_bit(Faulty, &rdev->flags)
+ && !test_bit(In_sync, &rdev->flags)) {
conf->working_disks++;
mddev->degraded--;
- set_bit(In_sync, &tmp->rdev->flags);
+ set_bit(In_sync, &rdev->flags);
}
}
@@ -1237,7 +1242,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
/* ouch - failed to read all of that.
* Try some synchronous reads of other devices to get
* good data, much like with normal read errors. Only
- * read into the pages we already have so they we don't
+ * read into the pages we already have so we don't
* need to re-issue the read request.
* We don't need to freeze the array, because being in an
* active sync request, there is no normal IO, and
@@ -1257,6 +1262,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
s = PAGE_SIZE >> 9;
do {
if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+ /* No rcu protection needed here devices
+ * can only be removed when no resync is
+ * active, and resync is currently active
+ */
rdev = conf->mirrors[d].rdev;
if (sync_page_io(rdev->bdev,
sect + rdev->data_offset,
@@ -1463,6 +1472,11 @@ static void raid1d(mddev_t *mddev)
s = PAGE_SIZE >> 9;
do {
+ /* Note: no rcu protection needed here
+ * as this is synchronous in the raid1d thread
+ * which is the thread that might remove
+ * a device. If raid1d ever becomes multi-threaded....
+ */
rdev = conf->mirrors[d].rdev;
if (rdev &&
test_bit(In_sync, &rdev->flags) &&
@@ -1486,7 +1500,6 @@ static void raid1d(mddev_t *mddev)
d = conf->raid_disks;
d--;
rdev = conf->mirrors[d].rdev;
- atomic_add(s, &rdev->corrected_errors);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
if (sync_page_io(rdev->bdev,
@@ -1509,9 +1522,11 @@ static void raid1d(mddev_t *mddev)
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
- else
+ else {
+ atomic_add(s, &rdev->corrected_errors);
printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b));
+ }
}
}
} else {
@@ -1625,15 +1640,16 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
- /* before building a request, check if we can skip these blocks..
- * This call the bitmap_start_sync doesn't actually record anything
- */
if (mddev->bitmap == NULL &&
mddev->recovery_cp == MaxSector &&
+ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
conf->fullsync == 0) {
*skipped = 1;
return max_sector - sector_nr;
}
+ /* before building a request, check if we can skip these blocks..
+ * This call the bitmap_start_sync doesn't actually record anything
+ */
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* We can skip this block, and probably several more */
@@ -1786,19 +1802,17 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0; iraid_disks; i++) {
bio = r1_bio->bios[i];
if (bio->bi_end_io == end_sync_read) {
- md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+ md_sync_acct(bio->bi_bdev, nr_sectors);
generic_make_request(bio);
}
}
} else {
atomic_set(&r1_bio->remaining, 1);
bio = r1_bio->bios[r1_bio->read_disk];
- md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
- nr_sectors);
+ md_sync_acct(bio->bi_bdev, nr_sectors);
generic_make_request(bio);
}
-
return nr_sectors;
}
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index d687a14ec0a7..06ac899a9a26 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -393,7 +393,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
state->bandwidth = bandwidth;
if (state->dst_type != DST_TYPE_IS_TERR)
- return 0;
+ return -EOPNOTSUPP;
switch (bandwidth) {
case BANDWIDTH_6_MHZ:
@@ -462,7 +462,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
state->symbol_rate = srate;
if (state->dst_type == DST_TYPE_IS_TERR) {
- return 0;
+ return -EOPNOTSUPP;
}
dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
srate /= 1000;
@@ -504,7 +504,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
{
if (state->dst_type != DST_TYPE_IS_CABLE)
- return 0;
+ return -EOPNOTSUPP;
state->modulation = modulation;
switch (modulation) {
@@ -1234,7 +1234,7 @@ int dst_command(struct dst_state *state, u8 *data, u8 len)
goto error;
}
if (write_dst(state, data, len)) {
- dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
+ dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
goto error;
@@ -1328,15 +1328,13 @@ static int dst_tone_power_cmd(struct dst_state *state)
{
u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
- if (state->dst_type == DST_TYPE_IS_TERR)
- return 0;
+ if (state->dst_type != DST_TYPE_IS_SAT)
+ return -EOPNOTSUPP;
paket[4] = state->tx_tuna[4];
paket[2] = state->tx_tuna[2];
paket[3] = state->tx_tuna[3];
paket[7] = dst_check_sum (paket, 7);
- dst_command(state, paket, 8);
-
- return 0;
+ return dst_command(state, paket, 8);
}
static int dst_get_tuna(struct dst_state *state)
@@ -1465,7 +1463,7 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
if (state->dst_type != DST_TYPE_IS_SAT)
- return 0;
+ return -EOPNOTSUPP;
if (cmd->msg_len > 0 && cmd->msg_len < 5)
memcpy(&paket[3], cmd->msg, cmd->msg_len);
else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
@@ -1473,18 +1471,17 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
else
return -EINVAL;
paket[7] = dst_check_sum(&paket[0], 7);
- dst_command(state, paket, 8);
- return 0;
+ return dst_command(state, paket, 8);
}
static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
- int need_cmd;
+ int need_cmd, retval = 0;
struct dst_state *state = fe->demodulator_priv;
state->voltage = voltage;
if (state->dst_type != DST_TYPE_IS_SAT)
- return 0;
+ return -EOPNOTSUPP;
need_cmd = 0;
@@ -1506,9 +1503,9 @@ static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
}
if (need_cmd)
- dst_tone_power_cmd(state);
+ retval = dst_tone_power_cmd(state);
- return 0;
+ return retval;
}
static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
@@ -1517,7 +1514,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
state->tone = tone;
if (state->dst_type != DST_TYPE_IS_SAT)
- return 0;
+ return -EOPNOTSUPP;
switch (tone) {
case SEC_TONE_OFF:
@@ -1533,9 +1530,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
default:
return -EINVAL;
}
- dst_tone_power_cmd(state);
-
- return 0;
+ return dst_tone_power_cmd(state);
}
static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
@@ -1543,7 +1538,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
struct dst_state *state = fe->demodulator_priv;
if (state->dst_type != DST_TYPE_IS_SAT)
- return 0;
+ return -EOPNOTSUPP;
state->minicmd = minicmd;
switch (minicmd) {
case SEC_MINI_A:
@@ -1553,9 +1548,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
state->tx_tuna[3] = 0xff;
break;
}
- dst_tone_power_cmd(state);
-
- return 0;
+ return dst_tone_power_cmd(state);
}
@@ -1608,28 +1601,31 @@ static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct dst_state *state = fe->demodulator_priv;
- dst_get_signal(state);
+ int retval = dst_get_signal(state);
*strength = state->decode_strength;
- return 0;
+ return retval;
}
static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct dst_state *state = fe->demodulator_priv;
- dst_get_signal(state);
+ int retval = dst_get_signal(state);
*snr = state->decode_snr;
- return 0;
+ return retval;
}
static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
+ int retval = -EINVAL;
struct dst_state *state = fe->demodulator_priv;
if (p != NULL) {
- dst_set_freq(state, p->frequency);
+ retval = dst_set_freq(state, p->frequency);
+ if(retval != 0)
+ return retval;
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1647,10 +1643,10 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
dst_set_symbolrate(state, p->u.qam.symbol_rate);
dst_set_modulation(state, p->u.qam.modulation);
}
- dst_write_tuna(fe);
+ retval = dst_write_tuna(fe);
}
- return 0;
+ return retval;
}
static int dst_tune_frontend(struct dvb_frontend* fe,
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index 11054657fdb5..0b5182835cc8 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -2,8 +2,8 @@
# Makefile for the kernel DVB device drivers.
#
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_frontend.o \
- dvb_net.o dvb_ringbuffer.o dvb_math.o
+dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
+ dvb_ca_en50221.o dvb_frontend.o \
+ dvb_net.o dvb_ringbuffer.o dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 59ac35ddd51e..57b34cda99f5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -526,7 +526,9 @@ static int dvb_frontend_thread(void *data)
fepriv->delay = 3*HZ;
fepriv->status = 0;
fepriv->wakeup = 0;
- fepriv->reinitialise = 1;
+ fepriv->reinitialise = 0;
+
+ dvb_frontend_init(fe);
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
@@ -1013,17 +1015,18 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
return ret;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+
+ /* normal tune mode when opened R/W */
+ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+ fepriv->tone = -1;
+ fepriv->voltage = -1;
+
ret = dvb_frontend_start (fe);
if (ret)
dvb_generic_release (inode, file);
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
-
- /* normal tune mode when opened R/W */
- fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
- fepriv->tone = -1;
- fepriv->voltage = -1;
}
return ret;
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index a189683454b7..2be33f27c69f 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -194,11 +194,11 @@ struct dvb_pll_desc dvb_pll_tda665x = {
{ 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ },
{ 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ },
{ 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
- { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
- { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ },
- { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ },
- { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
- { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ },
+ { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ },
+ { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ },
+ { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ },
+ { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ },
+ { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ },
}
};
EXPORT_SYMBOL(dvb_pll_tda665x);
@@ -613,7 +613,21 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
{
+ u8 b1 [] = { 0 };
+ struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL;
+ int ret;
+
+ if (i2c != NULL) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = i2c_transfer (i2c, &msg, 1);
+ if (ret != 1)
+ return -1;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
if (priv == NULL)
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 500f15c10aaf..4506165c5de2 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2203,8 +2203,8 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
/* set TDA9819 into DVB mode */
- saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
/* tuner on this needs a slower i2c bus speed */
av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 64055461559d..6ffe53fdcf57 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -272,8 +272,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
}
if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
@@ -308,8 +308,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
}
}
@@ -750,8 +750,8 @@ int av7110_init_analog_module(struct av7110 *av7110)
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
}
/* init the saa7113 */
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 5f111d407730..2d21fec23b4d 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1303,6 +1303,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
budget_av->budget.dvb_adapter.priv = budget_av;
frontend_init(budget_av);
ciintf_init(budget_av);
+
+ ttpci_budget_init_hooks(&budget_av->budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 4b966eea3834..ffbbb3e34be4 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1101,6 +1101,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
budget_ci->budget.dvb_adapter.priv = budget_ci;
frontend_init(budget_ci);
+ ttpci_budget_init_hooks(&budget_ci->budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index e4cf7775e07f..e15562f81664 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -63,9 +63,6 @@ static int stop_ts_capture(struct budget *budget)
{
dprintk(2, "budget: %p\n", budget);
- if (--budget->feeding)
- return budget->feeding;
-
saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
SAA7146_IER_DISABLE(budget->dev, MASK_10);
return 0;
@@ -77,8 +74,8 @@ static int start_ts_capture(struct budget *budget)
dprintk(2, "budget: %p\n", budget);
- if (budget->feeding)
- return ++budget->feeding;
+ if (!budget->feeding || !budget->fe_synced)
+ return 0;
saa7146_write(dev, MC1, MASK_20); // DMA3 off
@@ -139,7 +136,33 @@ static int start_ts_capture(struct budget *budget)
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
- return ++budget->feeding;
+ return 0;
+}
+
+static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct budget *budget = (struct budget *) fe->dvb->priv;
+ int synced;
+ int ret;
+
+ if (budget->read_fe_status)
+ ret = budget->read_fe_status(fe, status);
+ else
+ ret = -EINVAL;
+
+ if (!ret) {
+ synced = (*status & FE_HAS_LOCK);
+ if (synced != budget->fe_synced) {
+ budget->fe_synced = synced;
+ spin_lock(&budget->feedlock);
+ if (synced)
+ start_ts_capture(budget);
+ else
+ stop_ts_capture(budget);
+ spin_unlock(&budget->feedlock);
+ }
+ }
+ return ret;
}
static void vpeirq(unsigned long data)
@@ -267,7 +290,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct budget *budget = (struct budget *) demux->priv;
- int status;
+ int status = 0;
dprintk(2, "budget: %p\n", budget);
@@ -276,7 +299,8 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
spin_lock(&budget->feedlock);
feed->pusi_seen = 0; /* have a clean section start */
- status = start_ts_capture(budget);
+ if (budget->feeding++ == 0)
+ status = start_ts_capture(budget);
spin_unlock(&budget->feedlock);
return status;
}
@@ -285,12 +309,13 @@ static int budget_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct budget *budget = (struct budget *) demux->priv;
- int status;
+ int status = 0;
dprintk(2, "budget: %p\n", budget);
spin_lock(&budget->feedlock);
- status = stop_ts_capture(budget);
+ if (--budget->feeding == 0)
+ status = stop_ts_capture(budget);
spin_unlock(&budget->feedlock);
return status;
}
@@ -470,6 +495,14 @@ err:
return ret;
}
+void ttpci_budget_init_hooks(struct budget *budget)
+{
+ if (budget->dvb_frontend && !budget->read_fe_status) {
+ budget->read_fe_status = budget->dvb_frontend->ops.read_status;
+ budget->dvb_frontend->ops.read_status = budget_read_fe_status;
+ }
+}
+
int ttpci_budget_deinit(struct budget *budget)
{
struct saa7146_dev *dev = budget->dev;
@@ -508,11 +541,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
spin_lock(&budget->feedlock);
budget->video_port = video_port;
if (budget->feeding) {
- int oldfeeding = budget->feeding;
- budget->feeding = 1;
stop_ts_capture(budget);
start_ts_capture(budget);
- budget->feeding = oldfeeding;
}
spin_unlock(&budget->feedlock);
}
@@ -520,6 +550,7 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
EXPORT_SYMBOL_GPL(ttpci_budget_init);
+EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index ee60ce90a400..57227441891e 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -617,6 +617,8 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
budget->dvb_adapter.priv = budget;
frontend_init(budget);
+ ttpci_budget_init_hooks(budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 35761f13c12b..863dffb4ed8e 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -375,9 +375,6 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
break;
@@ -474,6 +471,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
budget->dvb_adapter.priv = budget;
frontend_init(budget);
+ ttpci_budget_init_hooks(budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index ecea3a13030e..e8a5c79178e1 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -52,9 +52,6 @@ struct budget {
struct dmx_frontend hw_frontend;
struct dmx_frontend mem_frontend;
- int fe_synced;
- struct mutex pid_mutex;
-
int ci_present;
int video_port;
@@ -74,6 +71,9 @@ struct budget {
struct dvb_adapter dvb_adapter;
struct dvb_frontend *dvb_frontend;
+ int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+ int fe_synced;
+
void *priv;
};
@@ -106,6 +106,7 @@ static struct saa7146_pci_extension_data x_var = { \
extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner);
+extern void ttpci_budget_init_hooks(struct budget *budget);
extern int ttpci_budget_deinit(struct budget *budget);
extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index de3128a31de8..220076b1b956 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -350,5 +350,15 @@ config RADIO_ZOLTRIX_PORT
help
Enter the I/O port of your Zoltrix radio card.
-endmenu
+config USB_DSBR
+ tristate "D-Link USB FM radio support (EXPERIMENTAL)"
+ depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+ To compile this driver as a module, choose M here: the
+ module will be called dsbr100.
+endmenu
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index e95b6805e002..cf55a18e3ddf 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
+obj-$(CONFIG_USB_DSBR) += dsbr100.o
EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/video/dsbr100.c b/drivers/media/radio/dsbr100.c
similarity index 100%
rename from drivers/media/video/dsbr100.c
rename to drivers/media/radio/dsbr100.c
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6d532f170ce5..732bf1e7c326 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -145,7 +145,7 @@ config VIDEO_SAA5246A
config VIDEO_SAA5249
tristate "SAA5249 Teletext processor"
- depends on VIDEO_DEV && I2C
+ depends on VIDEO_DEV && I2C && VIDEO_V4L1
help
Support for I2C bus based teletext using the SAA5249 chip. At the
moment this is only useful on some European WinTV cards.
@@ -155,7 +155,7 @@ config VIDEO_SAA5249
config TUNER_3036
tristate "SAB3036 tuner"
- depends on VIDEO_DEV && I2C
+ depends on VIDEO_DEV && I2C && VIDEO_V4L1
help
Say Y here to include support for Philips SAB3036 compatible tuners.
If in doubt, say N.
@@ -449,18 +449,6 @@ source "drivers/media/video/pvrusb2/Kconfig"
source "drivers/media/video/em28xx/Kconfig"
-config USB_DSBR
- tristate "D-Link USB FM radio support (EXPERIMENTAL)"
- depends on USB && VIDEO_V4L1 && EXPERIMENTAL
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- To compile this driver as a module, choose M here: the
- module will be called dsbr100.
-
source "drivers/media/video/usbvideo/Kconfig"
source "drivers/media/video/et61x251/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 353d61cfac1b..e82e511f2a72 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -77,7 +77,6 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
-obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_STV680) += stv680.o
@@ -91,6 +90,7 @@ obj-$(CONFIG_USB_ZC0301) += zc0301/
obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
+obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 153f6a4a96c9..cdcf55650714 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+ depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 5764a89d3562..20dff7c316eb 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3923,7 +3923,12 @@ static int __devinit bttv_register_video(struct bttv *btv)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->c.nr,btv->video_dev->minor & 0x1f);
- video_device_create_file(btv->video_dev, &class_device_attr_card);
+ if (class_device_create_file(&btv->video_dev->class_dev,
+ &class_device_attr_card)<0) {
+ printk(KERN_ERR "bttv%d: class_device_create_file 'card' "
+ "failed\n", btv->c.nr);
+ goto err;
+ }
/* vbi */
btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
@@ -4287,6 +4292,8 @@ static struct pci_driver bttv_pci_driver = {
static int bttv_init_module(void)
{
+ int ret;
+
bttv_num = 0;
printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
@@ -4308,7 +4315,11 @@ static int bttv_init_module(void)
bttv_check_chipset();
- bus_register(&bttv_sub_bus_type);
+ ret = bus_register(&bttv_sub_bus_type);
+ if (ret < 0) {
+ printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+ return ret;
+ }
return pci_register_driver(&bttv_pci_driver);
}
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 8c9f0f7cf467..63676e7bd635 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -31,11 +31,16 @@
#include
#include "bttvp.h"
-/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
- bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
- HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
- of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
-#define VBI_OFFSET ((64 + 0) * 2)
+/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
+ in fCLKx2 pixels. According to the datasheet, VBI capture starts
+ VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
+ is 64 fCLKx1 pixels wide. VBI_HDELAY is set to 0, so this should be
+ (64 + 0) * 2 = 128 fCLKx2 pixels. But it's not! The datasheet is
+ Just Plain Wrong. The real value appears to be different for
+ different revisions of the bt8x8 chips, and to be affected by the
+ horizontal scaling factor. Experimentally, the value is measured
+ to be about 244. */
+#define VBI_OFFSET 244
#define VBI_DEFLINES 16
#define VBI_MAXLINES 32
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 353d02b67c33..b69ee1194815 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -21,7 +21,7 @@
#ifdef CONFIG_COMPAT
-
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
struct video_tuner32 {
compat_int_t tuner;
char name[32];
@@ -107,6 +107,7 @@ struct video_window32 {
compat_caddr_t clips;
compat_int_t clipcount;
};
+#endif
static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
@@ -124,6 +125,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* You get back everything except the clips... */
static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
{
@@ -138,6 +140,7 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
return -EFAULT;
return 0;
}
+#endif
struct v4l2_clip32
{
@@ -490,6 +493,24 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
return 0;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+struct video_code32
+{
+ char loadwhat[16]; /* name or tag of file being passed */
+ compat_int_t datasize;
+ unsigned char *data;
+};
+
+static inline int microcode32(struct video_code *kp, struct video_code32 __user *up)
+{
+ if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
+ copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) ||
+ get_user(kp->datasize, &up->datasize) ||
+ copy_from_user(kp->data, up->data, up->datasize))
+ return -EFAULT;
+ return 0;
+}
+
#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
@@ -498,6 +519,9 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
#define VIDIOCGFREQ32 _IOR('v',14, u32)
#define VIDIOCSFREQ32 _IOW('v',15, u32)
+#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32)
+
+#endif
/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
@@ -519,6 +543,7 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t)
#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32)
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
enum {
MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
};
@@ -583,13 +608,17 @@ static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
}
+#endif
static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
union {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
struct video_tuner vt;
struct video_buffer vb;
struct video_window vw;
+ struct video_code vc;
+#endif
struct v4l2_format v2f;
struct v4l2_buffer v2b;
struct v4l2_framebuffer v2fb;
@@ -605,6 +634,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
/* First, convert the command. */
switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
@@ -612,6 +642,8 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+ case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
+#endif
case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
@@ -631,6 +663,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
};
switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCSTUNER:
case VIDIOCGTUNER:
err = get_video_tuner32(&karg.vt, up);
@@ -644,6 +677,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
break;
case VIDIOCSFREQ:
+#endif
case VIDIOC_S_INPUT:
case VIDIOC_OVERLAY:
case VIDIOC_STREAMON:
@@ -697,14 +731,21 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
compatible_arg = 0;
break;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGWIN:
case VIDIOCGFBUF:
case VIDIOCGFREQ:
+#endif
case VIDIOC_G_FBUF:
case VIDIOC_G_INPUT:
compatible_arg = 0;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ case VIDIOCSMICROCODE:
+ err = microcode32(&karg.vc, up);
+ compatible_arg = 0;
+ break;
+#endif
};
-
if(err)
goto out;
@@ -719,6 +760,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
}
if(err == 0) {
switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGTUNER:
err = put_video_tuner32(&karg.vt, up);
break;
@@ -730,7 +772,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case VIDIOCGFBUF:
err = put_video_buffer32(&karg.vb, up);
break;
-
+#endif
case VIDIOC_G_FBUF:
err = put_v4l2_framebuffer32(&karg.v2fb, up);
break;
@@ -768,7 +810,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
err = put_v4l2_input32(&karg.v2i, up);
break;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGFREQ:
+#endif
case VIDIOC_G_INPUT:
err = put_user(((u32)karg.vx), (u32 __user *)up);
break;
@@ -786,6 +830,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
return ret;
switch (cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCSWIN32:
ret = do_set_window(file, cmd, arg);
break;
@@ -796,6 +841,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOCSFBUF32:
case VIDIOCGFREQ32:
case VIDIOCSFREQ32:
+#endif
case VIDIOC_QUERYCAP:
case VIDIOC_ENUM_FMT:
case VIDIOC_G_FMT32:
@@ -827,6 +873,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
ret = do_video_ioctl(file, cmd, arg);
break;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* Little v, the video4linux ioctls (conflict?) */
case VIDIOCGCAP:
case VIDIOCGCHAN:
@@ -855,6 +902,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
break;
+#endif
default:
v4l_print_ioctl("compat_ioctl32", cmd);
}
diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig
index 513cc0927389..e39a96152004 100644
--- a/drivers/media/video/cpia2/Kconfig
+++ b/drivers/media/video/cpia2/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_CPIA2
tristate "CPiA2 Video For Linux"
- depends on VIDEO_DEV && USB
+ depends on VIDEO_DEV && USB && VIDEO_V4L1
---help---
This is the video4linux driver for cameras based on Vision's CPiA2
(Colour Processor Interface ASIC), such as the Digital Blue QX5
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 5c2036b40ea1..7bb7589a07c3 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -104,8 +104,8 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr)
if (i2c_master_recv(client, buffer, 4) < 4)
return 0;
- return (buffer[0] << 24) | (buffer[1] << 16) |
- (buffer[2] << 8) | buffer[3];
+ return (buffer[3] << 24) | (buffer[2] << 16) |
+ (buffer[1] << 8) | buffer[0];
}
int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 72b630a91f41..c25564648993 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -89,7 +89,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
auxgpio = cx_read(MO_GP1_IO);
/* Take out the parity part */
- gpio+=(gpio & 0x7fd) + (auxgpio & 0xef);
+ gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
} else
auxgpio = gpio;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 2225d4b94140..94c92bacc342 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1180,7 +1180,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_VIDEO_OVERLAY |
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
@@ -1226,7 +1225,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_format *f = arg;
return cx8800_try_fmt(dev,fh,f);
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* --- streaming capture ------------------------------------- */
case VIDIOCGMBUF:
{
@@ -1585,7 +1584,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
*id = 0;
return 0;
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCSTUNER:
{
struct video_tuner *v = arg;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index dbb75a7db199..56246b8578f3 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -362,7 +362,7 @@ int msp_sleep(struct msp_state *state, int timeout)
}
/* ------------------------------------------------------------------------ */
-
+#ifdef CONFIG_VIDEO_V4L1
static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
{
if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -384,6 +384,7 @@ static int msp_mode_v4l1_to_v4l2(int mode)
return V4L2_TUNER_MODE_LANG1;
return V4L2_TUNER_MODE_MONO;
}
+#endif
static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
{
@@ -509,6 +510,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
kernel pointer here... */
+#ifdef CONFIG_VIDEO_V4L1
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
@@ -577,6 +579,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
case VIDIOCSFREQ:
+ {
+ /* new channel -- kick audio carrier scan */
+ msp_wake_thread(client);
+ break;
+ }
+#endif
case VIDIOC_S_FREQUENCY:
{
/* new channel -- kick audio carrier scan */
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index f2fd9195b3ac..ed02ff811388 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -961,10 +961,10 @@ int msp34xxg_thread(void *data)
/* setup the chip*/
msp34xxg_reset(client);
state->std = state->radio ? 0x40 : msp_standard;
- if (state->std != 1)
- goto unmute;
/* start autodetect */
msp_write_dem(client, 0x20, state->std);
+ if (state->std != 1)
+ goto unmute;
/* watch autodetect */
v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 9b48abcf6089..be1e5cc78081 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -852,7 +852,6 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
return hdw->serial_number;
}
-
int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
{
return hdw->unit_number;
@@ -2318,7 +2317,6 @@ void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
}
}
-
/* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
{
@@ -2542,6 +2540,10 @@ static void pvr2_ctl_timeout(unsigned long data)
}
+/* Issue a command and get a response from the device. This extended
+ version includes a probe flag (which if set means that device errors
+ should not be logged or treated as fatal) and a timeout in jiffies.
+ This can be used to non-lethally probe the health of endpoint 1. */
static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
unsigned int timeout,int probe_fl,
void *write_data,unsigned int write_len,
@@ -2970,6 +2972,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
}
+/* Stop / start video stream transport */
static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
{
int status;
@@ -3068,6 +3071,7 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
}
+/* Find I2C address of eeprom */
static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
{
int result;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 681f79c8064e..1e393762546c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -26,6 +26,8 @@
#include
#include
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
#define BUFFER_SIG 0x47653271
// #define SANITY_CHECK_BUFFERS
@@ -515,6 +517,10 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
}
/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+ return sp->buffer_target_count;
+}
int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
{
@@ -553,7 +559,6 @@ int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
return sp->r_count;
}
-
void pvr2_stream_kill(struct pvr2_stream *sp)
{
struct pvr2_buffer *bp;
@@ -607,7 +612,6 @@ int pvr2_buffer_queue(struct pvr2_buffer *bp)
return ret;
}
-
int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
{
int ret = 0;
@@ -646,7 +650,6 @@ int pvr2_buffer_get_status(struct pvr2_buffer *bp)
return bp->status;
}
-
int pvr2_buffer_get_id(struct pvr2_buffer *bp)
{
return bp->id;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
index 96285ad234a6..93279cc2a35e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -47,6 +47,7 @@ void pvr2_stream_set_callback(struct pvr2_stream *,
void *data);
/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
/* Get a pointer to a buffer that is either idle, ready, or is specified
@@ -58,6 +59,7 @@ struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
/* Find out how many buffers are idle or ready */
int pvr2_stream_get_ready_count(struct pvr2_stream *);
+
/* Kill all pending buffers and throw away any ready buffers as well */
void pvr2_stream_kill(struct pvr2_stream *);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index f7a2e225a002..b71f9a961f8a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -213,7 +213,9 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
" pvr2_ioread_setup (tear-down) id=%p",cp);
pvr2_ioread_stop(cp);
pvr2_stream_kill(cp->stream);
- pvr2_stream_set_buffer_count(cp->stream,0);
+ if (pvr2_stream_get_buffer_count(cp->stream)) {
+ pvr2_stream_set_buffer_count(cp->stream,0);
+ }
cp->stream = NULL;
}
if (sp) {
@@ -251,7 +253,6 @@ int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
return ret;
}
-
static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
{
int stat;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 6af55a8b6f05..d1dda5caf406 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -44,12 +44,16 @@ struct pvr2_sysfs {
struct kobj_type ktype;
struct class_device_attribute attr_v4l_minor_number;
struct class_device_attribute attr_unit_number;
+ int v4l_minor_number_created_ok;
+ int unit_number_created_ok;
};
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
struct pvr2_sysfs_debugifc {
struct class_device_attribute attr_debugcmd;
struct class_device_attribute attr_debuginfo;
+ int debugcmd_created_ok;
+ int debuginfo_created_ok;
};
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
@@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item {
struct pvr2_sysfs_ctl_item *item_next;
struct attribute *attr_gen[7];
struct attribute_group grp;
+ int created_ok;
char name[80];
};
@@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
struct pvr2_sysfs_func_set *fp;
struct pvr2_ctrl *cptr;
unsigned int cnt,acnt;
+ int ret;
if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
return;
@@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->grp.name = cip->name;
cip->grp.attrs = cip->attr_gen;
- sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ if (ret) {
+ printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+ __FUNCTION__, ret);
+ return;
+ }
+ cip->created_ok = !0;
}
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -600,6 +612,8 @@ static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
{
struct pvr2_sysfs_debugifc *dip;
+ int ret;
+
dip = kmalloc(sizeof(*dip),GFP_KERNEL);
if (!dip) return;
memset(dip,0,sizeof(*dip));
@@ -613,17 +627,34 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
dip->attr_debuginfo.attr.mode = S_IRUGO;
dip->attr_debuginfo.show = debuginfo_show;
sfp->debugifc = dip;
- class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
- class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ dip->debugcmd_created_ok = !0;
+ }
+ ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ dip->debuginfo_created_ok = !0;
+ }
}
static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
{
if (!sfp->debugifc) return;
- class_device_remove_file(sfp->class_dev,
- &sfp->debugifc->attr_debuginfo);
- class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+ if (sfp->debugifc->debuginfo_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->debugifc->attr_debuginfo);
+ }
+ if (sfp->debugifc->debugcmd_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->debugifc->attr_debugcmd);
+ }
kfree(sfp->debugifc);
sfp->debugifc = NULL;
}
@@ -645,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
struct pvr2_sysfs_ctl_item *cip1,*cip2;
for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
cip2 = cip1->item_next;
- sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+ if (cip1->created_ok) {
+ sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+ }
pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
kfree(cip1);
}
@@ -675,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
pvr2_sysfs_tear_down_debugifc(sfp);
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
pvr2_sysfs_tear_down_controls(sfp);
- class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
- class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+ if (sfp->v4l_minor_number_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->attr_v4l_minor_number);
+ }
+ if (sfp->unit_number_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->attr_unit_number);
+ }
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
sfp->class_dev->class_data = NULL;
class_device_unregister(sfp->class_dev);
@@ -709,6 +748,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
{
struct usb_device *usb_dev;
struct class_device *class_dev;
+ int ret;
+
usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
if (!usb_dev) return;
class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
@@ -733,20 +774,40 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->class_dev = class_dev;
class_dev->class_data = sfp;
- class_device_register(class_dev);
+ ret = class_device_register(class_dev);
+ if (ret) {
+ printk(KERN_ERR "%s: class_device_register failed\n",
+ __FUNCTION__);
+ kfree(class_dev);
+ return;
+ }
sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
sfp->attr_v4l_minor_number.store = NULL;
- class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+ ret = class_device_create_file(sfp->class_dev,
+ &sfp->attr_v4l_minor_number);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ sfp->v4l_minor_number_created_ok = !0;
+ }
+
sfp->attr_unit_number.attr.owner = THIS_MODULE;
sfp->attr_unit_number.attr.name = "unit_number";
sfp->attr_unit_number.attr.mode = S_IRUGO;
sfp->attr_unit_number.show = unit_number_show;
sfp->attr_unit_number.store = NULL;
- class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ sfp->unit_number_created_ok = !0;
+ }
pvr2_sysfs_add_controls(sfp);
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
index 697145e0bf15..8fdf7101d3bf 100644
--- a/drivers/media/video/pwc/Kconfig
+++ b/drivers/media/video/pwc/Kconfig
@@ -30,7 +30,7 @@ config USB_PWC
config USB_PWC_DEBUG
bool "USB Philips Cameras verbose debug"
- depends USB_PWC
+ depends on USB_PWC
help
Say Y here in order to have the pwc driver generate verbose debugging
messages.
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 47d0d83a0264..d4703944df9c 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -160,6 +160,7 @@ static struct file_operations pwc_fops = {
.poll = pwc_video_poll,
.mmap = pwc_video_mmap,
.ioctl = pwc_video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device pwc_template = {
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index f1fd69e7f119..d73cff1970ae 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -997,9 +997,9 @@ static int saa7134_alsa_init(void)
struct saa7134_dev *dev = NULL;
struct list_head *list;
- if (!dmasound_init && !dmasound_exit) {
- dmasound_init = alsa_device_init;
- dmasound_exit = alsa_device_exit;
+ if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+ saa7134_dmasound_init = alsa_device_init;
+ saa7134_dmasound_exit = alsa_device_exit;
} else {
printk(KERN_WARNING "saa7134 ALSA: can't load, DMA sound handler already assigned (probably to OSS)\n");
return -EBUSY;
@@ -1036,8 +1036,8 @@ static void saa7134_alsa_exit(void)
snd_card_free(snd_saa7134_cards[idx]);
}
- dmasound_init = NULL;
- dmasound_exit = NULL;
+ saa7134_dmasound_init = NULL;
+ saa7134_dmasound_exit = NULL;
printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
return;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 6e97cc84ba89..be3a81fc90a2 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -95,8 +95,8 @@ LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
-int (*dmasound_init)(struct saa7134_dev *dev);
-int (*dmasound_exit)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -1008,8 +1008,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* check for signal */
saa7134_irq_video_intl(dev);
- if (dmasound_init && !dev->dmasound.priv_data) {
- dmasound_init(dev);
+ if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
+ saa7134_dmasound_init(dev);
}
return 0;
@@ -1036,8 +1036,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
struct saa7134_mpeg_ops *mops;
/* Release DMA sound modules if present */
- if (dmasound_exit && dev->dmasound.priv_data) {
- dmasound_exit(dev);
+ if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
+ saa7134_dmasound_exit(dev);
}
/* debugging ... */
@@ -1169,8 +1169,8 @@ EXPORT_SYMBOL(saa7134_boards);
/* ----------------- for the DMA sound modules --------------- */
-EXPORT_SYMBOL(dmasound_init);
-EXPORT_SYMBOL(dmasound_exit);
+EXPORT_SYMBOL(saa7134_dmasound_init);
+EXPORT_SYMBOL(saa7134_dmasound_exit);
EXPORT_SYMBOL(saa7134_pgtable_free);
EXPORT_SYMBOL(saa7134_pgtable_build);
EXPORT_SYMBOL(saa7134_pgtable_alloc);
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 3895d05804ae..2e3ba5f31453 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -993,9 +993,9 @@ static int saa7134_oss_init(void)
struct saa7134_dev *dev = NULL;
struct list_head *list;
- if (!dmasound_init && !dmasound_exit) {
- dmasound_init = oss_device_init;
- dmasound_exit = oss_device_exit;
+ if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+ saa7134_dmasound_init = oss_device_init;
+ saa7134_dmasound_exit = oss_device_exit;
} else {
printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
return -EBUSY;
@@ -1037,8 +1037,8 @@ static void saa7134_oss_exit(void)
}
- dmasound_init = NULL;
- dmasound_exit = NULL;
+ saa7134_dmasound_init = NULL;
+ saa7134_dmasound_exit = NULL;
printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index e4156ec9c6d7..2c171af9a9f2 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -40,7 +40,7 @@
static unsigned int video_debug = 0;
static unsigned int gbuffers = 8;
-static unsigned int noninterlaced = 0;
+static unsigned int noninterlaced = 1;
static unsigned int gbufsize = 720*576*4;
static unsigned int gbufsize_max = 720*576*4;
module_param(video_debug, int, 0644);
@@ -48,7 +48,7 @@ MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
module_param(gbuffers, int, 0444);
MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
module_param(noninterlaced, int, 0644);
-MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
+MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");
#define dprintk(fmt, arg...) if (video_debug) \
printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
@@ -2087,7 +2087,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_format *f = arg;
return saa7134_try_fmt(dev,fh,f);
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index d5ee99c574cc..c04ce6152fd5 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -586,8 +586,8 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
int saa7134_set_dmabits(struct saa7134_dev *dev);
-extern int (*dmasound_init)(struct saa7134_dev *dev);
-extern int (*dmasound_exit)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index b36ba9fa3a28..5686547ba76a 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2181,7 +2181,6 @@ static struct pci_device_id stradis_pci_tbl[] = {
{ 0 }
};
-MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
static struct pci_driver stradis_driver = {
.name = "stradis",
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f7eb402d5f2b..40590bae5ff7 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -196,14 +196,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
i2c_master_send(c, buffer, 4);
default_tuner_init(c);
break;
- case TUNER_LG_TDVS_H06XF:
- /* Set the Auxiliary Byte. */
- buffer[2] &= ~0x20;
- buffer[2] |= 0x18;
- buffer[3] = 0x20;
- i2c_master_send(c, buffer, 4);
- default_tuner_init(c);
- break;
case TUNER_PHILIPS_TD1316:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
@@ -598,6 +590,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (t->standby)
t->standby (client);
break;
+#ifdef CONFIG_VIDEO_V4L1
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
@@ -607,17 +600,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
break;
- case TDA9887_SET_CONFIG:
- if (t->type == TUNER_TDA9887) {
- int *i = arg;
-
- t->tda9887_config = *i;
- set_freq(client, t->tv_freq);
- }
- break;
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
case VIDIOCSCHAN:
{
static const v4l2_std_id map[] = {
@@ -701,7 +683,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
return 0;
}
+#endif
+ case TDA9887_SET_CONFIG:
+ if (t->type == TUNER_TDA9887) {
+ int *i = arg;
+ t->tda9887_config = *i;
+ set_freq(client, t->tv_freq);
+ }
+ break;
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index d071c5cbf013..abe37cf632c6 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -339,7 +339,20 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
- if (t->type == TUNER_MICROTUNE_4042FI5) {
+ switch (t->type) {
+ case TUNER_LG_TDVS_H06XF:
+ /* Set the Auxiliary Byte. */
+ buffer[0] = buffer[2];
+ buffer[0] &= ~0x20;
+ buffer[0] |= 0x18;
+ buffer[1] = 0x20;
+ tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
+
+ if (2 != (rc = i2c_master_send(c,buffer,2)))
+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+ break;
+ case TUNER_MICROTUNE_4042FI5:
+ {
// FIXME - this may also work for other tuners
unsigned long timeout = jiffies + msecs_to_jiffies(1);
u8 status_byte = 0;
@@ -364,10 +377,12 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = config;
buffer[3] = cb;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0],buffer[1],buffer[2],buffer[3]);
+ buffer[0],buffer[1],buffer[2],buffer[3]);
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+ break;
+ }
}
}
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index a167e17c6dcd..d7eadc2c298d 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -1027,10 +1027,11 @@ static struct tuner_params tuner_tnf_5335mf_params[] = {
/* 70-79 */
/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+/* '+ 4' turns on the Low Noise Amplifier */
static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
- { 16 * 130.00 /*MHz*/, 0xce, 0x01, },
- { 16 * 364.50 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x08, },
+ { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
+ { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
+ { 16 * 999.99 , 0xce, 0x08 + 4, },
};
static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
@@ -1060,10 +1061,11 @@ static struct tuner_params tuner_thomson_fe6600_params[] = {
/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
+/* '+ 4' turns on the Low Noise Amplifier */
static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
- { 16 * 146.25 /*MHz*/, 0xce, 0x01, },
- { 16 * 428.50 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x08, },
+ { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
+ { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
+ { 16 * 999.99 , 0xce, 0x08 + 4, },
};
static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
index 59fb899f31f3..a0fd82b924f2 100644
--- a/drivers/media/video/usbvideo/Kconfig
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -3,7 +3,7 @@ config VIDEO_USBVIDEO
config USB_VICAM
tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
- depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+ depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL
select VIDEO_USBVIDEO
---help---
Say Y here if you have 3com homeconnect camera (vicam).
@@ -13,7 +13,7 @@ config USB_VICAM
config USB_IBMCAM
tristate "USB IBM (Xirlink) C-it Camera support"
- depends on USB && VIDEO_V4L1
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y here if you want to connect a IBM "C-It" camera, also known as
@@ -28,7 +28,7 @@ config USB_IBMCAM
config USB_KONICAWC
tristate "USB Konica Webcam support"
- depends on USB && VIDEO_V4L1
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y here if you want support for webcams based on a Konica
@@ -39,7 +39,7 @@ config USB_KONICAWC
config USB_QUICKCAM_MESSENGER
tristate "USB Logitech Quickcam Messenger"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y or M here to enable support for the USB Logitech Quickcam
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index d83a2c84d233..d7c3fcbc80f7 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -599,6 +599,10 @@ v4l_compat_translate_ioctl(struct inode *inode,
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
break;
}
+
+ pict->depth = ((fmt2->fmt.pix.bytesperline<<3)
+ + (fmt2->fmt.pix.width-1) )
+ /fmt2->fmt.pix.width;
pict->palette = pixelformat_to_palette(
fmt2->fmt.pix.pixelformat);
break;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index f06dc19e504a..8d972ffdaf98 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -202,7 +202,7 @@ static char *v4l2_memory_names[] = {
/* ------------------------------------------------------------------ */
/* debug help functions */
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
static const char *v4l1_ioctls[] = {
[_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
[_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
@@ -301,7 +301,7 @@ static const char *v4l2_ioctls[] = {
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *v4l2_int_ioctls[] = {
-#ifdef HAVE_VIDEO_DECODER
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
[_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
[_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
[_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
@@ -367,7 +367,7 @@ void v4l_printk_ioctl(unsigned int cmd)
(_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case 'v':
printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L1_IOCTLS) ?
@@ -414,6 +414,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
printk ("%s: tuner type=%d\n", s, *p);
break;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case DECODER_SET_VBI_BYPASS:
case DECODER_ENABLE_OUTPUT:
case DECODER_GET_STATUS:
@@ -424,6 +425,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case VIDIOCCAPTURE:
case VIDIOCSYNC:
case VIDIOCSWRITEMODE:
+#endif
case TUNER_SET_TYPE_ADDR:
case TUNER_SET_STANDBY:
case TDA9887_SET_CONFIG:
@@ -755,6 +757,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
p->afc);
break;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGVBIFMT:
case VIDIOCSVBIFMT:
{
@@ -924,6 +927,14 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
p->clipcount);
break;
}
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ {
+ unsigned long *p=arg;
+ printk ("%s: value=%lu\n", s, *p);
+ break;
+ }
+#endif
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
case VIDIOC_INT_I2S_CLOCK_FREQ:
case VIDIOC_INT_S_STANDBY:
@@ -933,13 +944,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
printk ("%s: value=%d\n", s, *p);
break;
}
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- {
- unsigned long *p=arg;
- printk ("%s: value=%lu\n", s, *p);
- break;
- }
case VIDIOC_G_STD:
case VIDIOC_S_STD:
case VIDIOC_QUERYSTD:
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index b26ebaff226f..88bf2af2a0e7 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -760,7 +760,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_overlay(file, fh, *i);
break;
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* --- streaming capture ------------------------------------- */
case VIDIOCGMBUF:
{
@@ -1512,6 +1512,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
int i=0;
int base;
int end;
+ int ret;
char *name_base;
switch(type)
@@ -1537,6 +1538,8 @@ int video_register_device(struct video_device *vfd, int type, int nr)
name_base = "radio";
break;
default:
+ printk(KERN_ERR "%s called with unknown type: %d\n",
+ __FUNCTION__, type);
return -1;
}
@@ -1571,9 +1574,18 @@ int video_register_device(struct video_device *vfd, int type, int nr)
vfd->class_dev.class = &video_class;
vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base);
- class_device_register(&vfd->class_dev);
- class_device_create_file(&vfd->class_dev,
- &class_device_attr_name);
+ ret = class_device_register(&vfd->class_dev);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_register failed\n",
+ __FUNCTION__);
+ goto fail_minor;
+ }
+ ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_create_file 'name' failed\n",
+ __FUNCTION__);
+ goto fail_classdev;
+ }
#if 1
/* needed until all drivers are fixed */
@@ -1583,6 +1595,15 @@ int video_register_device(struct video_device *vfd, int type, int nr)
"http://lwn.net/Articles/36850/\n", vfd->name);
#endif
return 0;
+
+fail_classdev:
+ class_device_unregister(&vfd->class_dev);
+fail_minor:
+ mutex_lock(&videodev_lock);
+ video_device[vfd->minor] = NULL;
+ vfd->minor = -1;
+ mutex_unlock(&videodev_lock);
+ return ret;
}
/**
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 41d23c8acbd8..841884af0cc0 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -986,7 +986,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
file->f_flags & O_NONBLOCK));
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
{
struct vivi_fh *fh=priv;
@@ -1328,7 +1328,7 @@ static struct video_device vivi = {
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
.tvnorms = tvnorms,
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d4cb144ab402..c537d71c18e4 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -640,7 +640,6 @@ typedef struct _MPT_ADAPTER
struct work_struct fc_setup_reset_work;
struct list_head fc_rports;
spinlock_t fc_rescan_work_lock;
- int fc_rescan_work_count;
struct work_struct fc_rescan_work;
char fc_rescan_work_q_name[KOBJ_NAME_LEN];
struct workqueue_struct *fc_rescan_work_q;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 90da7d63b08e..85696f34c310 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -669,7 +669,10 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
* if still doing discovery,
* hang loose a while until finished
*/
- if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+ if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
+ (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
+ (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
+ == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
if (count-- > 0) {
msleep(100);
goto try_again;
@@ -895,59 +898,45 @@ mptfc_rescan_devices(void *arg)
{
MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
int ii;
- int work_to_do;
u64 pn;
- unsigned long flags;
struct mptfc_rport_info *ri;
- do {
- /* start by tagging all ports as missing */
- list_for_each_entry(ri, &ioc->fc_rports, list) {
- if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
- ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
- }
+ /* start by tagging all ports as missing */
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
}
+ }
- /*
- * now rescan devices known to adapter,
- * will reregister existing rports
- */
- for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) mptfc_GetFcPortPage0(ioc, ii);
- mptfc_init_host_attr(ioc,ii); /* refresh */
- mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ /*
+ * now rescan devices known to adapter,
+ * will reregister existing rports
+ */
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ (void) mptfc_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc, ii); /* refresh */
+ mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
+ }
+
+ /* delete devices still missing */
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ /* if newly missing, delete it */
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
+
+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+ MPT_RPORT_INFO_FLAGS_MISSING);
+ fc_remote_port_delete(ri->rport); /* won't sleep */
+ ri->rport = NULL;
+
+ pn = (u64)ri->pg0.WWPN.High << 32 |
+ (u64)ri->pg0.WWPN.Low;
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_rescan.%d: %llx deleted\n",
+ ioc->name,
+ ioc->sh->host_no,
+ (unsigned long long)pn));
}
-
- /* delete devices still missing */
- list_for_each_entry(ri, &ioc->fc_rports, list) {
- /* if newly missing, delete it */
- if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
-
- ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
- MPT_RPORT_INFO_FLAGS_MISSING);
- fc_remote_port_delete(ri->rport); /* won't sleep */
- ri->rport = NULL;
-
- pn = (u64)ri->pg0.WWPN.High << 32 |
- (u64)ri->pg0.WWPN.Low;
- dfcprintk ((MYIOC_s_INFO_FMT
- "mptfc_rescan.%d: %llx deleted\n",
- ioc->name,
- ioc->sh->host_no,
- (unsigned long long)pn));
- }
- }
-
- /*
- * allow multiple passes as target state
- * might have changed during scan
- */
- spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- if (ioc->fc_rescan_work_count > 2) /* only need one more */
- ioc->fc_rescan_work_count = 2;
- work_to_do = --ioc->fc_rescan_work_count;
- spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- } while (work_to_do);
+ }
}
static int
@@ -1159,7 +1148,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* by doing it via the workqueue, some locking is eliminated
*/
- ioc->fc_rescan_work_count = 1;
queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
flush_workqueue(ioc->fc_rescan_work_q);
@@ -1202,10 +1190,8 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
case MPI_EVENT_RESCAN:
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
if (ioc->fc_rescan_work_q) {
- if (ioc->fc_rescan_work_count++ == 0) {
- queue_work(ioc->fc_rescan_work_q,
- &ioc->fc_rescan_work);
- }
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
}
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
break;
@@ -1248,10 +1234,8 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
mptfc_SetFcPortPage1_defaults(ioc);
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
if (ioc->fc_rescan_work_q) {
- if (ioc->fc_rescan_work_count++ == 0) {
- queue_work(ioc->fc_rescan_work_q,
- &ioc->fc_rescan_work);
- }
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
}
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
}
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 0b9682e9a357..74f8cdeeff0f 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -79,7 +79,8 @@ static int mmc_queue_thread(void *d)
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
if (!blk_queue_plugged(q))
- mq->req = req = elv_next_request(q);
+ req = elv_next_request(q);
+ mq->req = req;
spin_unlock_irq(q->queue_lock);
if (!req) {
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 8a30ef3ae419..c351c6d1a18a 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -41,7 +41,7 @@
#include "wbsd.h"
#define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.5"
+#define DRIVER_VERSION "1.6"
#define DBG(x...) \
pr_debug(DRIVER_NAME ": " x)
@@ -1439,13 +1439,13 @@ static int __devinit wbsd_scan(struct wbsd_host *host)
static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
{
- if (io & 0x7)
+ if (base & 0x7)
return -EINVAL;
if (!request_region(base, 8, DRIVER_NAME))
return -EIO;
- host->base = io;
+ host->base = base;
return 0;
}
@@ -1773,7 +1773,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
/*
* Request resources.
*/
- ret = wbsd_request_resources(host, io, irq, dma);
+ ret = wbsd_request_resources(host, base, irq, dma);
if (ret) {
wbsd_release_resources(host);
wbsd_free_mmc(dev);
@@ -1861,6 +1861,7 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp)
static int __devinit wbsd_probe(struct platform_device *dev)
{
+ /* Use the module parameters for resources */
return wbsd_init(&dev->dev, io, irq, dma, 0);
}
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index d7897dc6b3c8..a0ba07c36ee9 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -130,11 +130,13 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
if (ctrl & NAND_CTRL_CHANGE) {
unsigned long bits;
- bits = (~ctrl & NAND_NCE) << 2;
- bits |= (ctrl & NAND_CLE) << 7;
- bits |= (ctrl & NAND_ALE) << 6;
+ bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0;
+ bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0;
+ bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0;
- ams_delta_latch2_write(0xC2, bits);
+ ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE |
+ AMS_DELTA_LATCH2_NAND_ALE |
+ AMS_DELTA_LATCH2_NAND_NCE, bits);
}
if (cmd != NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 62b861304e03..c8cbc00243fe 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1093,9 +1093,10 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
ret = nand_do_read_ops(mtd, from, &chip->ops);
+ *retlen = chip->ops.retlen;
+
nand_release_device(mtd);
- *retlen = chip->ops.retlen;
return ret;
}
@@ -1691,9 +1692,10 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
ret = nand_do_write_ops(mtd, to, &chip->ops);
+ *retlen = chip->ops.retlen;
+
nand_release_device(mtd);
- *retlen = chip->ops.retlen;
return ret;
}
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 4532b17e40ea..aedfddf20cb3 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -1003,7 +1003,8 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry;
- unsigned long flags, i;
+ unsigned long flags;
+ int i;
if (vp->tx_full) /* No room to transmit with */
return 1;
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 7e2ca9571467..257d3bce3993 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -899,7 +899,7 @@ memory_squeeze:
}
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
{
struct i596_cmd *ptr;
@@ -932,7 +932,8 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private
lp->scb.cmd = I596_NULL;
}
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
+static void i596_reset(struct net_device *dev, struct i596_private *lp,
+ int ioaddr)
{
unsigned long flags;
@@ -1578,7 +1579,7 @@ static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "i82596 debug mask");
-int init_module(void)
+int __init init_module(void)
{
if (debug >= 0)
i596_debug = debug;
@@ -1588,7 +1589,7 @@ int init_module(void)
return 0;
}
-void cleanup_module(void)
+void __exit cleanup_module(void)
{
unregister_netdev(dev_82596);
#ifdef __mc68000__
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 39189903e355..30b3671d833d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1724,6 +1724,20 @@ config VIA_RHINE_MMIO
If unsure, say Y.
+config VIA_RHINE_NAPI
+ bool "Use Rx Polling (NAPI)"
+ depends on VIA_RHINE
+ help
+ NAPI is a new driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card.
+
+ If your estimated Rx load is 10kpps or more, or if the card will be
+ deployed on potentially unfriendly networks (e.g. in a firewall),
+ then say Y here.
+
+ See for more
+ information.
+
config LAN_SAA9730
bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -2219,6 +2233,33 @@ config GFAR_NAPI
bool "NAPI Support"
depends on GIANFAR
+config UCC_GETH
+ tristate "Freescale QE UCC GETH"
+ depends on QUICC_ENGINE && UCC_FAST
+ help
+ This driver supports the Gigabit Ethernet mode of QE UCC.
+ QE can be found on MPC836x CPUs.
+
+config UGETH_NAPI
+ bool "NAPI Support"
+ depends on UCC_GETH
+
+config UGETH_MAGIC_PACKET
+ bool "Magic Packet detection support"
+ depends on UCC_GETH
+
+config UGETH_FILTERING
+ bool "Mac address filtering support"
+ depends on UCC_GETH
+
+config UGETH_TX_ON_DEMOND
+ bool "Transmit on Demond support"
+ depends on UCC_GETH
+
+config UGETH_HAS_GIGA
+ bool
+ depends on UCC_GETH && MPC836x
+
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c91e95126f78..8427bf9dec9d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -18,6 +18,9 @@ gianfar_driver-objs := gianfar.o \
gianfar_mii.o \
gianfar_sysfs.o
+obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
+
#
# link order important here
#
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 7952dc6d77e3..0fbbcb75af69 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -370,8 +370,7 @@ MODULE_PARM_DESC(mem, "Memory base address(es)");
MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
MODULE_LICENSE("GPL");
-int
-init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index b14e89004c3a..0a0e0cd81a23 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -29,7 +29,7 @@ config ATALK
even politically correct people are allowed to say Y here.
config DEV_APPLETALK
- bool "Appletalk interfaces support"
+ tristate "Appletalk interfaces support"
depends on ATALK
help
AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 1d01ac0000e4..ae7f828344d9 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -1030,7 +1030,7 @@ module_param(io, int, 0);
module_param(irq, int, 0);
module_param(board_type, int, 0);
-int init_module(void)
+int __init init_module(void)
{
if (io == 0)
printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 5d7929c79bce..4ca061c2d5b2 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -901,7 +901,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
-int init_module(void)
+int __init init_module(void)
{
if (io == 0)
printk("at1700: You should not use auto-probing with insmod!\n");
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index db73de0d2511..652eb05a6c2d 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.43"
-#define DRV_MODULE_RELDATE "June 28, 2006"
+#define DRV_MODULE_VERSION "1.4.44"
+#define DRV_MODULE_RELDATE "August 10, 2006"
#define RUN_AT(x) (jiffies + (x))
@@ -209,8 +209,10 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
static inline u32 bnx2_tx_avail(struct bnx2 *bp)
{
- u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+ u32 diff;
+ smp_mb();
+ diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
if (diff > MAX_TX_DESC_CNT)
diff = (diff & MAX_TX_DESC_CNT) - 1;
return (bp->tx_ring_size - diff);
@@ -1569,7 +1571,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
unsigned long align;
- skb = dev_alloc_skb(bp->rx_buf_size);
+ skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
if (skb == NULL) {
return -ENOMEM;
}
@@ -1578,7 +1580,6 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
skb_reserve(skb, 8 - align);
}
- skb->dev = bp->dev;
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
@@ -1686,15 +1687,20 @@ bnx2_tx_int(struct bnx2 *bp)
}
bp->tx_cons = sw_cons;
+ /* Need to make the tx_cons update visible to bnx2_start_xmit()
+ * before checking for netif_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that bnx2_start_xmit()
+ * will miss it and cause the queue to be stopped forever.
+ */
+ smp_mb();
- if (unlikely(netif_queue_stopped(bp->dev))) {
- spin_lock(&bp->tx_lock);
+ if (unlikely(netif_queue_stopped(bp->dev)) &&
+ (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) {
+ netif_tx_lock(bp->dev);
if ((netif_queue_stopped(bp->dev)) &&
- (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
-
+ (bnx2_tx_avail(bp) > bp->tx_wake_thresh))
netif_wake_queue(bp->dev);
- }
- spin_unlock(&bp->tx_lock);
+ netif_tx_unlock(bp->dev);
}
}
@@ -1786,7 +1792,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
struct sk_buff *new_skb;
- new_skb = dev_alloc_skb(len + 2);
+ new_skb = netdev_alloc_skb(bp->dev, len + 2);
if (new_skb == NULL)
goto reuse_rx;
@@ -1797,7 +1803,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
skb_reserve(new_skb, 2);
skb_put(new_skb, len);
- new_skb->dev = bp->dev;
bnx2_reuse_rx_skb(bp, skb,
sw_ring_cons, sw_ring_prod);
@@ -3503,6 +3508,8 @@ bnx2_init_tx_ring(struct bnx2 *bp)
struct tx_bd *txbd;
u32 val;
+ bp->tx_wake_thresh = bp->tx_ring_size / 2;
+
txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
@@ -3952,7 +3959,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
return -EINVAL;
pkt_size = 1514;
- skb = dev_alloc_skb(pkt_size);
+ skb = netdev_alloc_skb(bp->dev, pkt_size);
if (!skb)
return -ENOMEM;
packet = skb_put(skb, pkt_size);
@@ -4390,10 +4397,8 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
#endif
/* Called with netif_tx_lock.
- * hard_start_xmit is pseudo-lockless - a lock is only required when
- * the tx queue is full. This way, we get the benefit of lockless
- * operations most of the time without the complexities to handle
- * netif_stop_queue/wake_queue race conditions.
+ * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
+ * netif_wake_queue().
*/
static int
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -4512,12 +4517,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
- spin_lock(&bp->tx_lock);
netif_stop_queue(dev);
-
- if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+ if (bnx2_tx_avail(bp) > bp->tx_wake_thresh)
netif_wake_queue(dev);
- spin_unlock(&bp->tx_lock);
}
return NETDEV_TX_OK;
@@ -5628,7 +5630,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->pdev = pdev;
spin_lock_init(&bp->phy_lock);
- spin_lock_init(&bp->tx_lock);
INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
@@ -5751,7 +5752,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->mac_addr[5] = (u8) reg;
bp->tx_ring_size = MAX_TX_DESC_CNT;
- bnx2_set_rx_ring_size(bp, 100);
+ bnx2_set_rx_ring_size(bp, 255);
bp->rx_csum = 1;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 658c5ee95c73..fe804763c607 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3890,10 +3890,6 @@ struct bnx2 {
u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
u16 tx_prod;
- struct tx_bd *tx_desc_ring;
- struct sw_bd *tx_buf_ring;
- int tx_ring_size;
-
u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
u16 hw_tx_cons;
@@ -3916,9 +3912,11 @@ struct bnx2 {
struct sw_bd *rx_buf_ring;
struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
- /* Only used to synchronize netif_stop_queue/wake_queue when tx */
- /* ring is full */
- spinlock_t tx_lock;
+ /* TX constants */
+ struct tx_bd *tx_desc_ring;
+ struct sw_bd *tx_buf_ring;
+ int tx_ring_size;
+ u32 tx_wake_thresh;
/* End of fields used in the performance code paths. */
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 47eecce35fa4..2dcca79b1f6a 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -1905,8 +1905,7 @@ MODULE_LICENSE("GPL");
*/
-int
-init_module(void)
+int __init init_module(void)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
struct net_local *lp;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 1b758b707134..3d76fa144c4f 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -339,6 +339,17 @@ static void dm9000_timeout(struct net_device *dev)
spin_unlock_irqrestore(&db->lock,flags);
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ *Used by netconsole
+ */
+static void dm9000_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ dm9000_interrupt(dev->irq,dev,NULL);
+ enable_irq(dev->irq);
+}
+#endif
/* dm9000_release_board
*
@@ -538,6 +549,9 @@ dm9000_probe(struct platform_device *pdev)
ndev->stop = &dm9000_stop;
ndev->get_stats = &dm9000_get_stats;
ndev->set_multicast_list = &dm9000_hash_table;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = &dm9000_poll_controller;
+#endif
#ifdef DM9000_PROGRAM_EEPROM
program_eeprom(db);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 91ef5f2fd768..ce850f1078b5 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -173,8 +173,11 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
static int debug = 3;
+static int eeprom_bad_csum_allow = 0;
module_param(debug, int, 0);
+module_param(eeprom_bad_csum_allow, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
#define DPRINTK(nlevel, klevel, fmt, args...) \
(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
@@ -756,7 +759,8 @@ static int e100_eeprom_load(struct nic *nic)
checksum = le16_to_cpu(0xBABA - checksum);
if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
- return -EAGAIN;
+ if (!eeprom_bad_csum_allow)
+ return -EAGAIN;
}
return 0;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 583518ae49ce..b3b919116e0f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -105,6 +105,33 @@ static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
uint16_t duplex);
static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
+static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw,
+ uint32_t segment);
+static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+ uint16_t words, uint16_t *data);
+static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
+ uint8_t* data);
+static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
+ uint16_t *data);
+static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ uint16_t *data);
+static void e1000_release_software_flag(struct e1000_hw *hw);
+static void e1000_release_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw,
+ uint32_t no_snoop);
+static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw,
+ uint32_t index, uint8_t byte);
+static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+ uint16_t words, uint16_t *data);
+static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
+ uint8_t data);
+static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ uint16_t data);
+
/* IGP cable length table */
static const
uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
@@ -3233,7 +3260,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
return data;
}
-int32_t
+static int32_t
e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
{
uint32_t swfw_sync = 0;
@@ -3277,7 +3304,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
return E1000_SUCCESS;
}
-void
+static void
e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
{
uint32_t swfw_sync;
@@ -3575,7 +3602,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw,
return E1000_SUCCESS;
}
-int32_t
+static int32_t
e1000_read_kmrn_reg(struct e1000_hw *hw,
uint32_t reg_addr,
uint16_t *data)
@@ -3608,7 +3635,7 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
return E1000_SUCCESS;
}
-int32_t
+static int32_t
e1000_write_kmrn_reg(struct e1000_hw *hw,
uint32_t reg_addr,
uint16_t data)
@@ -3839,7 +3866,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
-int32_t
+static int32_t
e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
{
int32_t ret_val;
@@ -4086,7 +4113,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-int32_t
+static int32_t
e1000_phy_ife_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info)
{
@@ -5643,6 +5670,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
* for the first 15 multicast addresses, and hashes the rest into the
* multicast table.
*****************************************************************************/
+#if 0
void
e1000_mc_addr_list_update(struct e1000_hw *hw,
uint8_t *mc_addr_list,
@@ -5719,6 +5747,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
}
DEBUGOUT("MC Update Complete\n");
}
+#endif /* 0 */
/******************************************************************************
* Hashes an address to determine its location in the multicast table
@@ -6587,6 +6616,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* offset - offset to read from
*****************************************************************************/
+#if 0
uint32_t
e1000_read_reg_io(struct e1000_hw *hw,
uint32_t offset)
@@ -6597,6 +6627,7 @@ e1000_read_reg_io(struct e1000_hw *hw,
e1000_io_write(hw, io_addr, offset);
return e1000_io_read(hw, io_data);
}
+#endif /* 0 */
/******************************************************************************
* Writes a value to one of the devices registers using port I/O (as opposed to
@@ -7909,6 +7940,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
* returns: - none.
*
***************************************************************************/
+#if 0
void
e1000_enable_pciex_master(struct e1000_hw *hw)
{
@@ -7923,6 +7955,7 @@ e1000_enable_pciex_master(struct e1000_hw *hw)
ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
E1000_WRITE_REG(hw, CTRL, ctrl);
}
+#endif /* 0 */
/*******************************************************************************
*
@@ -8148,7 +8181,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-int32_t
+static int32_t
e1000_get_software_semaphore(struct e1000_hw *hw)
{
int32_t timeout = hw->eeprom.word_size + 1;
@@ -8183,7 +8216,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-void
+static void
e1000_release_software_semaphore(struct e1000_hw *hw)
{
uint32_t swsm;
@@ -8265,7 +8298,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* returns: E1000_SUCCESS
*
*****************************************************************************/
-int32_t
+static int32_t
e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
{
uint32_t gcr_reg = 0;
@@ -8306,7 +8339,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-int32_t
+static int32_t
e1000_get_software_flag(struct e1000_hw *hw)
{
int32_t timeout = PHY_CFG_TIMEOUT;
@@ -8345,7 +8378,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-void
+static void
e1000_release_software_flag(struct e1000_hw *hw)
{
uint32_t extcnf_ctrl;
@@ -8369,6 +8402,7 @@ e1000_release_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
+#if 0
int32_t
e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
{
@@ -8388,6 +8422,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
return ret_val;
}
+#endif /* 0 */
/***************************************************************************
*
@@ -8397,6 +8432,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
+#if 0
int32_t
e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
{
@@ -8416,6 +8452,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
return ret_val;
}
+#endif /* 0 */
/******************************************************************************
* Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
@@ -8426,7 +8463,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-int32_t
+static int32_t
e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
uint16_t *data)
{
@@ -8482,7 +8519,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
* words - number of words to write
* data - words to write to the EEPROM
*****************************************************************************/
-int32_t
+static int32_t
e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
uint16_t *data)
{
@@ -8529,7 +8566,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
*
* hw - The pointer to the hw structure
****************************************************************************/
-int32_t
+static int32_t
e1000_ich8_cycle_init(struct e1000_hw *hw)
{
union ich8_hws_flash_status hsfsts;
@@ -8596,7 +8633,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
*
* hw - The pointer to the hw structure
****************************************************************************/
-int32_t
+static int32_t
e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
{
union ich8_hws_flash_ctrl hsflctl;
@@ -8631,7 +8668,7 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
* size - Size of data to read, 1=byte 2=word
* data - Pointer to the word to store the value read.
*****************************************************************************/
-int32_t
+static int32_t
e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
uint32_t size, uint16_t* data)
{
@@ -8710,7 +8747,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
* size - Size of data to read, 1=byte 2=word
* data - The byte(s) to write to the NVM.
*****************************************************************************/
-int32_t
+static int32_t
e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
uint16_t data)
{
@@ -8785,7 +8822,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
* index - The index of the byte to read.
* data - Pointer to a byte to store the value read.
*****************************************************************************/
-int32_t
+static int32_t
e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
{
int32_t status = E1000_SUCCESS;
@@ -8808,7 +8845,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
* index - The index of the byte to write.
* byte - The byte to write to the NVM.
*****************************************************************************/
-int32_t
+static int32_t
e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
{
int32_t error = E1000_SUCCESS;
@@ -8839,7 +8876,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
* index - The index of the byte to read.
* data - The byte to write to the NVM.
*****************************************************************************/
-int32_t
+static int32_t
e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
{
int32_t status = E1000_SUCCESS;
@@ -8857,7 +8894,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
* index - The starting byte index of the word to read.
* data - Pointer to a word to store the value read.
*****************************************************************************/
-int32_t
+static int32_t
e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
{
int32_t status = E1000_SUCCESS;
@@ -8872,6 +8909,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
* index - The starting byte index of the word to read.
* data - The word to write to the NVM.
*****************************************************************************/
+#if 0
int32_t
e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
{
@@ -8879,6 +8917,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
status = e1000_write_ich8_data(hw, index, 2, data);
return status;
}
+#endif /* 0 */
/******************************************************************************
* Erases the bank specified. Each bank is a 4k block. Segments are 0 based.
@@ -8887,7 +8926,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
* hw - pointer to e1000_hw structure
* segment - 0 for first segment, 1 for second segment, etc.
*****************************************************************************/
-int32_t
+static int32_t
e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
{
union ich8_hws_flash_status hsfsts;
@@ -8984,6 +9023,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
* hw: Struct containing variables accessed by shared code
*
*****************************************************************************/
+#if 0
int32_t
e1000_duplex_reversal(struct e1000_hw *hw)
{
@@ -9012,8 +9052,9 @@ e1000_duplex_reversal(struct e1000_hw *hw)
return ret_val;
}
+#endif /* 0 */
-int32_t
+static int32_t
e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
uint32_t cnf_base_addr, uint32_t cnf_size)
{
@@ -9047,7 +9088,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
}
-int32_t
+static int32_t
e1000_init_lcd_from_nvm(struct e1000_hw *hw)
{
uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index f9341e3276b3..375b95518c31 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -323,13 +323,8 @@ int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t dat
int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
-int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
-int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
-int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
-int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
-int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
/* EEPROM Functions */
int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
@@ -400,13 +395,8 @@ int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw);
-int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
-void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
-void e1000_release_software_flag(struct e1000_hw *hw);
-int32_t e1000_get_software_flag(struct e1000_hw *hw);
/* Filters (multicast, vlan, receive) */
-void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -431,31 +421,9 @@ void e1000_pci_clear_mwi(struct e1000_hw *hw);
void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* Port I/O is only supported on 82544 and newer */
-uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
-uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
-void e1000_enable_pciex_master(struct e1000_hw *hw);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
-int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
-void e1000_release_software_semaphore(struct e1000_hw *hw);
int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
-int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
-
-int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
- uint8_t *data);
-int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
- uint8_t byte);
-int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
- uint8_t byte);
-int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
- uint16_t *data);
-int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
- uint32_t size, uint16_t *data);
-int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
- uint16_t words, uint16_t *data);
-int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
- uint16_t words, uint16_t *data);
-int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment);
#define E1000_READ_REG_IO(a, reg) \
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index da62db897426..726f43d55937 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3127,7 +3127,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
break;
}
- /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size
* i.e. RXBUFFER_2048 --> size-4096 slab */
@@ -3708,7 +3708,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
#define E1000_CB_LENGTH 256
if (length < E1000_CB_LENGTH) {
struct sk_buff *new_skb =
- dev_alloc_skb(length + NET_IP_ALIGN);
+ netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
if (new_skb) {
skb_reserve(new_skb, NET_IP_ALIGN);
new_skb->dev = netdev;
@@ -3979,7 +3979,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
while (cleaned_count--) {
if (!(skb = buffer_info->skb))
- skb = dev_alloc_skb(bufsz);
+ skb = netdev_alloc_skb(netdev, bufsz);
else {
skb_trim(skb, 0);
goto map_skb;
@@ -3997,7 +3997,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes "
"at %p\n", bufsz, skb->data);
/* Try again, without freeing the previous */
- skb = dev_alloc_skb(bufsz);
+ skb = netdev_alloc_skb(netdev, bufsz);
/* Failed allocation, critical failure */
if (!skb) {
dev_kfree_skb(oldskb);
@@ -4121,7 +4121,8 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc->read.buffer_addr[j+1] = ~0;
}
- skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(netdev,
+ adapter->rx_ps_bsize0 + NET_IP_ALIGN);
if (unlikely(!skb)) {
adapter->alloc_rx_buff_failed++;
@@ -4385,11 +4386,13 @@ e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
pci_write_config_word(adapter->pdev, reg, *value);
}
+#if 0
uint32_t
e1000_io_read(struct e1000_hw *hw, unsigned long port)
{
return inl(port);
}
+#endif /* 0 */
void
e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index e5c5cd2a2712..e4e733a380e3 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -425,8 +425,8 @@ MODULE_LICENSE("GPL");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
-int
-init_module(void)
+
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 20d31430c74f..8dc61d65dd23 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1807,8 +1807,7 @@ MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
-int
-init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int i;
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 33291bcf6d4c..0701c1d810ca 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -1698,7 +1698,7 @@ MODULE_LICENSE("GPL");
* are specified, we verify and then use them. If no parameters are given, we
* autoprobe for one card only.
*/
-int init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 6b0ab1eac3fb..fd7b32a24ea4 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -421,8 +421,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
MODULE_LICENSE("GPL");
-int
-init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 4bf76f86d8e9..ca42efa9143c 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1434,7 +1434,7 @@ MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
-int init_module(void)
+int __init init_module(void)
{
int this_dev, found = 0;
struct net_device *dev;
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 97d34fee8c1f..567e27413cfd 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#include
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index d6dd3f2fb43e..02d4dc18ba69 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_FS_ENET) += fs_enet.o
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
-obj-$(CONFIG_8260) += mac-fcc.o
+obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
+obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
-fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
+fs_enet-objs := fs_enet-main.o
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
new file mode 100644
index 000000000000..e980527e2b99
--- /dev/null
+++ b/drivers/net/fs_enet/fec.h
@@ -0,0 +1,42 @@
+#ifndef FS_ENET_FEC_H
+#define FS_ENET_FEC_H
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY 0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS 64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
+#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
+#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
+#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
+#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
+#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
+#define FEC_ENET_RXF 0x02000000U /* Full frame received */
+#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
+#define FEC_ENET_MII 0x00800000U /* MII interrupt */
+#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
+
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+#define FEC_ECNTRL_RESET 0x00000001
+
+#define FEC_RCNTRL_BC_REJ 0x00000010
+#define FEC_RCNTRL_PROM 0x00000008
+#define FEC_RCNTRL_MII_MODE 0x00000004
+#define FEC_RCNTRL_DRT 0x00000002
+#define FEC_RCNTRL_LOOP 0x00000001
+
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_GTS 0x00000001
+
+
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY 50
+#endif
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index f6abff5846b3..df62506a1787 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
#include
#include
@@ -682,35 +683,6 @@ static void fs_free_irq(struct net_device *dev, int irq)
(*fep->ops->post_free_irq)(dev, irq);
}
-/**********************************************************************************/
-
-/* This interrupt occurs when the PHY detects a link change. */
-static irqreturn_t
-fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = dev_id;
- struct fs_enet_private *fep;
- const struct fs_platform_info *fpi;
-
- fep = netdev_priv(dev);
- fpi = fep->fpi;
-
- /*
- * Acknowledge the interrupt if possible. If we have not
- * found the PHY yet we can't process or acknowledge the
- * interrupt now. Instead we ignore this interrupt for now,
- * which we can do since it is edge triggered. It will be
- * acknowledged later by fs_enet_open().
- */
- if (!fep->phy)
- return IRQ_NONE;
-
- fs_mii_ack_int(dev);
- fs_mii_link_status_change_check(dev, 0);
-
- return IRQ_HANDLED;
-}
-
static void fs_timeout(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -722,10 +694,13 @@ static void fs_timeout(struct net_device *dev)
spin_lock_irqsave(&fep->lock, flags);
if (dev->flags & IFF_UP) {
+ phy_stop(fep->phydev);
(*fep->ops->stop)(dev);
(*fep->ops->restart)(dev);
+ phy_start(fep->phydev);
}
+ phy_start(fep->phydev);
wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
spin_unlock_irqrestore(&fep->lock, flags);
@@ -733,35 +708,112 @@ static void fs_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
+/*-----------------------------------------------------------------------------
+ * generic link-change handler - should be sufficient for most cases
+ *-----------------------------------------------------------------------------*/
+static void generic_adjust_link(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct phy_device *phydev = fep->phydev;
+ int new_state = 0;
+
+ if (phydev->link) {
+
+ /* adjust to duplex mode */
+ if (phydev->duplex != fep->oldduplex){
+ new_state = 1;
+ fep->oldduplex = phydev->duplex;
+ }
+
+ if (phydev->speed != fep->oldspeed) {
+ new_state = 1;
+ fep->oldspeed = phydev->speed;
+ }
+
+ if (!fep->oldlink) {
+ new_state = 1;
+ fep->oldlink = 1;
+ netif_schedule(dev);
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+ }
+
+ if (new_state)
+ fep->ops->restart(dev);
+
+ } else if (fep->oldlink) {
+ new_state = 1;
+ fep->oldlink = 0;
+ fep->oldspeed = 0;
+ fep->oldduplex = -1;
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ }
+
+ if (new_state && netif_msg_link(fep))
+ phy_print_status(phydev);
+}
+
+
+static void fs_adjust_link(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fep->lock, flags);
+
+ if(fep->ops->adjust_link)
+ fep->ops->adjust_link(dev);
+ else
+ generic_adjust_link(dev);
+
+ spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+static int fs_init_phy(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct phy_device *phydev;
+
+ fep->oldlink = 0;
+ fep->oldspeed = 0;
+ fep->oldduplex = -1;
+ if(fep->fpi->bus_id)
+ phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0);
+ else {
+ printk("No phy bus ID specified in BSP code\n");
+ return -EINVAL;
+ }
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
+ }
+
+ fep->phydev = phydev;
+
+ return 0;
+}
+
+
static int fs_enet_open(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
int r;
+ int err;
/* Install our interrupt handler. */
r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
- ": %s Could not allocate FEC IRQ!", dev->name);
+ ": %s Could not allocate FS_ENET IRQ!", dev->name);
return -EINVAL;
}
- /* Install our phy interrupt handler */
- if (fpi->phy_irq != -1) {
+ err = fs_init_phy(dev);
+ if(err)
+ return err;
- r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s Could not allocate PHY IRQ!", dev->name);
- fs_free_irq(dev, fep->interrupt);
- return -EINVAL;
- }
- }
-
- fs_mii_startup(dev);
- netif_carrier_off(dev);
- fs_mii_link_status_change_check(dev, 1);
+ phy_start(fep->phydev);
return 0;
}
@@ -769,20 +821,19 @@ static int fs_enet_open(struct net_device *dev)
static int fs_enet_close(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
unsigned long flags;
netif_stop_queue(dev);
netif_carrier_off(dev);
- fs_mii_shutdown(dev);
+ phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags);
(*fep->ops->stop)(dev);
spin_unlock_irqrestore(&fep->lock, flags);
/* release any irqs */
- if (fpi->phy_irq != -1)
- fs_free_irq(dev, fpi->phy_irq);
+ phy_disconnect(fep->phydev);
+ fep->phydev = NULL;
fs_free_irq(dev, fep->interrupt);
return 0;
@@ -830,33 +881,19 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct fs_enet_private *fep = netdev_priv(dev);
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&fep->lock, flags);
- rc = mii_ethtool_gset(&fep->mii_if, cmd);
- spin_unlock_irqrestore(&fep->lock, flags);
-
- return rc;
+ return phy_ethtool_gset(fep->phydev, cmd);
}
static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct fs_enet_private *fep = netdev_priv(dev);
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&fep->lock, flags);
- rc = mii_ethtool_sset(&fep->mii_if, cmd);
- spin_unlock_irqrestore(&fep->lock, flags);
-
- return rc;
+ phy_ethtool_sset(fep->phydev, cmd);
+ return 0;
}
static int fs_nway_reset(struct net_device *dev)
{
- struct fs_enet_private *fep = netdev_priv(dev);
- return mii_nway_restart(&fep->mii_if);
+ return 0;
}
static u32 fs_get_msglevel(struct net_device *dev)
@@ -898,7 +935,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EINVAL;
spin_lock_irqsave(&fep->lock, flags);
- rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+ rc = phy_mii_ioctl(fep->phydev, mii, cmd);
spin_unlock_irqrestore(&fep->lock, flags);
return rc;
}
@@ -1030,12 +1067,6 @@ static struct net_device *fs_init_instance(struct device *dev,
}
registered = 1;
- err = fs_mii_connect(ndev);
- if (err != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s fs_mii_connect failed.\n", ndev->name);
- goto err;
- }
return ndev;
@@ -1073,8 +1104,6 @@ static int fs_cleanup_instance(struct net_device *ndev)
fpi = fep->fpi;
- fs_mii_disconnect(ndev);
-
unregister_netdev(ndev);
dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
@@ -1196,17 +1225,39 @@ static int __init fs_init(void)
r = setup_immap();
if (r != 0)
return r;
- r = driver_register(&fs_enet_fec_driver);
- if (r != 0)
- goto err;
+#ifdef CONFIG_FS_ENET_HAS_FCC
+ /* let's insert mii stuff */
+ r = fs_enet_mdio_bb_init();
+
+ if (r != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ "BB PHY init failed.\n");
+ return r;
+ }
r = driver_register(&fs_enet_fcc_driver);
if (r != 0)
goto err;
+#endif
+#ifdef CONFIG_FS_ENET_HAS_FEC
+ r = fs_enet_mdio_fec_init();
+ if (r != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ "FEC PHY init failed.\n");
+ return r;
+ }
+
+ r = driver_register(&fs_enet_fec_driver);
+ if (r != 0)
+ goto err;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_SCC
r = driver_register(&fs_enet_scc_driver);
if (r != 0)
goto err;
+#endif
return 0;
err:
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
deleted file mode 100644
index b7e6e21725cb..000000000000
--- a/drivers/net/fs_enet/fs_enet-mii.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A.
- * by Pantelis Antoniou
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug
- *
- * Heavily based on original FEC driver by Dan Malek
- * and modifications by Joakim Tjernlund
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include "fs_enet.h"
-
-/*************************************************/
-
-/*
- * Generic PHY support.
- * Should work for all PHYs, but link change is detected by polling
- */
-
-static void generic_timer_callback(unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- struct fs_enet_private *fep = netdev_priv(dev);
-
- fep->phy_timer_list.expires = jiffies + HZ / 2;
-
- add_timer(&fep->phy_timer_list);
-
- fs_mii_link_status_change_check(dev, 0);
-}
-
-static void generic_startup(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
- fep->phy_timer_list.data = (unsigned long)dev;
- fep->phy_timer_list.function = generic_timer_callback;
- add_timer(&fep->phy_timer_list);
-}
-
-static void generic_shutdown(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- del_timer_sync(&fep->phy_timer_list);
-}
-
-/* ------------------------------------------------------------------------- */
-/* The Davicom DM9161 is used on the NETTA board */
-
-/* register definitions */
-
-#define MII_DM9161_ANAR 4 /* Aux. Config Register */
-#define MII_DM9161_ACR 16 /* Aux. Config Register */
-#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
-#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
-#define MII_DM9161_INTR 21 /* Interrupt Register */
-#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
-#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
-
-static void dm9161_startup(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
- /* Start autonegotiation */
- fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ*8);
-}
-
-static void dm9161_ack_int(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
-}
-
-static void dm9161_shutdown(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
-}
-
-/**********************************************************************************/
-
-static const struct phy_info phy_info[] = {
- {
- .id = 0x00181b88,
- .name = "DM9161",
- .startup = dm9161_startup,
- .ack_int = dm9161_ack_int,
- .shutdown = dm9161_shutdown,
- }, {
- .id = 0,
- .name = "GENERIC",
- .startup = generic_startup,
- .shutdown = generic_shutdown,
- },
-};
-
-/**********************************************************************************/
-
-static int phy_id_detect(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
- struct fs_enet_mii_bus *bus = fep->mii_bus;
- int i, r, start, end, phytype, physubtype;
- const struct phy_info *phy;
- int phy_hwid, phy_id;
-
- phy_hwid = -1;
- fep->phy = NULL;
-
- /* auto-detect? */
- if (fpi->phy_addr == -1) {
- start = 1;
- end = 32;
- } else { /* direct */
- start = fpi->phy_addr;
- end = start + 1;
- }
-
- for (phy_id = start; phy_id < end; phy_id++) {
- /* skip already used phy addresses on this bus */
- if (bus->usage_map & (1 << phy_id))
- continue;
- r = fs_mii_read(dev, phy_id, MII_PHYSID1);
- if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
- continue;
- r = fs_mii_read(dev, phy_id, MII_PHYSID2);
- if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
- continue;
- phy_hwid = (phytype << 16) | physubtype;
- if (phy_hwid != -1)
- break;
- }
-
- if (phy_hwid == -1) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s No PHY detected! range=0x%02x-0x%02x\n",
- dev->name, start, end);
- return -1;
- }
-
- for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
- if (phy->id == (phy_hwid >> 4) || phy->id == 0)
- break;
-
- if (i >= ARRAY_SIZE(phy_info)) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s PHY id 0x%08x is not supported!\n",
- dev->name, phy_hwid);
- return -1;
- }
-
- fep->phy = phy;
-
- /* mark this address as used */
- bus->usage_map |= (1 << phy_id);
-
- printk(KERN_INFO DRV_MODULE_NAME
- ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
- dev->name, phy_id, fep->phy->name, phy_hwid,
- fpi->phy_addr == -1 ? " (auto-detected)" : "");
-
- return phy_id;
-}
-
-void fs_mii_startup(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- if (fep->phy->startup)
- (*fep->phy->startup) (dev);
-}
-
-void fs_mii_shutdown(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- if (fep->phy->shutdown)
- (*fep->phy->shutdown) (dev);
-}
-
-void fs_mii_ack_int(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- if (fep->phy->ack_int)
- (*fep->phy->ack_int) (dev);
-}
-
-#define MII_LINK 0x0001
-#define MII_HALF 0x0002
-#define MII_FULL 0x0004
-#define MII_BASE4 0x0008
-#define MII_10M 0x0010
-#define MII_100M 0x0020
-#define MII_1G 0x0040
-#define MII_10G 0x0080
-
-/* return full mii info at one gulp, with a usable form */
-static unsigned int mii_full_status(struct mii_if_info *mii)
-{
- unsigned int status;
- int bmsr, adv, lpa, neg;
- struct fs_enet_private* fep = netdev_priv(mii->dev);
-
- /* first, a dummy read, needed to latch some MII phys */
- (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
- bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-
- /* no link */
- if ((bmsr & BMSR_LSTATUS) == 0)
- return 0;
-
- status = MII_LINK;
-
- /* Lets look what ANEG says if it's supported - otherwize we shall
- take the right values from the platform info*/
- if(!mii->force_media) {
- /* autoneg not completed; don't bother */
- if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
- return 0;
-
- adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
- lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
-
- neg = lpa & adv;
- } else {
- neg = fep->fpi->bus_info->lpa;
- }
-
- if (neg & LPA_100FULL)
- status |= MII_FULL | MII_100M;
- else if (neg & LPA_100BASE4)
- status |= MII_FULL | MII_BASE4 | MII_100M;
- else if (neg & LPA_100HALF)
- status |= MII_HALF | MII_100M;
- else if (neg & LPA_10FULL)
- status |= MII_FULL | MII_10M;
- else
- status |= MII_HALF | MII_10M;
-
- return status;
-}
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- struct mii_if_info *mii = &fep->mii_if;
- unsigned int mii_status;
- int ok_to_print, link, duplex, speed;
- unsigned long flags;
-
- ok_to_print = netif_msg_link(fep);
-
- mii_status = mii_full_status(mii);
-
- if (!init_media && mii_status == fep->last_mii_status)
- return;
-
- fep->last_mii_status = mii_status;
-
- link = !!(mii_status & MII_LINK);
- duplex = !!(mii_status & MII_FULL);
- speed = (mii_status & MII_100M) ? 100 : 10;
-
- if (link == 0) {
- netif_carrier_off(mii->dev);
- netif_stop_queue(dev);
- if (!init_media) {
- spin_lock_irqsave(&fep->lock, flags);
- (*fep->ops->stop)(dev);
- spin_unlock_irqrestore(&fep->lock, flags);
- }
-
- if (ok_to_print)
- printk(KERN_INFO "%s: link down\n", mii->dev->name);
-
- } else {
-
- mii->full_duplex = duplex;
-
- netif_carrier_on(mii->dev);
-
- spin_lock_irqsave(&fep->lock, flags);
- fep->duplex = duplex;
- fep->speed = speed;
- (*fep->ops->restart)(dev);
- spin_unlock_irqrestore(&fep->lock, flags);
-
- netif_start_queue(dev);
-
- if (ok_to_print)
- printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
- dev->name, speed, duplex ? "full" : "half");
- }
-}
-
-/**********************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- struct fs_enet_mii_bus *bus = fep->mii_bus;
-
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&bus->mii_lock, flags);
- ret = (*bus->mii_read)(bus, phy_id, location);
- spin_unlock_irqrestore(&bus->mii_lock, flags);
-
- return ret;
-}
-
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- struct fs_enet_mii_bus *bus = fep->mii_bus;
- unsigned long flags;
-
- spin_lock_irqsave(&bus->mii_lock, flags);
- (*bus->mii_write)(bus, phy_id, location, value);
- spin_unlock_irqrestore(&bus->mii_lock, flags);
-}
-
-/*****************************************************************************/
-
-/* list of all registered mii buses */
-static LIST_HEAD(fs_mii_bus_list);
-
-static struct fs_enet_mii_bus *lookup_bus(int method, int id)
-{
- struct list_head *ptr;
- struct fs_enet_mii_bus *bus;
-
- list_for_each(ptr, &fs_mii_bus_list) {
- bus = list_entry(ptr, struct fs_enet_mii_bus, list);
- if (bus->bus_info->method == method &&
- bus->bus_info->id == id)
- return bus;
- }
- return NULL;
-}
-
-static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
-{
- struct fs_enet_mii_bus *bus;
- int ret = 0;
-
- bus = kmalloc(sizeof(*bus), GFP_KERNEL);
- if (bus == NULL) {
- ret = -ENOMEM;
- goto err;
- }
- memset(bus, 0, sizeof(*bus));
- spin_lock_init(&bus->mii_lock);
- bus->bus_info = bi;
- bus->refs = 0;
- bus->usage_map = 0;
-
- /* perform initialization */
- switch (bi->method) {
-
- case fsmii_fixed:
- ret = fs_mii_fixed_init(bus);
- if (ret != 0)
- goto err;
- break;
-
- case fsmii_bitbang:
- ret = fs_mii_bitbang_init(bus);
- if (ret != 0)
- goto err;
- break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
- case fsmii_fec:
- ret = fs_mii_fec_init(bus);
- if (ret != 0)
- goto err;
- break;
-#endif
- default:
- ret = -EINVAL;
- goto err;
- }
-
- list_add(&bus->list, &fs_mii_bus_list);
-
- return bus;
-
-err:
- kfree(bus);
- return ERR_PTR(ret);
-}
-
-static void destroy_bus(struct fs_enet_mii_bus *bus)
-{
- /* remove from bus list */
- list_del(&bus->list);
-
- /* nothing more needed */
- kfree(bus);
-}
-
-int fs_mii_connect(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
- struct fs_enet_mii_bus *bus = NULL;
-
- /* check method validity */
- switch (fpi->bus_info->method) {
- case fsmii_fixed:
- case fsmii_bitbang:
- break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
- case fsmii_fec:
- break;
-#endif
- default:
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s Unknown MII bus method (%d)!\n",
- dev->name, fpi->bus_info->method);
- return -EINVAL;
- }
-
- bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
-
- /* if not found create new bus */
- if (bus == NULL) {
- bus = create_bus(fpi->bus_info);
- if (IS_ERR(bus)) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s MII bus creation failure!\n", dev->name);
- return PTR_ERR(bus);
- }
- }
-
- bus->refs++;
-
- fep->mii_bus = bus;
-
- fep->mii_if.dev = dev;
- fep->mii_if.phy_id_mask = 0x1f;
- fep->mii_if.reg_num_mask = 0x1f;
- fep->mii_if.mdio_read = fs_mii_read;
- fep->mii_if.mdio_write = fs_mii_write;
- fep->mii_if.force_media = fpi->bus_info->disable_aneg;
- fep->mii_if.phy_id = phy_id_detect(dev);
-
- return 0;
-}
-
-void fs_mii_disconnect(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- struct fs_enet_mii_bus *bus = NULL;
-
- bus = fep->mii_bus;
- fep->mii_bus = NULL;
-
- if (--bus->refs <= 0)
- destroy_bus(bus);
-}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e7ec96c964a9..95022c005f75 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
@@ -12,12 +13,30 @@
#ifdef CONFIG_CPM1
#include
+
+struct fec_info {
+ fec_t* fecp;
+ u32 mii_speed;
+};
#endif
#ifdef CONFIG_CPM2
#include
#endif
+/* This is used to operate with pins.
+ Note that the actual port size may
+ be different; cpm(s) handle it OK */
+struct bb_info {
+ u8 mdio_dat_msk;
+ u8 mdio_dir_msk;
+ u8 *mdio_dir;
+ u8 *mdio_dat;
+ u8 mdc_msk;
+ u8 *mdc_dat;
+ int delay;
+};
+
/* hw driver ops */
struct fs_ops {
int (*setup_data)(struct net_device *dev);
@@ -25,6 +44,7 @@ struct fs_ops {
void (*free_bd)(struct net_device *dev);
void (*cleanup_data)(struct net_device *dev);
void (*set_multicast_list)(struct net_device *dev);
+ void (*adjust_link)(struct net_device *dev);
void (*restart)(struct net_device *dev);
void (*stop)(struct net_device *dev);
void (*pre_request_irq)(struct net_device *dev, int irq);
@@ -100,10 +120,6 @@ struct fs_enet_mii_bus {
};
};
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
-
struct fs_enet_private {
struct device *dev; /* pointer back to the device (must be initialized first) */
spinlock_t lock; /* during all ops except TX pckt processing */
@@ -130,7 +146,8 @@ struct fs_enet_private {
struct fs_enet_mii_bus *mii_bus;
int interrupt;
- int duplex, speed; /* current settings */
+ struct phy_device *phydev;
+ int oldduplex, oldspeed, oldlink; /* current settings */
/* event masks */
u32 ev_napi_rx; /* mask of NAPI rx events */
@@ -168,15 +185,9 @@ struct fs_enet_private {
};
/***************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location);
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
-
-void fs_mii_startup(struct net_device *dev);
-void fs_mii_shutdown(struct net_device *dev);
-void fs_mii_ack_int(struct net_device *dev);
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+int fs_enet_mdio_bb_init(void);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+int fs_enet_mdio_fec_init(void);
void fs_init_bds(struct net_device *dev);
void fs_cleanup_bds(struct net_device *dev);
@@ -194,7 +205,6 @@ int fs_enet_platform_init(void);
void fs_enet_platform_cleanup(void);
/***************************************************************************/
-
/* buffer descriptor access macros */
/* access macros */
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 64e20982c1fe..1ff2597b8495 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include
#include
@@ -122,22 +123,32 @@ static int do_pd_setup(struct fs_enet_private *fep)
/* Attach the memory for the FCC Parameter RAM */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
- fep->fcc.ep = (void *)r->start;
-
+ fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1);
if (fep->fcc.ep == NULL)
return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
- fep->fcc.fccp = (void *)r->start;
-
+ fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1);
if (fep->fcc.fccp == NULL)
return -EINVAL;
- fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+ if (fep->fpi->fcc_regs_c) {
+
+ fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+ } else {
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "fcc_regs_c");
+ fep->fcc.fcccp = (void *)ioremap(r->start,
+ r->end - r->start + 1);
+ }
if (fep->fcc.fcccp == NULL)
return -EINVAL;
+ fep->fcc.mem = (void *)fep->fpi->mem_offset;
+ if (fep->fcc.mem == NULL)
+ return -EINVAL;
+
return 0;
}
@@ -155,8 +166,6 @@ static int setup_data(struct net_device *dev)
if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
return -EINVAL;
- fep->fcc.mem = (void *)fpi->mem_offset;
-
if (do_pd_setup(fep) != 0)
return -EINVAL;
@@ -394,7 +403,7 @@ static void restart(struct net_device *dev)
/* adjust to speed (for RMII mode) */
if (fpi->use_rmii) {
- if (fep->speed == 100)
+ if (fep->phydev->speed == 100)
C8(fcccp, fcc_gfemr, 0x20);
else
S8(fcccp, fcc_gfemr, 0x20);
@@ -420,7 +429,7 @@ static void restart(struct net_device *dev)
S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
/* adjust to duplex mode */
- if (fep->duplex)
+ if (fep->phydev->duplex)
S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
else
C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
@@ -486,7 +495,10 @@ static void rx_bd_done(struct net_device *dev)
static void tx_kickstart(struct net_device *dev)
{
- /* nothing */
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ S32(fccp, fcc_ftodr, 0x80);
}
static u32 get_int_events(struct net_device *dev)
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index e09547077529..c2c5fd419bd0 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -46,6 +46,7 @@
#endif
#include "fs_enet.h"
+#include "fec.h"
/*************************************************/
@@ -75,50 +76,8 @@
/* clear bits */
#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
-
-/* CRC polynomium used by the FEC for the multicast group filtering */
-#define FEC_CRC_POLY 0x04C11DB7
-
-#define FEC_MAX_MULTICAST_ADDRS 64
-
-/* Interrupt events/masks.
-*/
-#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
-#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
-#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
-#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
-#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
-#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
-#define FEC_ENET_RXF 0x02000000U /* Full frame received */
-#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
-#define FEC_ENET_MII 0x00800000U /* MII interrupt */
-#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
-
-#define FEC_ECNTRL_PINMUX 0x00000004
-#define FEC_ECNTRL_ETHER_EN 0x00000002
-#define FEC_ECNTRL_RESET 0x00000001
-
-#define FEC_RCNTRL_BC_REJ 0x00000010
-#define FEC_RCNTRL_PROM 0x00000008
-#define FEC_RCNTRL_MII_MODE 0x00000004
-#define FEC_RCNTRL_DRT 0x00000002
-#define FEC_RCNTRL_LOOP 0x00000001
-
-#define FEC_TCNTRL_FDEN 0x00000004
-#define FEC_TCNTRL_HBC 0x00000002
-#define FEC_TCNTRL_GTS 0x00000001
-
-
-/* Make MII read/write commands for the FEC.
-*/
-#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
-#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
-#define mk_mii_end 0
-
-#define FEC_MII_LOOPS 10000
-
/*
- * Delay to wait for FEC reset command to complete (in us)
+ * Delay to wait for FEC reset command to complete (in us)
*/
#define FEC_RESET_DELAY 50
@@ -303,13 +262,15 @@ static void restart(struct net_device *dev)
int r;
u32 addrhi, addrlo;
+ struct mii_bus* mii = fep->phydev->bus;
+ struct fec_info* fec_inf = mii->priv;
+
r = whack_reset(fep->fec.fecp);
if (r != 0)
printk(KERN_ERR DRV_MODULE_NAME
": %s FEC Reset FAILED!\n", dev->name);
-
/*
- * Set station address.
+ * Set station address.
*/
addrhi = ((u32) dev->dev_addr[0] << 24) |
((u32) dev->dev_addr[1] << 16) |
@@ -350,12 +311,12 @@ static void restart(struct net_device *dev)
FW(fecp, fun_code, 0x78000000);
/*
- * Set MII speed.
+ * Set MII speed.
*/
- FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+ FW(fecp, mii_speed, fec_inf->mii_speed);
/*
- * Clear any outstanding interrupt.
+ * Clear any outstanding interrupt.
*/
FW(fecp, ievent, 0xffc0);
FW(fecp, ivec, (fep->interrupt / 2) << 29);
@@ -390,11 +351,12 @@ static void restart(struct net_device *dev)
}
#endif
+
FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
/*
- * adjust to duplex mode
+ * adjust to duplex mode
*/
- if (fep->duplex) {
+ if (fep->phydev->duplex) {
FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
} else {
@@ -418,9 +380,11 @@ static void restart(struct net_device *dev)
static void stop(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
fec_t *fecp = fep->fec.fecp;
- struct fs_enet_mii_bus *bus = fep->mii_bus;
- const struct fs_mii_bus_info *bi = bus->bus_info;
+
+ struct fec_info* feci= fep->phydev->bus->priv;
+
int i;
if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@@ -444,11 +408,11 @@ static void stop(struct net_device *dev)
fs_cleanup_bds(dev);
/* shut down FEC1? that's where the mii bus is */
- if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
+ if (fpi->has_phy) {
FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
FW(fecp, ievent, FEC_ENET_MII);
- FW(fecp, mii_speed, bus->fec.mii_speed);
+ FW(fecp, mii_speed, feci->mii_speed);
}
}
@@ -583,73 +547,3 @@ const struct fs_ops fs_fec_ops = {
.free_bd = free_bd,
};
-/***********************************************************************/
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
- fec_t *fecp = bus->fec.fecp;
- int i, ret = -1;
-
- if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
- BUG();
-
- /* Add PHY address to register command. */
- FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
-
- for (i = 0; i < FEC_MII_LOOPS; i++)
- if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
- break;
-
- if (i < FEC_MII_LOOPS) {
- FW(fecp, ievent, FEC_ENET_MII);
- ret = FR(fecp, mii_data) & 0xffff;
- }
-
- return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
-{
- fec_t *fecp = bus->fec.fecp;
- int i;
-
- /* this must never happen */
- if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
- BUG();
-
- /* Add PHY address to register command. */
- FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
-
- for (i = 0; i < FEC_MII_LOOPS; i++)
- if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
- break;
-
- if (i < FEC_MII_LOOPS)
- FW(fecp, ievent, FEC_ENET_MII);
-}
-
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
-{
- bd_t *bd = (bd_t *)__res;
- const struct fs_mii_bus_info *bi = bus->bus_info;
- fec_t *fecp;
-
- if (bi->id != 0)
- return -1;
-
- bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
- bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
- & 0x3F) << 1;
-
- fecp = bus->fec.fecp;
-
- FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
- FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
- FW(fecp, ievent, FEC_ENET_MII);
- FW(fecp, mii_speed, bus->fec.mii_speed);
-
- bus->mii_read = mii_read;
- bus->mii_write = mii_write;
-
- return 0;
-}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index eaa24fab645f..95ec5872c507 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -369,7 +369,7 @@ static void restart(struct net_device *dev)
W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
/* Set full duplex mode if needed */
- if (fep->duplex)
+ if (fep->phydev->duplex)
S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@@ -500,6 +500,8 @@ static void tx_restart(struct net_device *dev)
scc_cr_cmd(fep, CPM_CR_RESTART_TX);
}
+
+
/*************************************************************************/
const struct fs_ops fs_scc_ops = {
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 48f9cf83ab6f..0b9b8b5c847c 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
@@ -40,129 +41,25 @@
#include "fs_enet.h"
-#ifdef CONFIG_8xx
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+static int bitbang_prep_bit(u8 **datp, u8 *mskp,
+ struct fs_mii_bit *mii_bit)
{
- immap_t *im = (immap_t *)fs_enet_immap;
- void *dir, *dat, *ppar;
+ void *dat;
int adv;
u8 msk;
- switch (port) {
- case fsiop_porta:
- dir = &im->im_ioport.iop_padir;
- dat = &im->im_ioport.iop_padat;
- ppar = &im->im_ioport.iop_papar;
- break;
+ dat = (void*) mii_bit->offset;
- case fsiop_portb:
- dir = &im->im_cpm.cp_pbdir;
- dat = &im->im_cpm.cp_pbdat;
- ppar = &im->im_cpm.cp_pbpar;
- break;
-
- case fsiop_portc:
- dir = &im->im_ioport.iop_pcdir;
- dat = &im->im_ioport.iop_pcdat;
- ppar = &im->im_ioport.iop_pcpar;
- break;
-
- case fsiop_portd:
- dir = &im->im_ioport.iop_pddir;
- dat = &im->im_ioport.iop_pddat;
- ppar = &im->im_ioport.iop_pdpar;
- break;
-
- case fsiop_porte:
- dir = &im->im_cpm.cp_pedir;
- dat = &im->im_cpm.cp_pedat;
- ppar = &im->im_cpm.cp_pepar;
- break;
-
- default:
- printk(KERN_ERR DRV_MODULE_NAME
- "Illegal port value %d!\n", port);
- return -EINVAL;
- }
-
- adv = bit >> 3;
- dir = (char *)dir + adv;
+ adv = mii_bit->bit >> 3;
dat = (char *)dat + adv;
- ppar = (char *)ppar + adv;
- msk = 1 << (7 - (bit & 7));
- if ((in_8(ppar) & msk) != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "pin %d on port %d is not general purpose!\n", bit, port);
- return -EINVAL;
- }
+ msk = 1 << (7 - (mii_bit->bit & 7));
- *dirp = dir;
*datp = dat;
*mskp = msk;
return 0;
}
-#endif
-
-#ifdef CONFIG_8260
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
-{
- iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
- void *dir, *dat, *ppar;
- int adv;
- u8 msk;
-
- switch (port) {
- case fsiop_porta:
- dir = &io->iop_pdira;
- dat = &io->iop_pdata;
- ppar = &io->iop_ppara;
- break;
-
- case fsiop_portb:
- dir = &io->iop_pdirb;
- dat = &io->iop_pdatb;
- ppar = &io->iop_pparb;
- break;
-
- case fsiop_portc:
- dir = &io->iop_pdirc;
- dat = &io->iop_pdatc;
- ppar = &io->iop_pparc;
- break;
-
- case fsiop_portd:
- dir = &io->iop_pdird;
- dat = &io->iop_pdatd;
- ppar = &io->iop_ppard;
- break;
-
- default:
- printk(KERN_ERR DRV_MODULE_NAME
- "Illegal port value %d!\n", port);
- return -EINVAL;
- }
-
- adv = bit >> 3;
- dir = (char *)dir + adv;
- dat = (char *)dat + adv;
- ppar = (char *)ppar + adv;
-
- msk = 1 << (7 - (bit & 7));
- if ((in_8(ppar) & msk) != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "pin %d on port %d is not general purpose!\n", bit, port);
- return -EINVAL;
- }
-
- *dirp = dir;
- *datp = dat;
- *mskp = msk;
-
- return 0;
-}
-#endif
static inline void bb_set(u8 *p, u8 m)
{
@@ -179,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m)
return (in_8(p) & m) != 0;
}
-static inline void mdio_active(struct fs_enet_mii_bus *bus)
+static inline void mdio_active(struct bb_info *bitbang)
{
- bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+ bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
}
-static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+static inline void mdio_tristate(struct bb_info *bitbang )
{
- bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+ bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
}
-static inline int mdio_read(struct fs_enet_mii_bus *bus)
+static inline int mdio_read(struct bb_info *bitbang )
{
- return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+ return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
}
-static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+static inline void mdio(struct bb_info *bitbang , int what)
{
if (what)
- bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+ bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
else
- bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+ bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
}
-static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+static inline void mdc(struct bb_info *bitbang , int what)
{
if (what)
- bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+ bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
else
- bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+ bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
}
-static inline void mii_delay(struct fs_enet_mii_bus *bus)
+static inline void mii_delay(struct bb_info *bitbang )
{
- udelay(bus->bus_info->i.bitbang.delay);
+ udelay(bitbang->delay);
}
/* Utility to send the preamble, address, and register (common to read and write). */
-static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
+static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
{
int j;
@@ -228,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
* but it is safer and will be much more robust.
*/
- mdio_active(bus);
- mdio(bus, 1);
+ mdio_active(bitbang);
+ mdio(bitbang, 1);
for (j = 0; j < 32; j++) {
- mdc(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
}
/* send the start bit (01) and the read opcode (10) or write (10) */
- mdc(bus, 0);
- mdio(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
- mdc(bus, 0);
- mdio(bus, 1);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
- mdc(bus, 0);
- mdio(bus, read);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
- mdc(bus, 0);
- mdio(bus, !read);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 0);
+ mdio(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 0);
+ mdio(bitbang, read);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 0);
+ mdio(bitbang, !read);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
/* send the PHY address */
for (j = 0; j < 5; j++) {
- mdc(bus, 0);
- mdio(bus, (addr & 0x10) != 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio(bitbang, (addr & 0x10) != 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
addr <<= 1;
}
/* send the register address */
for (j = 0; j < 5; j++) {
- mdc(bus, 0);
- mdio(bus, (reg & 0x10) != 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio(bitbang, (reg & 0x10) != 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
reg <<= 1;
}
}
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
{
u16 rdreg;
int ret, j;
u8 addr = phy_id & 0xff;
u8 reg = location & 0xff;
+ struct bb_info* bitbang = bus->priv;
- bitbang_pre(bus, 1, addr, reg);
+ bitbang_pre(bitbang, 1, addr, reg);
/* tri-state our MDIO I/O pin so we can read */
- mdc(bus, 0);
- mdio_tristate(bus);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio_tristate(bitbang);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
/* check the turnaround bit: the PHY should be driving it to zero */
- if (mdio_read(bus) != 0) {
+ if (mdio_read(bitbang) != 0) {
/* PHY didn't drive TA low */
for (j = 0; j < 32; j++) {
- mdc(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
}
ret = -1;
goto out;
}
- mdc(bus, 0);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
/* read 16 bits of register data, MSB first */
rdreg = 0;
for (j = 0; j < 16; j++) {
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
rdreg <<= 1;
- rdreg |= mdio_read(bus);
- mdc(bus, 0);
- mii_delay(bus);
+ rdreg |= mdio_read(bitbang);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
}
- mdc(bus, 1);
- mii_delay(bus);
- mdc(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
ret = rdreg;
out:
return ret;
}
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{
int j;
+ struct bb_info* bitbang = bus->priv;
+
u8 addr = phy_id & 0xff;
u8 reg = location & 0xff;
u16 value = val & 0xffff;
- bitbang_pre(bus, 0, addr, reg);
+ bitbang_pre(bitbang, 0, addr, reg);
/* send the turnaround (10) */
- mdc(bus, 0);
- mdio(bus, 1);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
- mdc(bus, 0);
- mdio(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ mdc(bitbang, 0);
+ mdio(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
/* write 16 bits of register data, MSB first */
for (j = 0; j < 16; j++) {
- mdc(bus, 0);
- mdio(bus, (value & 0x8000) != 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdc(bitbang, 0);
+ mdio(bitbang, (value & 0x8000) != 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
value <<= 1;
}
/*
* Tri-state the MDIO line.
*/
- mdio_tristate(bus);
- mdc(bus, 0);
- mii_delay(bus);
- mdc(bus, 1);
- mii_delay(bus);
+ mdio_tristate(bitbang);
+ mdc(bitbang, 0);
+ mii_delay(bitbang);
+ mdc(bitbang, 1);
+ mii_delay(bitbang);
+ return 0;
}
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+static int fs_enet_mii_bb_reset(struct mii_bus *bus)
+{
+ /*nothing here - dunno how to reset it*/
+ return 0;
+}
+
+static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
{
- const struct fs_mii_bus_info *bi = bus->bus_info;
int r;
- r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
- &bus->bitbang.mdio_dat,
- &bus->bitbang.mdio_msk,
- bi->i.bitbang.mdio_port,
- bi->i.bitbang.mdio_bit);
+ bitbang->delay = fmpi->delay;
+
+ r = bitbang_prep_bit(&bitbang->mdio_dir,
+ &bitbang->mdio_dir_msk,
+ &fmpi->mdio_dir);
if (r != 0)
return r;
- r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
- &bus->bitbang.mdc_dat,
- &bus->bitbang.mdc_msk,
- bi->i.bitbang.mdc_port,
- bi->i.bitbang.mdc_bit);
+ r = bitbang_prep_bit(&bitbang->mdio_dat,
+ &bitbang->mdio_dat_msk,
+ &fmpi->mdio_dat);
if (r != 0)
return r;
- bus->mii_read = mii_read;
- bus->mii_write = mii_write;
+ r = bitbang_prep_bit(&bitbang->mdc_dat,
+ &bitbang->mdc_msk,
+ &fmpi->mdc_dat);
+ if (r != 0)
+ return r;
return 0;
}
+
+
+static int __devinit fs_enet_mdio_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_mii_bb_platform_info *pdata;
+ struct mii_bus *new_bus;
+ struct bb_info *bitbang;
+ int err = 0;
+
+ if (NULL == dev)
+ return -EINVAL;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus)
+ return -ENOMEM;
+
+ bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+
+ if (NULL == bitbang)
+ return -ENOMEM;
+
+ new_bus->name = "BB MII Bus",
+ new_bus->read = &fs_enet_mii_bb_read,
+ new_bus->write = &fs_enet_mii_bb_write,
+ new_bus->reset = &fs_enet_mii_bb_reset,
+ new_bus->id = pdev->id;
+
+ new_bus->phy_mask = ~0x9;
+ pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
+
+ if (NULL == pdata) {
+ printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+ return -ENODEV;
+ }
+
+ /*set up workspace*/
+ fs_mii_bitbang_init(bitbang, pdata);
+
+ new_bus->priv = bitbang;
+
+ new_bus->irq = pdata->irq;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+ new_bus->name);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ kfree(bitbang);
+ kfree(new_bus);
+
+ return err;
+}
+
+
+static int fs_enet_mdio_remove(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(dev, NULL);
+
+ iounmap((void *) (&bus->priv));
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct device_driver fs_enet_bb_mdio_driver = {
+ .name = "fsl-bb-mdio",
+ .bus = &platform_bus_type,
+ .probe = fs_enet_mdio_probe,
+ .remove = fs_enet_mdio_remove,
+};
+
+int fs_enet_mdio_bb_init(void)
+{
+ return driver_register(&fs_enet_bb_mdio_driver);
+}
+
+void fs_enet_mdio_bb_exit(void)
+{
+ driver_unregister(&fs_enet_bb_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
new file mode 100644
index 000000000000..1328e10caa35
--- /dev/null
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -0,0 +1,243 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "fs_enet.h"
+#include "fec.h"
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end 0
+
+#define FEC_MII_LOOPS 10000
+
+static int match_has_phy (struct device *dev, void* data)
+{
+ struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+ struct fs_platform_info* fpi;
+ if(strcmp(pdev->name, (char*)data))
+ {
+ return 0;
+ }
+
+ fpi = pdev->dev.platform_data;
+ if((fpi)&&(fpi->has_phy))
+ return 1;
+ return 0;
+}
+
+static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
+{
+ struct resource *r;
+ fec_t *fecp;
+ char* name = "fsl-cpm-fec";
+
+ /* we need fec in order to be useful */
+ struct platform_device *fec_pdev =
+ container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
+ struct platform_device, dev);
+
+ if(fec_pdev == NULL) {
+ printk(KERN_ERR"Unable to find PHY for %s", name);
+ return -ENODEV;
+ }
+
+ r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
+
+ fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t));
+ fec->mii_speed = fmpi->mii_speed;
+
+ setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+ out_be32(&fecp->fec_mii_speed, fec->mii_speed);
+
+ return 0;
+}
+
+static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
+{
+ struct fec_info* fec = bus->priv;
+ fec_t *fecp = fec->fecp;
+ int i, ret = -1;
+
+ if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+ BUG();
+
+ /* Add PHY address to register command. */
+ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS) {
+ out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+ ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+ }
+
+ return ret;
+
+}
+
+static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+ struct fec_info* fec = bus->priv;
+ fec_t *fecp = fec->fecp;
+ int i;
+
+ /* this must never happen */
+ if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+ BUG();
+
+ /* Add PHY address to register command. */
+ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS)
+ out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+
+ return 0;
+
+}
+
+static int fs_enet_fec_mii_reset(struct mii_bus *bus)
+{
+ /* nothing here - for now */
+ return 0;
+}
+
+static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_mii_fec_platform_info *pdata;
+ struct mii_bus *new_bus;
+ struct fec_info *fec;
+ int err = 0;
+ if (NULL == dev)
+ return -EINVAL;
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus)
+ return -ENOMEM;
+
+ fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+
+ if (NULL == fec)
+ return -ENOMEM;
+
+ new_bus->name = "FEC MII Bus",
+ new_bus->read = &fs_enet_fec_mii_read,
+ new_bus->write = &fs_enet_fec_mii_write,
+ new_bus->reset = &fs_enet_fec_mii_reset,
+ new_bus->id = pdev->id;
+
+ pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+
+ if (NULL == pdata) {
+ printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
+ return -ENODEV;
+ }
+
+ /*set up workspace*/
+
+ fs_mii_fec_init(fec, pdata);
+ new_bus->priv = fec;
+
+ new_bus->irq = pdata->irq;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+ new_bus->name);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+static int fs_enet_fec_mdio_remove(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(dev, NULL);
+ kfree(bus->priv);
+
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct device_driver fs_enet_fec_mdio_driver = {
+ .name = "fsl-cpm-fec-mdio",
+ .bus = &platform_bus_type,
+ .probe = fs_enet_fec_mdio_probe,
+ .remove = fs_enet_fec_mdio_remove,
+};
+
+int fs_enet_mdio_fec_init(void)
+{
+ return driver_register(&fs_enet_fec_mdio_driver);
+}
+
+void fs_enet_mdio_fec_exit(void)
+{
+ driver_unregister(&fs_enet_fec_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c
deleted file mode 100644
index ae4a9c3bb393..000000000000
--- a/drivers/net/fs_enet/mii-fixed.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A.
- * by Pantelis Antoniou
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include "fs_enet.h"
-
-static const u16 mii_regs[7] = {
- 0x3100,
- 0x786d,
- 0x0fff,
- 0x0fff,
- 0x01e1,
- 0x45e1,
- 0x0003,
-};
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
- int ret = 0;
-
- if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
- return -1;
-
- if (location != 5)
- ret = mii_regs[location];
- else
- ret = bus->fixed.lpa;
-
- return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
-{
- /* do nothing */
-}
-
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
-{
- const struct fs_mii_bus_info *bi = bus->bus_info;
-
- bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */
-
- /* if speed is fixed at 10Mb, remove 100Mb modes */
- if (bi->i.fixed.speed == 10)
- bus->fixed.lpa &= ~LPA_100;
-
- /* if duplex is half, remove full duplex modes */
- if (bi->i.fixed.duplex == 0)
- bus->fixed.lpa &= ~LPA_DUPLEX;
-
- bus->mii_read = mii_read;
- bus->mii_write = mii_write;
-
- return 0;
-}
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index c1c3452c90ca..5b4dbfe5fb77 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -326,7 +326,7 @@ MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)");
MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)");
MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)");
-int init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 646e89fc3562..c0ec7f6abcb2 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -406,7 +406,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
MODULE_LICENSE("GPL");
-int init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 07ca9480a6fe..9bdd43ab3573 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -177,6 +177,7 @@ struct myri10ge_priv {
struct work_struct watchdog_work;
struct timer_list watchdog_timer;
int watchdog_tx_done;
+ int watchdog_tx_req;
int watchdog_resets;
int tx_linearized;
int pause;
@@ -448,6 +449,7 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
struct mcp_gen_header *hdr;
size_t hdr_offset;
int status;
+ unsigned i;
if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
dev_err(dev, "Unable to load %s firmware image via hotplug\n",
@@ -479,18 +481,12 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
goto abort_with_fw;
crc = crc32(~0, fw->data, fw->size);
- if (mgp->tx.boundary == 2048) {
- /* Avoid PCI burst on chipset with unaligned completions. */
- int i;
- __iomem u32 *ptr = (__iomem u32 *) (mgp->sram +
- MYRI10GE_FW_OFFSET);
- for (i = 0; i < fw->size / 4; i++) {
- __raw_writel(((u32 *) fw->data)[i], ptr + i);
- wmb();
- }
- } else {
- myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data,
- fw->size);
+ for (i = 0; i < fw->size; i += 256) {
+ myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i,
+ fw->data + i,
+ min(256U, (unsigned)(fw->size - i)));
+ mb();
+ readb(mgp->sram);
}
/* corruption checking is good for parity recovery and buggy chipset */
memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
@@ -620,7 +616,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
return -ENXIO;
}
dev_info(&mgp->pdev->dev, "handoff confirmed\n");
- myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+ myri10ge_dummy_rdma(mgp, 1);
return 0;
}
@@ -2429,7 +2425,7 @@ static int myri10ge_resume(struct pci_dev *pdev)
}
myri10ge_reset(mgp);
- myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+ myri10ge_dummy_rdma(mgp, 1);
/* Save configuration space to be restored if the
* nic resets due to a parity error */
@@ -2547,7 +2543,8 @@ static void myri10ge_watchdog_timer(unsigned long arg)
mgp = (struct myri10ge_priv *)arg;
if (mgp->tx.req != mgp->tx.done &&
- mgp->tx.done == mgp->watchdog_tx_done)
+ mgp->tx.done == mgp->watchdog_tx_done &&
+ mgp->watchdog_tx_req != mgp->watchdog_tx_done)
/* nic seems like it might be stuck.. */
schedule_work(&mgp->watchdog_work);
else
@@ -2556,6 +2553,7 @@ static void myri10ge_watchdog_timer(unsigned long arg)
jiffies + myri10ge_watchdog_timeout * HZ);
mgp->watchdog_tx_done = mgp->tx.done;
+ mgp->watchdog_tx_req = mgp->tx.req;
}
static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index fa854c8fde75..4d52ecf8af56 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -1323,7 +1323,7 @@ MODULE_PARM_DESC(irq, "NI5210 IRQ number,required");
MODULE_PARM_DESC(memstart, "NI5210 memory base address,required");
MODULE_PARM_DESC(memend, "NI5210 memory end address,required");
-int init_module(void)
+int __init init_module(void)
{
if(io <= 0x0 || !memend || !memstart || irq < 2) {
printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n");
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index bb42ff218484..810cc572f5f7 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1253,7 +1253,7 @@ MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)");
MODULE_PARM_DESC(io, "ni6510 I/O base address");
MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
-int init_module(void)
+int __init init_module(void)
{
dev_ni65 = ni65_probe(-1);
return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 9bae77ce1314..4122bb46f5ff 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -345,6 +345,7 @@ typedef struct local_info_t {
void __iomem *dingo_ccr; /* only used for CEM56 cards */
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
+ struct work_struct tx_timeout_task;
} local_info_t;
/****************
@@ -352,6 +353,7 @@ typedef struct local_info_t {
*/
static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void do_tx_timeout(struct net_device *dev);
+static void xirc2ps_tx_timeout_task(void *data);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -589,6 +591,7 @@ xirc2ps_probe(struct pcmcia_device *link)
#ifdef HAVE_TX_TIMEOUT
dev->tx_timeout = do_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
#endif
return xirc2ps_config(link);
@@ -1341,17 +1344,24 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*====================================================================*/
static void
-do_tx_timeout(struct net_device *dev)
+xirc2ps_tx_timeout_task(void *data)
{
- local_info_t *lp = netdev_priv(dev);
- printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
- lp->stats.tx_errors++;
+ struct net_device *dev = data;
/* reset the card */
do_reset(dev,1);
dev->trans_start = jiffies;
netif_wake_queue(dev);
}
+static void
+do_tx_timeout(struct net_device *dev)
+{
+ local_info_t *lp = netdev_priv(dev);
+ lp->stats.tx_errors++;
+ printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+ schedule_work(&lp->tx_timeout_task);
+}
+
static int
do_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 4daafe303358..d50bcb89dd28 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
#define CSR15 15
#define PCNET32_MC_FILTER 8
+#define PCNET32_79C970A 0x2621
+
/* The PCNET32 Rx and Tx ring descriptors. */
struct pcnet32_rx_head {
u32 base;
@@ -289,6 +291,7 @@ struct pcnet32_private {
/* each bit indicates an available PHY */
u32 phymask;
+ unsigned short chip_version; /* which variant this is */
};
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
if (lp->mii) {
r = mii_link_ok(&lp->mii_if);
- } else {
+ } else if (lp->chip_version >= PCNET32_79C970A) {
ulong ioaddr = dev->base_addr; /* card base I/O address */
r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+ } else { /* can not detect link on really old chips */
+ r = 1;
}
spin_unlock_irqrestore(&lp->lock, flags);
@@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
ulong ioaddr = dev->base_addr;
int ticks;
+ /* really old chips have to be stopped. */
+ if (lp->chip_version < PCNET32_79C970A)
+ return 0;
+
/* set SUSPEND (SPND) - CSR5 bit 0 */
csr5 = a->read_csr(ioaddr, CSR5);
a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp->mii_if.reg_num_mask = 0x1f;
lp->dxsuflo = dxsuflo;
lp->mii = mii;
+ lp->chip_version = chip_version;
lp->msg_enable = pcnet32_debug;
if ((cards_found >= MAX_UNITS)
|| (options[cards_found] > sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_device *dev)
val |= 2;
} else if (lp->options & PCNET32_PORT_ASEL) {
/* workaround of xSeries250, turn on for 79C975 only */
- i = ((lp->a.read_csr(ioaddr, 88) |
- (lp->a.
- read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
- if (i == 0x2627)
+ if (lp->chip_version == 0x2627)
val |= 3;
}
lp->a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_device *dev)
netif_start_queue(dev);
- /* Print the link status and start the watchdog */
- pcnet32_check_media(dev, 1);
- mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+ if (lp->chip_version >= PCNET32_79C970A) {
+ /* Print the link status and start the watchdog */
+ pcnet32_check_media(dev, 1);
+ mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+ }
i = 0;
while (i++ < 100)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 2ba6d3a40e2e..b79ec0d7480f 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,5 +56,22 @@ config SMSC_PHY
---help---
Currently supports the LAN83C185 PHY
+config FIXED_PHY
+ tristate "Drivers for PHY emulation on fixed speed/link"
+ depends on PHYLIB
+ ---help---
+ Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
+ but with the ability to manipulate with speed/link in software. The relavant MII
+ speed/duplex parameters could be effectively handled in user-specified fuction.
+ Currently tested with mpc866ads.
+
+config FIXED_MII_10_FDX
+ bool "Emulation for 10M Fdx fixed PHY behavior"
+ depends on FIXED_PHY
+
+config FIXED_MII_100_FDX
+ bool "Emulation for 100M Fdx fixed PHY behavior"
+ depends on FIXED_PHY
+
endmenu
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a00e61942525..320f8323123f 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
+obj-$(CONFIG_FIXED_PHY) += fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644
index 000000000000..341036df4710
--- /dev/null
+++ b/drivers/net/phy/fixed.c
@@ -0,0 +1,358 @@
+/*
+ * drivers/net/phy/fixed.c
+ *
+ * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
+ *
+ * Author: Vitaly Bordug
+ *
+ * Copyright (c) 2006 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.
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#define MII_REGS_NUM 7
+
+/*
+ The idea is to emulate normal phy behavior by responding with
+ pre-defined values to mii BMCR read, so that read_status hook could
+ take all the needed info.
+*/
+
+struct fixed_phy_status {
+ u8 link;
+ u16 speed;
+ u8 duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ * Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+ u16 *regs;
+ u8 regs_num;
+ struct fixed_phy_status phy_status;
+ struct phy_device *phydev; /* pointer to the container */
+ /* link & speed cb */
+ int(*link_update)(struct net_device*, struct fixed_phy_status*);
+
+};
+
+/*-----------------------------------------------------------------------------
+ * If something weird is required to be done with link/speed,
+ * network driver is able to assign a function to implement this.
+ * May be useful for PHY's that need to be software-driven.
+ *-----------------------------------------------------------------------------*/
+int fixed_mdio_set_link_update(struct phy_device* phydev,
+ int(*link_update)(struct net_device*, struct fixed_phy_status*))
+{
+ struct fixed_info *fixed;
+
+ if(link_update == NULL)
+ return -EINVAL;
+
+ if(phydev) {
+ if(phydev->bus) {
+ fixed = phydev->bus->priv;
+ fixed->link_update = link_update;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(fixed_mdio_set_link_update);
+
+/*-----------------------------------------------------------------------------
+ * This is used for updating internal mii regs from the status
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_update_regs(struct fixed_info *fixed)
+{
+ u16 *regs = fixed->regs;
+ u16 bmsr = 0;
+ u16 bmcr = 0;
+
+ if(!regs) {
+ printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if(fixed->phy_status.link)
+ bmsr |= BMSR_LSTATUS;
+
+ if(fixed->phy_status.duplex) {
+ bmcr |= BMCR_FULLDPLX;
+
+ switch ( fixed->phy_status.speed ) {
+ case 100:
+ bmsr |= BMSR_100FULL;
+ bmcr |= BMCR_SPEED100;
+ break;
+
+ case 10:
+ bmsr |= BMSR_10FULL;
+ break;
+ }
+ } else {
+ switch ( fixed->phy_status.speed ) {
+ case 100:
+ bmsr |= BMSR_100HALF;
+ bmcr |= BMCR_SPEED100;
+ break;
+
+ case 10:
+ bmsr |= BMSR_100HALF;
+ break;
+ }
+ }
+
+ regs[MII_BMCR] = bmcr;
+ regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/
+
+ return 0;
+}
+
+static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
+{
+ struct fixed_info *fixed = bus->priv;
+
+ /* if user has registered link update callback, use it */
+ if(fixed->phydev)
+ if(fixed->phydev->attached_dev) {
+ if(fixed->link_update) {
+ fixed->link_update(fixed->phydev->attached_dev,
+ &fixed->phy_status);
+ fixed_mdio_update_regs(fixed);
+ }
+ }
+
+ if ((unsigned int)location >= fixed->regs_num)
+ return -1;
+ return fixed->regs[location];
+}
+
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+ /* do nothing for now*/
+ return 0;
+}
+
+static int fixed_mii_reset(struct mii_bus *bus)
+{
+ /*nothing here - no way/need to reset it*/
+ return 0;
+}
+
+static int fixed_config_aneg(struct phy_device *phydev)
+{
+ /* :TODO:03/13/2006 09:45:37 PM::
+ The full autoneg funcionality can be emulated,
+ but no need to have anything here for now
+ */
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * the manual bind will do the magic - with phy_id_mask == 0
+ * match will never return true...
+ *-----------------------------------------------------------------------------*/
+static struct phy_driver fixed_mdio_driver = {
+ .name = "Fixed PHY",
+ .features = PHY_BASIC_FEATURES,
+ .config_aneg = fixed_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+/*-----------------------------------------------------------------------------
+ * This func is used to create all the necessary stuff, bind
+ * the fixed phy driver and register all it on the mdio_bus_type.
+ * speed is either 10 or 100, duplex is boolean.
+ * number is used to create multiple fixed PHYs, so that several devices can
+ * utilize them simultaneously.
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_register_device(int number, int speed, int duplex)
+{
+ struct mii_bus *new_bus;
+ struct fixed_info *fixed;
+ struct phy_device *phydev;
+ int err = 0;
+
+ struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+
+ if (NULL == dev)
+ return -ENOMEM;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus) {
+ kfree(dev);
+ return -ENOMEM;
+ }
+ fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
+
+ if (NULL == fixed) {
+ kfree(dev);
+ kfree(new_bus);
+ return -ENOMEM;
+ }
+
+ fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
+ fixed->regs_num = MII_REGS_NUM;
+ fixed->phy_status.speed = speed;
+ fixed->phy_status.duplex = duplex;
+ fixed->phy_status.link = 1;
+
+ new_bus->name = "Fixed MII Bus",
+ new_bus->read = &fixed_mii_read,
+ new_bus->write = &fixed_mii_write,
+ new_bus->reset = &fixed_mii_reset,
+
+ /*set up workspace*/
+ fixed_mdio_update_regs(fixed);
+ new_bus->priv = fixed;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ /* create phy_device and register it on the mdio bus */
+ phydev = phy_device_create(new_bus, 0, 0);
+
+ /*
+ Put the phydev pointer into the fixed pack so that bus read/write code could
+ be able to access for instance attached netdev. Well it doesn't have to do
+ so, only in case of utilizing user-specified link-update...
+ */
+ fixed->phydev = phydev;
+
+ if(NULL == phydev) {
+ err = -ENOMEM;
+ goto device_create_fail;
+ }
+
+ phydev->irq = -1;
+ phydev->dev.bus = &mdio_bus_type;
+
+ if(number)
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+ "fixed_%d@%d:%d", number, speed, duplex);
+ else
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+ "fixed@%d:%d", speed, duplex);
+ phydev->bus = new_bus;
+
+ err = device_register(&phydev->dev);
+ if(err) {
+ printk(KERN_ERR "Phy %s failed to register\n",
+ phydev->dev.bus_id);
+ goto bus_register_fail;
+ }
+
+ /*
+ the mdio bus has phy_id match... In order not to do it
+ artificially, we are binding the driver here by hand;
+ it will be the same for all the fixed phys anyway.
+ */
+ down_write(&phydev->dev.bus->subsys.rwsem);
+
+ phydev->dev.driver = &fixed_mdio_driver.driver;
+
+ err = phydev->dev.driver->probe(&phydev->dev);
+ if(err < 0) {
+ printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
+ up_write(&phydev->dev.bus->subsys.rwsem);
+ goto probe_fail;
+ }
+
+ device_bind_driver(&phydev->dev);
+ up_write(&phydev->dev.bus->subsys.rwsem);
+
+ return 0;
+
+probe_fail:
+ device_unregister(&phydev->dev);
+bus_register_fail:
+ kfree(phydev);
+device_create_fail:
+ kfree(dev);
+ kfree(new_bus);
+ kfree(fixed);
+
+ return err;
+}
+
+
+MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
+MODULE_AUTHOR("Vitaly Bordug");
+MODULE_LICENSE("GPL");
+
+static int __init fixed_init(void)
+{
+ int ret;
+ int duplex = 0;
+
+ /* register on the bus... Not expected to be matched with anything there... */
+ phy_driver_register(&fixed_mdio_driver);
+
+ /* So let the fun begin...
+ We will create several mdio devices here, and will bound the upper
+ driver to them.
+
+ Then the external software can lookup the phy bus by searching
+ fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
+ virtual 100M Fdx phy.
+
+ In case several virtual PHYs required, the bus_id will be in form
+ fixed_@